之前因为工作没有转型kotlin的必要,并且一些杂事较多,一直没有好好深入学习kotlin。现在放眼看去,kotlin已经是统治地位了,不会kotlin,真不好意思说自己会做安卓开发。
非常遗憾,现在重新开始,我任是一个爱学新技术的追风少年。
我的学习方法是:
- 看语法讲解
- 看代码
- 修改代码或者自己实现一遍
在网上看了分享的一个车牌省份选择控件,使用kotlin实现的,可以作为学习资料。
项目地址:https://github.com/AbnerMing888/LicensePlateView。感兴趣的小伙伴可以去看原项目。
效果图
贴上代码
package com.example.mylogindemomvp.ui.carnumber import android.content.Context import android.graphics.Color import android.graphics.drawable.Drawable import android.util.AttributeSet import android.view.Gravity import android.widget.ImageView import android.widget.LinearLayout import android.widget.RelativeLayout import android.widget.TextView import androidx.core.content.ContextCompat import com.example.mylogindemomvp.R /** * 自定义车牌号选择器 */ class LicensePlateView: LinearLayout { companion object { val mLicensePlateList = arrayListOf( "京", "津", "渝", "沪", "冀", "晋", "辽", "吉", "黑", "苏", "浙", "皖", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "琼", "川", "贵", "云", "陕", "甘", "青", "蒙", "桂", "宁", "新", "藏", "使", "领", "学", "港", "澳", ) } private var mSpacing = 10f // 间隔 private var mMarginLeftRight = 10f // 左边距 private var mMarginBottom = 0f // 下边距 private var mMarginTop = 60f // 上边距 private var mLength = 10 // 长度 private var mRectHeight = 88f // 每个格子高度 private var mRectMarginTop = 16f // 距离上边高度 private var mBackGroundColor = Color.TRANSPARENT // 背景颜色 private var mBackGroundImageRes:Int ?= null // 背景图片资源 private var mRectBackGround = R.drawable.view_shape_stroke_8548d2_radius_2 // 格子背景 private var mRectSelectBackGround = R.drawable.view_shape_stroke_8548d2_radius_2// 格子选中背景 private var mIsShowComplete = true//是否显示完成按钮 private var mCompleteTextColor = Color.BLACK//完成按钮文字颜色 private var mCompleteTextSize = 36f//完成文字大小 private var mCompleteText = "完成"//完成文字内容 private var mCompleteMarginTop = 20f//完成距离上边 private var mCompleteMarginBottom = 20f//完成距离上边 private var mCompleteMarginRight = 20f//完成距离右边 private var mRectTextSize = 56f//格子的文字大小 private var mRectTextColor = ContextCompat.getColor(context, R.color.text_333333)//格子文字的默认颜色 private var mRectSelectTextColor = ContextCompat.getColor(context, R.color.text_8548D2) // 格子文字的选中颜色 private var mNumProhibit = true // 默认禁止选择 private var mNumProhibitColor = ContextCompat.getColor(context, R.color.text_999999) private var mTempTextViewList = ArrayList<TextView>() // 存储临时View private var mTextClickEffect = true // 是否触发点击效果 private var mOldTextView:TextView = TextView(context) constructor(context: Context): super(context) { initData(context) } constructor(context: Context, attrs: AttributeSet?): super(context, attrs) { context.obtainStyledAttributes(attrs, R.styleable.LicensePlateView) .apply { // 整理的背景颜色 mBackGroundColor = getColor(R.styleable.LicensePlateView_lp_background, Color.parseColor("#F5F5F5")) mBackGroundImageRes = getResourceId(R.styleable.LicensePlateView_lp_background_img, -1) // 每个格子的默认背景 mRectBackGround = getResourceId(R.styleable.LicensePlateView_lp_rect_background, mRectBackGround) // 每个格子的选中背景 mRectSelectBackGround = getResourceId(R.styleable.LicensePlateView_lp_rect_background, mRectSelectBackGround) // 格子的文字大小 mRectTextSize = getDimension(R.styleable.LicensePlateView_lp_rect_text_size, mRectTextSize) // 格子的文字颜色 mRectTextColor = getColor(R.styleable.LicensePlateView_lp_rect_text_color, mRectTextColor) //格子的选中文字颜色 mRectSelectTextColor = getColor(R.styleable.LicensePlateView_lp_rect_select_text_color, mRectSelectTextColor) //每个格子的边距 mSpacing = getDimension(R.styleable.LicensePlateView_lp_rect_spacing, mSpacing) //每个格子的高度 mRectHeight = getDimension(R.styleable.LicensePlateView_lp_rect_height, mRectHeight) // 格子距离上边的距离 mRectMarginTop = getDimension(R.styleable.LicensePlateView_lp_rect_margin_top, mRectMarginTop) // 视图距离左右的距离 mMarginLeftRight = getDimension(R.styleable.LicensePlateView_lp_margin_left_right, mMarginLeftRight) //视图距离上边的距离 mMarginTop = getDimension(R.styleable.LicensePlateView_lp_margin_top, mMarginTop) //视图距离下边的距离 mMarginBottom = getDimension(R.styleable.LicensePlateView_lp_margin_bottom, mMarginBottom) //视图距离左右的距离 mMarginLeftRight = getDimension(R.styleable.LicensePlateView_lp_margin_left_right, mMarginLeftRight) //是否显示完成按钮 mIsShowComplete = getBoolean(R.styleable.LicensePlateView_lp_is_show_complete, true) //完成按钮文字颜色 mCompleteTextColor = getColor(R.styleable.LicensePlateView_lp_complete_text_color, Color.parseColor("#087EFD")) //完成按钮文字大小 mCompleteTextSize = getDimension( R.styleable.LicensePlateView_lp_complete_text_size, mCompleteTextSize ) //完成按钮文字内容 getString(R.styleable.LicensePlateView_lp_complete_text)?.let { mCompleteText = it } //完成按钮距离上边 mCompleteMarginTop = getDimension( R.styleable.LicensePlateView_lp_complete_margin_top, mCompleteMarginTop ) //完成按钮距离下边 mCompleteMarginBottom = getDimension( R.styleable.LicensePlateView_lp_complete_margin_bottom, mCompleteMarginBottom ) //完成按钮距离上边 mCompleteMarginRight = getDimension( R.styleable.LicensePlateView_lp_complete_margin_right, mCompleteMarginRight ) //是否触发点击效果 mTextClickEffect = getBoolean( R.styleable.LicensePlateView_lp_text_click_effect, mTextClickEffect ) this.recycle() } initData(context) } /** * 初始化数据 */ private fun initData(context: Context) { // 设置背景颜色 setBackgroundColor(mBackGroundColor) if(mBackGroundImageRes != -1) { mBackGroundImageRes?.let { setBackgroundResource(it) } } orientation = VERTICAL // 设置距离底部 setPadding(0, mMarginTop.toInt(), 0, mMarginBottom.toInt()) // “完成” 按钮是否显示? if(mIsShowComplete) { // 添加完成的View视图 val textView = TextView(context) textView.apply { setOnClickListener() { mKeyboardCompleted?.invoke() } gravity = Gravity.END text = mCompleteText setTextColor(mCompleteTextColor) textSize = px2sp(mCompleteTextSize) } addView(textView) val submitParams = textView.layoutParams as LayoutParams submitParams.apply { width = LayoutParams.MATCH_PARENT topMargin = mCompleteMarginTop.toInt() bottomMargin = (mCompleteMarginBottom - mRectMarginTop).toInt() rightMargin = mCompleteMarginRight.toInt() textView.layoutParams = this } } // 每行对应的省份简称 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,动态计算宽度 addEndView(layout) } /** * AUTHOR:AbnerMing * INTRODUCE:追加最后一个View */ private fun addEndView(layout: LinearLayout?) { val endViewLayout = LinearLayout(context) endViewLayout.gravity = Gravity.END //删除按钮 val endView = RelativeLayout(context) //添加删除按钮 val deleteImage = ImageView(context) deleteImage.setImageResource(R.mipmap.icon_left) 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 } } private fun addRectView(view: TextView, layout: LinearLayout?, w: Float) { layout?.addView(view) val textParams = view.layoutParams as LayoutParams textParams.apply { weight = w width = 0 height = LayoutParams.MATCH_PARENT //每行的最后一个 rightMargin = mSpacing.toInt() view.layoutParams = this } } private fun changeTextViewState(textView: TextView) { if (mTextClickEffect) { //点击设置成效果 textView.setSelectTextStyle() textView.postDelayed({ textView.setUnSelectTextStyle() }, 300) } else { //记录上一个 mOldTextView?.setUnSelectTextStyle() textView.setSelectTextStyle() mOldTextView = textView } println("点击选择:" + textView.text) //每次点击后进行赋值 mKeyboardContent?.invoke(textView.text.toString()) } private fun TextView.setSelectTextStyle() { setBackgroundResource(mRectSelectBackGround) setTextColor(mRectSelectTextColor) } private fun TextView.setUnSelectTextStyle() { setBackgroundResource(mRectBackGround) setTextColor(mRectTextColor) } private fun createLinearLayout(): LinearLayout? { val layout = LinearLayout(context) layout.orientation = HORIZONTAL return layout } private var mKeyboardContent: ((content: String) -> Unit?)? = null fun keyboardContent(block: (String) -> Unit) { mKeyboardContent = block } /** * 键盘“完成”按键 */ private var mKeyboardCompleted: (() -> Unit)? = null fun keyboardCompleted(block: () -> Unit) { mKeyboardCompleted = block } /** * 键盘“删除”按键 */ private var mKeyboardDelete: (() -> Unit?)? = null fun keyboardDelete(block: () -> Unit) { mKeyboardDelete = block } fun openProhibit(isOpen: Boolean) { //禁止解开 mNumProhibit = isOpen mTempTextViewList.forEach { if (isOpen) { it.setTextColor(mRectTextColor) } else { it.setTextColor(mNumProhibitColor) } } } /** * 获取屏幕的宽 */ private fun getScreenWidth(): Int { return resources.displayMetrics.widthPixels } /** * DP转像素 */ private fun px2sp(pxValue: Float): Float { val fontScale = resources.displayMetrics.scaledDensity return pxValue / fontScale + 0.5f } }
自定义属性 attrs.xml
<declare-styleable name="LicensePlateView"> <!-- 整体的背景颜色--> <attr name="lp_background" format="color" /> <!-- 整体的背景图片--> <attr name="lp_background_img" format="reference" /> <!-- 格子的边距--> <attr name="lp_rect_spacing" format="dimension" /> <!-- 格子的高度--> <attr name="lp_rect_height" format="dimension" /> <!-- 格子的距离上边--> <attr name="lp_rect_margin_top" format="dimension" /> <!-- 左右距离--> <attr name="lp_margin_left_right" format="dimension" /> <!-- 上边距离--> <attr name="lp_margin_top" format="dimension" /> <!-- 下边距离--> <attr name="lp_margin_bottom" format="dimension" /> <!-- 格子的背景--> <attr name="lp_rect_background" format="reference" /> <!-- 格子选择后的背景--> <attr name="lp_rect_select_background" format="reference" /> <!-- 格子的文字大小--> <attr name="lp_rect_text_size" format="dimension" /> <!-- 格子的文字颜色--> <attr name="lp_rect_text_color" format="color" /> <!-- 格子的文字选中颜色--> <attr name="lp_rect_select_text_color" format="color" /> <!--是否显示完成按钮--> <attr name="lp_is_show_complete" format="boolean" /> <!--完成按钮文字大小--> <attr name="lp_complete_text_size" format="dimension" /> <!--完成按钮文字颜色--> <attr name="lp_complete_text_color" format="color" /> <!--完成按钮文字内容--> <attr name="lp_complete_text" format="string" /> <!--完成按钮距离上边--> <attr name="lp_complete_margin_top" format="dimension" /> <!--完成按钮距离下边--> <attr name="lp_complete_margin_bottom" format="dimension" /> <!--完成按钮距离右边--> <attr name="lp_complete_margin_right" format="dimension" /> <!--是否触发点击效果--> <attr name="lp_text_click_effect" format="boolean" /> </declare-styleable>
标签:LicensePlateView,01,context,Kotlin,private,学习,styleable,lp,var From: https://www.cnblogs.com/LiuSiyuan/p/17426488.html