欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

Android自定义实现一个省份简称键盘,

来源: 开发者 投稿于  被查看 367 次 评论:98

Android自定义实现一个省份简称键盘,


目录
  • 一、分析UI,如何布局
  • 二、设置属性和方法,制定可扩展效果
    • 设置属性
    • 定义方法
  • 三、关键源码剖析
    • 定义身份简称数组
    • 遍历省份简称
    • 追加最后一个View
  • 四、开源地址及使用总结
    • Maven具体调用
    • 代码使用
  • 总结

    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_backgroundcolor整体的背景颜色
    lp_rect_spacingdimension格子的边距
    lp_rect_heightdimension格子的高度
    lp_rect_margin_topdimension格子的距离上边
    lp_margin_left_rightdimension左右距离
    lp_margin_topdimension上边距离
    lp_margin_bottomdimension下边距离
    lp_rect_backgroundreference格子的背景
    lp_rect_select_backgroundreference格子选择后的背景
    lp_rect_text_sizedimension格子的文字大小
    lp_rect_text_colorcolor格子的文字颜色
    lp_rect_select_text_colorcolor格子的文字选中颜色
    lp_is_show_completeboolean是否显示完成按钮
    lp_complete_text_sizedimension完成按钮文字大小
    lp_complete_text_colorcolor完成按钮文字颜色
    lp_complete_textstring完成按钮文字内容
    lp_complete_margin_topdimension完成按钮距离上边
    lp_complete_margin_bottomdimension完成按钮距离下边
    lp_complete_margin_rightdimension完成按钮距离右边
    lp_text_click_effectboolean是否触发点击效果,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/AbnerMing888/LicensePlateView

    关于使用,其实就是一个类,大家可以下载源码,直接复制即可使用,还可以进行修改里面的代码,非常的方便,如果懒得下载源码,没关系,我也上传到了远程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,实现方式有很多种,我目前的这种也不是最优的实现方式,只是自己的一个实现方案,给大家一个作为参考的依据。

    以上就是Android自定义实现一个省份简称键盘的详细内容,更多关于Android自定义键盘的资料请关注3672js教程其它相关文章!

    您可能感兴趣的文章:
    • Android自定义View软键盘实现搜索
    • Android自定义软键盘的设计与实现代码
    • Android自定义密码输入框和数字键盘
    • Android自定义View实现游戏摇杆键盘的方法示例
    • Android 仿微信自定义数字键盘的实现代码
    • Android自定义软键盘的步骤记录

    用户评论