Hello everyone, in this article, we return to the custom View in Android. In fact, we have been working on Flutter recently. The initial idea is to encapsulate the basic components of Flutter first, and then continue with various tools, lists, and networks. , Do it all from the shallower to the deeper. After finishing Flutter, gradually update the technical points in Android. Looking back, let’s intersperse it. The system planning will inevitably change. Write whatever you think of. Just be able to hold on to the output.
Today’s knowledge point is a custom View, the abbreviated keyboard of a province, which is mainly used in places such as license plate input, which is relatively simple. Let’s first look at the final implementation effect:
There are many ways to implement it, and I believe everyone has their own set of implementation mechanisms. Here, I use the combination View and LinearLayout.
Today’s content is roughly as follows:
1. Analyze UI, how to layout
2. Set attributes and develop scalable effects
3. Partial source code analysis
4. Open source address and practical summary
1. Analyze UI, how to layout
After getting the UI renderings, there is actually nothing to analyze. It is nothing more than two pieces, the completion button on the top and the province abbreviation grid at the bottom. At the beginning, I planned to use the RecyclerView grid layout to realize it, but how to place the delete button at the end It became a problem. It is obviously not suitable to directly float on the grid and dynamically calculate the position, and there is no such way to do it. Simply abandon this solution and choose the simplest LinearLayout combined View form.
The so-called simplicity is to continuously add sub-Views to the LinearLayout during the traversal of the province abbreviation array. It should be noted that the own View, that is, our custom View, after inheriting the LinearLayout, defaults to the vertical direction. What the View adds is a LinearLayout with a horizontal attribute, which is also the effect of line breaks, that is, a horizontal LinearLayout per line. Remember, the LinearLayout with a horizontal attribute is the direct parent class that finally adds the View.
The condition of line break is based on the UI effect. When the length is set equal to 0, we will recreate a horizontal LinearLayout. This is all right, isn’t it very simple.
As for the last delete button, make it to the right and occupy the weight settings of two grids.
2. Set attributes to develop scalable effects
After we draw this identity keyboard for short, it must be used by others. Based on flexible and changeable requirements, we also need to configure it dynamically, such as background color, text color, size, and border. distance, and click effects, etc., all of which need to be exposed for users to use selectively. At present, all the attributes are as follows, and you can also set them accordingly when using them.
Attributes |
type |
overview |
lp_background |
color |
overall background color |
lp_rect_spacing |
dimension |
grid margins |
lp_rect_height |
dimension |
grid height |
lp_rect_margin_top |
dimension |
grid distance top |
lp_margin_left_right |
dimension |
left and right distance |
lp_margin_top |
dimension |
top distance |
lp_margin_bottom |
dimension |
Bottom distance |
lp_rect_background |
reference |
plaid background |
lp_rect_select_background |
reference |
Background after grid selection |
lp_rect_text_size |
dimension |
grid text size |
lp_rect_text_color |
color |
grid text color |
lp_rect_select_text_color |
color |
grid text selection color |
lp_is_show_complete |
boolean |
Whether to show the done button |
lp_complete_text_size |
dimension |
Done button text size |
lp_complete_text_color |
color |
Done button text color |
lp_complete_text |
string |
Done button text content |
lp_complete_margin_top |
dimension |
Done button distance top |
lp_complete_margin_bottom |
dimension |
Done button distance below |
lp_complete_margin_right |
dimension |
Done button distance to the right |
lp_text_click_effect |
boolean |
Whether to trigger the click effect, if true, the background disappears after clicking, and if false, it does not disappear |
3. Key source code analysis
Only part of the key code is posted here, and the overall code, you can slide to the bottom to view the source code address.
Define an array of identity abbreviations
//Province abbreviation data private val mLicensePlateList = arrayListOf( "Beijing", "Tianjin", "Chongqing", "Shanghai", "Ji", "Jin", "Liao", "Ji", "Black", "Su", "Zhe", "Anhui", "Min", "Jiangxi", "Lu", "Yu", "E", "Xiang", "Yue", "Qiong", "Sichuan", "Gui", "Cloud", "Shaanxi", "Gan", "Qing", "Mongol", "Gui", "Ning", "Xin", "Tibet", "Shi", "Ling", "Study", "Hong Kong", "Macao", )
Traverse province abbreviations
mLength shows how many in one line. When the modulus is 0, it needs to wrap the line, that is, create a horizontal LinearLayout again and add it to the outer vertical LinearLayout. In each horizontal LinearLayout, there are TextViews one by one.
//The province abbreviation corresponding to each line var layout: LinearLayout? = null // Loop through license plate numbers mLicensePlateList.forEachIndexed { index, s -> if (index % mLength == 0) { //Recreate and add View layout = createLinearLayout() layout?.weightSum = 1f addView(layout) val params = layout?.layoutParams as LayoutParams params. apply { topMargin = mRectMarginTop.toInt() height = mRectHeight.toInt() leftMargin = mMarginLeftRight.toInt() rightMargin = mMarginLeftRight.toInt() - mSpacing.toInt() layout?.layoutParams = this } } //Create text view val textView = TextView(context).apply { text = s //Set the properties of the text textSize = px2sp(mRectTextSize) //whether the last five are forbidden if (mNumProhibit & amp; & amp; index > (mLicensePlateList. size - 6)) { setTextColor(mNumProhibitColor) mTempTextViewList. add(this) } else { setTextColor(mRectTextColor) } setBackgroundResource(mRectBackGround) gravity = Gravity.CENTER setOnClickListener { if (mNumProhibit & amp; & amp; index > (mLicensePlateList. size - 6)) { return @setOnClickListener } //Click event for each grid changeTextViewState(this) } } addRectView(textView, layout, 0.1f) }
Append the last View
Since the last view is a picture and occupies the size of two grids, it needs special treatment. What needs to be done is to set the weight and width separately, as shown below:
/** * AUTHOR:AbnerMing * INTRODUCE: Append the last View */ private fun addEndView(layout: LinearLayout?) { val endViewLayout = LinearLayout(context) endViewLayout.gravity = Gravity.RIGHT //delete button val endView = RelativeLayout(context) //add delete button val deleteImage = ImageView(context) deleteImage.setImageResource(R.drawable.view_ic_key_delete) endView. addView(deleteImage) val imageParams = deleteImage.layoutParams as RelativeLayout.LayoutParams imageParams.addRule(RelativeLayout.CENTER_IN_PARENT) deleteImage.layoutParams = imageParams endView. setOnClickListener { //delete mKeyboardDelete?.invoke() invalidate() } endView.setBackgroundResource(mRectBackGround) endViewLayout. addView(endView) val params = endView.layoutParams as LayoutParams params.width = (getScreenWidth() / mLength) * 2 - mMarginLeftRight.toInt() params.height = LayoutParams.MATCH_PARENT endView.layoutParams = params layout?.addView(endViewLayout) val endParams = endViewLayout.layoutParams as LayoutParams endParams. apply { width = (mSpacing * 3).toInt() height = LayoutParams.MATCH_PARENT weight = 0.4f rightMargin = mSpacing. toInt() endViewLayout.layoutParams = this } }
4. Summary of open source addresses and usage
Open source address: https://github.com/AbnerMing888/LicensePlateView
Regarding the use, it is actually a class. You can download the source code, copy it directly and use it. You can also modify the code inside. It is very convenient. If you are too lazy to download the source code, it doesn’t matter. I also uploaded it to the remote Maven. You can follow the steps below way to use.
Maven specific call
1. Under the build.gradle file under your root project, import maven.
allprojects { repositories { maven { url "https://gitee.com/AbnerAndroid/almighty/raw/master" } } }
2. Under the build.gradle file in the Module you need to use, introduce dependencies.
dependencies { implementation 'com.vip:plate:1.0.0' }
Code usage
<com.vip.plate.LicensePlateView android:id="@ + id/lp_view" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:lp_complete_text_size="14sp" app:lp_margin_left_right="10dp" app:lp_rect_spacing="6dp" app:lp_rect_text_size="19sp" app:lp_text_click_effect="false" />
Summary
When you use it, you must use it selectively according to the attribute table; about this province, it is referred to as custom View, and there are many ways to implement it. My current way is not the best way to achieve it, but it is just an implementation plan for me. Let’s use it as a basis for reference. Well, friends, this article will end here first, and I hope it can help everyone.