我正在参加「启航计划」
hello啊各位老铁,这篇文章咱们从头回到Android傍边的自界说View,其实最近一直在搞Flutter,开始主意是,把Flutter傍边的基础组件先封装一遍,然后接着各个东西类,列表,网络,通通由浅入深的搞一遍,弄完Flutter之后,再逐步的更新Android傍边的技术点,回头一想,仍是穿插着来吧,再系统的规划,难免也有改变,想到啥就写啥吧,能够坚持输出就行。
今日的这个知识点,是一个自界说View,一个省份的简称键盘,主要用到的当地,比方车牌输入等当地,相对来说仍是比较的简略,咱们先看下终究的完结作用:

完结办法呢有很多种,我相信我们也有自己的一套完结机制,这儿,我采用的是组合View,用的是LinearLayout的办法。
今日的内容大致如下:
1、分析UI,怎么布局
2、设置特点和办法,拟定可扩展作用
3、部分源码分析
4、开源地址及有用总结
一、分析UI,怎么布局
拿到UI作用图后,其实也没什么好分析的,无非便是两块,顶部的完结按钮和底部的省份简称格子,一开始,打算用RecyclerView网格布局来完结,但是最终的删去按钮怎么摆放就成了问题,直接悬浮在网格上边,动态核算方位,明显不太适宜,也没有这样去搞的,索性直接扔掉这个方案,多布局的主意也实验过,但终究仍是挑选了最简略的LinearLayout组合View形式。
所谓简略,便是在省份简称数组的遍历中,不断的给LinearLayout进行追加子View,需求注意的是,本身的View,也便是咱们自界说View,继承LinearLayout后,默认的是笔直方向的,往本身View追加的是横向特点的LinearLayout,这也是换行的作用,也便是,一行一个横向的LinearLayout,记住,横向特点的LinearLayout,才是终究增加View的直接父类。

换行的条件便是根据UI作用,当模于设置length等于0时,咱们就从头创立一个水平的LinearLayout,这就能够了,是不是十分的简略。
至于最终的删去按钮,使其靠右,占有两个格子的权重设置即可。
二、设置特点和办法,拟定可扩展作用
当咱们绘制完这个身份简称键盘后,肯定是要给别人用的,根据灵敏多变的需求,那么相对应的咱们也需求动态的进行装备,比方布景色彩,文字的色彩,巨细,还有边距,以及点击作用等等,这些都是需求外露,让运用者挑选性运用的,现在所有的特点如下,我们在运用的时分,也能够对照设置。
设置特点
特点 | 类型 | 概述 |
---|---|---|
lp_background | color | 全体的布景色彩 |
lp_rect_spacing | dimension | 格子的边距 |
lp_rect_height | dimension | 格子的高度 |
lp_rect_margin_top | dimension | 格子的间隔上边 |
lp_margin_left_right | dimension | 左右间隔 |
lp_margin_top | dimension | 上边间隔 |
lp_margin_bottom | dimension | 下边间隔 |
lp_rect_background | reference | 格子的布景 |
lp_rect_select_background | reference | 格子挑选后的布景 |
lp_rect_text_size | dimension | 格子的文字巨细 |
lp_rect_text_color | color | 格子的文字色彩 |
lp_rect_select_text_color | color | 格子的文字选中色彩 |
lp_is_show_complete | boolean | 是否显现完结按钮 |
lp_complete_text_size | dimension | 完结按钮文字巨细 |
lp_complete_text_color | color | 完结按钮文字色彩 |
lp_complete_text | string | 完结按钮文字内容 |
lp_complete_margin_top | dimension | 完结按钮间隔上边 |
lp_complete_margin_bottom | dimension | 完结按钮间隔下边 |
lp_complete_margin_right | dimension | 完结按钮间隔右边 |
lp_text_click_effect | boolean | 是否触发点击作用,true点击后布景消失,false不消失 |
界说办法
办法 | 参数 | 概述 |
---|---|---|
keyboardContent | 回调函数 | 获取点击的省份简称简称信息 |
keyboardDelete | 函数 | 删去省份简称简称信息 |
keyboardComplete | 回调函数 | 键盘点击完结 |
openProhibit | 函数 | 翻开制止(使领学港澳),使其能够点击 |
三、要害源码分析
这儿只贴出部分的要害性代码,全体的代码,我们滑到底部检查源码地址即可。
界说身份简称数组
//省份简称数据
private val mLicensePlateList = arrayListOf(
"京", "津", "渝", "沪", "冀", "晋", "辽", "吉", "黑", "苏",
"浙", "皖", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "琼",
"川", "贵", "云", "陕", "甘", "青", "蒙", "桂", "宁", "新",
"藏", "使", "领", "学", "港", "澳",
)
遍历省份简称
mLength为一行展现多少个,当取模为0时,就需求换行,也便是再次创立一个水平的LinearLayout,增加至外层的笔直LinearLayout中,每个水平的LinearLayout中,则是一个一个的TextView。
//每行对应的省份简称
var layout: LinearLayout? = null
//遍历车牌号
mLicensePlateList.forEachIndexed { index, s ->
if (index % mLength == 0) {
//从头创立,并增加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
}
}
//创立文字视图
val textView = TextView(context).apply {
text = s
//设置文字的特点
textSize = px2sp(mRectTextSize)
//最终五个是否制止
if (mNumProhibit && index > (mLicensePlateList.size - 6)) {
setTextColor(mNumProhibitColor)
mTempTextViewList.add(this)
} else {
setTextColor(mRectTextColor)
}
setBackgroundResource(mRectBackGround)
gravity = Gravity.CENTER
setOnClickListener {
if (mNumProhibit && index > (mLicensePlateList.size - 6)) {
return@setOnClickListener
}
//每个格子的点击事件
changeTextViewState(this)
}
}
addRectView(textView, layout, 0.1f)
}
追加最终一个View
因为最终一个视图是一个图片,占有了两个格子的巨细,所以需求特殊处理,需求做的便是,独自设置权重weight和独自设置宽度width,如下所示:
/**
* AUTHOR:AbnerMing
* INTRODUCE:追加最终一个View
*/
private fun addEndView(layout: LinearLayout?) {
val endViewLayout = LinearLayout(context)
endViewLayout.gravity = Gravity.RIGHT
//删去按钮
val endView = RelativeLayout(context)
//增加删去按钮
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 {
//删去
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
}
}
四、开源地址及运用总结
开源地址:github.com/AbnerMing88…
关于运用,其实便是一个类,我们能够下载源码,直接仿制即可运用,还能够进行修正里边的代码,十分的方便,假如懒得下载源码,没关系,我也上传到了远程Maven,我们能够依照下面的办法进行运用。
Maven详细调用
1、在你的根项目下的build.gradle文件下,引进maven。
allprojects {
repositories {
maven { url "https://gitee.com/AbnerAndroid/almighty/raw/master" }
}
}
2、在你需求运用的Module中build.gradle文件下,引进依赖。
dependencies {
implementation 'com.vip:plate:1.0.0'
}
代码运用
<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" />
总结
我们在运用的时分,必定对照特点表进行挑选性运用;关于这个省份简称自界说View,完结办法有很多种,我现在的这种也不是最优的完结办法,仅仅自己的一个完结方案,给我们一个作为参考的根据,好了,铁子们,本篇文章就先到这儿,期望能够协助到我们。