首页 > 其他分享 >Kotlin学习 01

Kotlin学习 01

时间:2023-05-23 21:45:12浏览次数:46  
标签:LicensePlateView 01 context Kotlin private 学习 styleable lp var

之前因为工作没有转型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

相关文章

  • 计算机组成原理学习之中央处理器
    中央处理器是控制计算机完成取指令和执行指令任务的部件;是计算机的核心部件,简称CPU。CPU的基本认功能分为四个:比较好想的就是指令控制,有指令就有操作,那就是就是操作控制,然后就是比较容易忽略的操作的时间特性,必须注意的一点是计算机类的任何操作都是在一定的周期内有条不紊的进......
  • mysql的继续学习第二天
    在mysql中读取文件的函数load_file使用方法:select*fromarticlewhereid=-1unionselect1,1,1,1,load_file('c:/boot.ini');//load_file会占一位,并且路径使用括号包围intooutfile写入函数:(来自csdn查找)要使用intooutfile把代码写到web目录取得webshell首先需要3大先天......
  • hudi学习
    1.背景想要对自己的各种数据(非结构化)进行统一管理,突然想到数据湖,看看是否符合我的需求。2.Hudi简介2.1hudi的特性mutabilitysupportforalldatalakeworkoadsQuicklyupdate&deletedatawithHudi'sfast,pluggableindexing.Thisincludesstreamingworkloads,w......
  • MAUI Blazor学习7-实现登录跳转页面
    MAUIBlazor学习7-实现登录跳转页面 MAUIBlazor系列目录MAUIBlazor学习1-移动客户端Shell布局-SunnyTrudeau-博客园(cnblogs.com)MAUIBlazor学习2-创建移动客户端Razor页面-SunnyTrudeau-博客园(cnblogs.com)MAUIBlazor学习3-绘制ECharts图表-SunnyTrudeau......
  • 1013 数素数(C++)
    一、问题描述:令 Pi​ 表示第 i 个素数。现任给两个正整数 M≤N≤104,请输出 PM​ 到 PN​ 的所有素数。输入格式:输入在一行中给出 M 和 N,其间以空格分隔。输出格式:输出从 PM​ 到 PN​ 的所有素数,每10个数字占1行,其间以空格分隔,但行末不得有多余空格。输......
  • 【安全学习之路】Day6
    ......
  • NumPy学习1
    NumPy是NumericalPython的缩写,它是一个由多维数组对象(ndarray)和处理这些数组的函数(function)集合组成的库。使用NumPy库,可以对数组执行数学运算和相关逻辑运算。NumPy不仅作为Python的扩展包,它同样也是Python科学计算的基础包。NumPy使用需求随着数据科学(DataScience,简......
  • MySQL学习基础篇Day8
    5.7多表查询案例数据环境准备:createtablesalgrade(gradeint,losalint,hisalint)comment'薪资等级表';insertintosalgradevalues(1,0,3000);insertintosalgradevalues(2,3001,5000);insertintosalgradevalues(3,5001,8000);insertin......
  • UE4学习笔记:Windows系统下如何在C++项目里调用第三方动态库
    本随笔介绍在Windows系统下,由UE4引擎创建的C++项目里如何实现调用第三方动态库的方法。随笔作者还在学习阶段,对UE4引擎的使用和理解还不是非常透彻,难免会在随笔内容里出现技术上或书写上的问题,如果出现了类似的问题欢迎在评论区或者私信讨论。 目录设置第三方库头文件的路......
  • Day01-常见的dos命令
    常见的dos命令windows打开cmd方式开始+系统+命令提示符win键+R输入cmd打开控制台(推荐使用)在任意的文件夹下面,按住shfit键+鼠标右键点击,在此处打开命令行窗口资源管理器的地址栏前面加上cmd路径管理员方式运行选择以管理员方式运行常用的dos命令 #盘符切......