IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android 自定义车牌键盘(kotlin) -> 正文阅读

[移动开发]android 自定义车牌键盘(kotlin)

前言

平时停车缴费都要填车牌号码,就想着自己能不能也做个车牌键盘demo。
自定义车牌键盘能满足(普通车牌,新能源,警车,军车,领事馆车,教练车以及特种车辆等车牌)

示例图

在这里插入图片描述
在这里插入图片描述

实现需求

1、车牌前两位默认是:粤A

2、第一个控件,默认是省份键盘

3、剩下控件,默认是abc键盘

4、当前输入框输完后能自动跳转到下个控件

5、当前输入框有选中背景,其他的没有

定义键盘文件

在res文件夹下创建xml文件夹,创建省份键盘(province.xml)和abc键盘(abc.xml)

province.xml

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="1%p"
    android:keyWidth="10%p"
    android:keyHeight="8%p"
    android:verticalGap="0.0px">
    <Row android:verticalGap="1%p">
        <Key
            android:codes="20140"
            android:keyLabel="" />
        <Key
            android:codes="27941"
            android:keyLabel="" />
        <Key
            android:codes="20864"
            android:keyLabel="" />
        <Key
            android:codes="40065"
            android:keyLabel="" />
        <Key
            android:codes="26187"
            android:keyLabel="" />
        <Key
            android:codes="33945"
            android:keyLabel="" />
        <Key
            android:codes="36797"
            android:keyLabel="" />
        <Key
            android:codes="21513"
            android:keyLabel="" />
        <Key
            android:codes="40657"
            android:keyLabel="" />
        <Key
            android:codes="27818"
            android:keyLabel="" />
    </Row>
    <Row android:verticalGap="1%p">
        <Key
            android:codes="33487"
            android:keyLabel="" />
        <Key
            android:codes="27993"
            android:keyLabel="" />
        <Key
            android:codes="30358"
            android:keyLabel="" />
        <Key
            android:codes="38397"
            android:keyLabel="" />
        <Key
            android:codes="36195"
            android:keyLabel="" />
        <Key
            android:codes="35947"
            android:keyLabel="" />
        <Key
            android:codes="37122"
            android:keyLabel="" />
        <Key
            android:codes="28248"
            android:keyLabel="" />
        <Key
            android:codes="31908"
            android:keyLabel="" />
        <Key
            android:codes="26690"
            android:keyLabel="" />
    </Row>
    <Row android:verticalGap="1%p">
        <Key
            android:codes="28189"
            android:keyLabel="" />
        <Key
            android:codes="24029"
            android:keyLabel="" />
        <Key
            android:codes="36149"
            android:keyLabel="" />
        <Key
            android:codes="20113"
            android:keyLabel="" />
        <Key
            android:codes="34255"
            android:keyLabel="" />
        <Key
            android:codes="38485"
            android:keyLabel="" />
        <Key
            android:codes="29976"
            android:keyLabel="" />
        <Key
            android:codes="38738"
            android:keyLabel="" />
        <Key
            android:codes="29756"
            android:keyLabel="" />
        <Key
            android:codes="26032"
            android:keyLabel="" />
    </Row>
    <Row>
        <Key
            android:codes="-1"
            android:isModifier="true"
            android:isSticky="true"
            android:keyWidth="10%p"
            android:keyLabel="ABC" />
        <Key
            android:codes="23425"
            android:keyLabel="" />
        <Key
            android:codes="20351"
            android:keyLabel="使" />
        <Key
            android:codes="39046"
            android:keyLabel="" />
        <Key
            android:codes="35686"
            android:keyLabel="" />
        <Key
            android:codes="23398"
            android:keyLabel="" />
        <Key
            android:codes="28207"
            android:keyLabel="" />
        <Key
            android:codes="28595"
            android:keyLabel="" />
<!--         注释台湾-->
<!--        <Key-->
<!--            android:codes="21488"-->
<!--            android:keyLabel="台" />-->
        <Key
            android:codes="-3"
            android:isRepeatable="false"
            android:keyWidth="10%p"
            android:keyLabel="删除" />
    </Row>
</Keyboard>

abc.xml

<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="9%p" android:keyHeight="8%"
    android:horizontalGap="1%p" android:verticalGap="0.0px"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <Row android:verticalGap="1%p">
        <Key android:codes="49" android:keyLabel="1"
            android:horizontalGap="1%p" android:keyWidth="8%p"  />
        <Key android:codes="50" android:keyLabel="2"
             />
        <Key android:codes="51" android:keyLabel="3"
             />
        <Key android:codes="52" android:keyLabel="4"
             />
        <Key android:codes="53" android:keyLabel="5"
             />
        <Key android:codes="54" android:keyLabel="6"
             />
        <Key android:codes="55" android:keyLabel="7"
             />
        <Key android:codes="56" android:keyLabel="8"
             />
        <Key android:codes="57" android:keyLabel="9"
             />
        <Key android:codes="48" android:keyLabel="0"
            />
    </Row>
    <Row android:verticalGap="1%p">
        <Key android:codes="81" android:keyLabel="Q"
            android:horizontalGap="1%p" android:keyWidth="8%p"
            android:keyEdgeFlags="left" />
        <Key android:codes="87" android:keyLabel="W"
             />
        <Key android:codes="69" android:keyLabel="E"
             />
        <Key android:codes="82" android:keyLabel="R"
             />
        <Key android:codes="84" android:keyLabel="T"
             />
        <Key android:codes="89" android:keyLabel="Y"
             />
        <Key android:codes="85" android:keyLabel="U"
             />
        <Key android:codes="73" android:keyLabel="I"
             />
        <Key android:codes="79" android:keyLabel="O"
             />
        <Key android:codes="80" android:keyLabel="P"
            
            android:keyEdgeFlags="right" />
    </Row>
    <Row android:verticalGap="1%p">
        <Key android:codes="65" android:keyLabel="A"
            android:horizontalGap="6%p" android:keyWidth="8%p"
            android:keyEdgeFlags="left"/>
        <Key android:codes="83" android:keyLabel="S"
             />
        <Key android:codes="68" android:keyLabel="D"
             />
        <Key android:codes="70"  android:keyLabel="F"
             />
        <Key android:codes="71" android:keyLabel="G"
             />
        <Key android:codes="72"  android:keyLabel="H"
             />
        <Key android:codes="74" android:keyLabel="J"
             />
        <Key android:codes="75" android:keyLabel="K"
             />
        <Key android:codes="76"  android:keyLabel="L"
            
            android:keyEdgeFlags="right" />
    </Row>
    <Row >
        <Key android:codes="-2"
            android:keyEdgeFlags="left" android:keyLabel="省份"
            android:horizontalGap="1%p" android:keyWidth="13%p"
            android:isModifier="true" android:isSticky="true"  />
        <Key android:codes="90" android:keyLabel="Z"
            />
        <Key android:codes="88" android:keyLabel="X"
             />
        <Key android:codes="67" android:keyLabel="C"
             />
        <Key android:codes="86" android:keyLabel="V"
             />
        <Key android:codes="66" android:keyLabel="B"
             />
        <Key android:codes="78" android:keyLabel="N"
            />
        <Key android:codes="77" android:keyLabel="M"
            />
        <Key  android:codes="-3"
            android:keyEdgeFlags="right" android:keyLabel="删除"
            android:horizontalGap="1.5%p" android:keyWidth="13%p"
            android:isRepeatable="false" />
    </Row>
</Keyboard>

核心代码

键盘工具类KeyboardUtil

package com.example.ktproject
import android.inputmethodservice.Keyboard
import android.inputmethodservice.KeyboardView
import android.text.InputType
import android.view.View
import android.view.WindowManager
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity

class KeyboardUtil(private var activity: AppCompatActivity) {

    private var mKeyboardView: KeyboardView
    private val provinceKeyboard: Keyboard
    private var abcKeyboard: Keyboard
    private var editText: EditText? = null
    
    init {
        // 省份键盘
        provinceKeyboard = Keyboard(activity, R.xml.province)
        // abc键盘
        abcKeyboard = Keyboard(activity, R.xml.abc)
        
        mKeyboardView = activity.findViewById(R.id.keyboard_view)
        
        mKeyboardView.apply {
            keyboard = provinceKeyboard
            isEnabled = true
            // 设置按键没有点击放大镜显示的效果
            isPreviewEnabled = false
            setOnKeyboardActionListener(object : KeyboardView.OnKeyboardActionListener {
                override fun onPress(primaryCode: Int) {
                }
                override fun onRelease(primaryCode: Int) {
                }
                override fun onText(text: CharSequence?) {
                }
                override fun swipeLeft() {
                }
                override fun swipeRight() {
                }
                override fun swipeDown() {
                }
                override fun swipeUp() {
                }
                override fun onKey(primaryCode: Int, keyCodes: IntArray?) {
                    val editable = editText?.text
                    val start: Int = editText?.selectionStart ?: 0
                    when (primaryCode) {
                        -1 -> changeKeyboard(true)
                        -2 -> changeKeyboard(false)
                        -3 -> {
                            if (start != null) {
                                editable?.delete(0, start)
                            }
                        }
                        else -> {
                            // 清空之前数据
                            editText?.text?.clear()
                            editable?.insert(0, primaryCode.toChar().toString())
                        }
                    }
                }
            })
        }
    }
    
    fun setEditText(editText: EditText) {
        this.editText = editText
    }
    
    /**
     * 指定切换软键盘
     * isNumber false 省份软键盘, true 数字字母软键盘
     */
    fun changeKeyboard(isNumber: Boolean) {
        if (isNumber) {
            mKeyboardView.keyboard = abcKeyboard
        } else {
            mKeyboardView.keyboard = provinceKeyboard
        }
    }
    /**
     * 软键盘展示状态
     */
    fun isShow() = mKeyboardView.visibility == View.VISIBLE
    /**
     * 显示软键盘
     */
    fun showKeyboard() {
        val visibility = mKeyboardView.visibility
        if (visibility == View.GONE || visibility == View.INVISIBLE) {
            mKeyboardView.visibility = View.VISIBLE
        }
    }
    /**
     * 隐藏软键盘
     */
    fun hideKeyboard() {
        val visibility = mKeyboardView.visibility
        if (visibility == View.VISIBLE) {
            mKeyboardView.visibility = View.INVISIBLE
        }
    }
    /**
     * 禁掉系统软键盘
     */
    fun hideSoftInputMethod(editText: EditText) {
        activity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
        editText.inputType = InputType.TYPE_NULL
    }
}

实现代码

package com.example.ktproject
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
    private lateinit var keyboardUtil: KeyboardUtil
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 默认选中第三个控件
        keyboardUtil = KeyboardUtil(this)
        keyboardUtil.hideSoftInputMethod(et2)
        keyboardUtil.showKeyboard()
        keyboardUtil.setEditText(et2)
        keyboardUtil.changeKeyboard(true)
        et2.setBackgroundResource(R.drawable.shape_et_select)
        val etList = listOf(etProvince, et1, et2, et3, et4, et5, et6, et7)
        etProvince.setOnTouchListener(MyOnTouchListener(0, false, etList, keyboardUtil))
        et1.setOnTouchListener(MyOnTouchListener(1, true, etList, keyboardUtil))
        et2.setOnTouchListener(MyOnTouchListener(2, true, etList, keyboardUtil))
        et3.setOnTouchListener(MyOnTouchListener(3, true, etList, keyboardUtil))
        et4.setOnTouchListener(MyOnTouchListener(4, true, etList, keyboardUtil))
        et5.setOnTouchListener(MyOnTouchListener(5, true, etList, keyboardUtil))
        et6.setOnTouchListener(MyOnTouchListener(6, true, etList, keyboardUtil))
        et7.setOnTouchListener(MyOnTouchListener(7, true, etList, keyboardUtil))

        etProvince.addTextChangedListener(MyTextWatcher(etProvince, et1, true, keyboardUtil))
        et1.addTextChangedListener(MyTextWatcher(et1, et2, true, keyboardUtil))
        et2.addTextChangedListener(MyTextWatcher(et2, et3, true, keyboardUtil))
        et3.addTextChangedListener(MyTextWatcher(et3, et4, true, keyboardUtil))
        et4.addTextChangedListener(MyTextWatcher(et4, et5, true, keyboardUtil))
        et5.addTextChangedListener(MyTextWatcher(et5, et6, true, keyboardUtil))
    }
    class MyTextWatcher(
        private val curEditText: EditText,
        private val nextEditText: EditText,
        private val isNumber: Boolean,
        private val keyboardUtil: KeyboardUtil
    ) : TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        }
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        }
        override fun afterTextChanged(s: Editable?) {
            s?.let {
                if (it.isNotEmpty()) {
                    // 下个控件获取焦点
                    nextEditText.requestFocus()
                    nextEditText.setSelection(nextEditText.text.length)
                    // 更新背景
                    curEditText.setBackgroundResource(R.drawable.shape_et)
                    nextEditText.setBackgroundResource(R.drawable.shape_et_select)
                    // 切换键盘
                    keyboardUtil.changeKeyboard(isNumber)
                    keyboardUtil.setEditText(nextEditText)
                }
            }
        }
    }
    class MyOnTouchListener(
        private val index: Int,
        private val isNumber: Boolean,
        private val etList: List<EditText>,
        private val keyboardUtil: KeyboardUtil
    ) : View.OnTouchListener {
        override fun onTouch(v: View?, event: MotionEvent?): Boolean {
            changeEditTextBg(index, etList)
            // 切换键盘
            keyboardUtil.hideSoftInputMethod(v as EditText)
            keyboardUtil.changeKeyboard(isNumber)
            keyboardUtil.setEditText(v)
            v.setSelection(v.text.length)
            return false
        }
        // 更新控件背景
        private fun changeEditTextBg(index: Int, etList: List<EditText>) {
            etList[0].setBackgroundResource((if (index == 0) R.drawable.shape_et_select else R.drawable.shape_et))
            etList[1].setBackgroundResource((if (index == 1) R.drawable.shape_et_select else R.drawable.shape_et))
            etList[2].setBackgroundResource((if (index == 2) R.drawable.shape_et_select else R.drawable.shape_et))
            etList[3].setBackgroundResource((if (index == 3) R.drawable.shape_et_select else R.drawable.shape_et))
            etList[4].setBackgroundResource((if (index == 4) R.drawable.shape_et_select else R.drawable.shape_et))
            etList[5].setBackgroundResource((if (index == 5) R.drawable.shape_et_select else R.drawable.shape_et))
            etList[6].setBackgroundResource((if (index == 6) R.drawable.shape_et_select else R.drawable.shape_et))
            etList[7].setBackgroundResource((if (index == 7) R.drawable.shape_et_select else R.drawable.shape_et_green))
        }
    }
    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (keyboardUtil.isShow()) {
                keyboardUtil.hideKeyboard()
            } else {
                finish()
            }
        }
        return false
    }
}


布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="20dp"
        android:text="请输入您的车牌号码:"
        android:textColor="#000"
        android:textSize="20sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <LinearLayout
        android:id="@+id/carLayout"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal"
        app:layout_constraintTop_toBottomOf="@id/tvTitle"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="12dp">
        <EditText
            android:id="@+id/etProvince"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@drawable/shape_et"
            android:gravity="center"
            android:text=""
            android:maxLength="1"
            android:textSize="20sp" />
        <EditText
            android:id="@+id/et1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="2dp"
            android:layout_weight="1"
            android:background="@drawable/shape_et"
            android:gravity="center"
            android:text="A"
            android:maxLength="1"
            android:textSize="20sp" />
        <EditText
            android:id="@+id/et2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="2dp"
            android:layout_weight="1"
            android:background="@drawable/shape_et"
            android:gravity="center"
            android:maxLength="1"
            android:textSize="20sp" />

        <EditText
            android:id="@+id/et3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="2dp"
            android:layout_weight="1"
            android:background="@drawable/shape_et"
            android:gravity="center"
            android:maxLength="1"
            android:textSize="20sp" />
        <EditText
            android:id="@+id/et4"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="2dp"
            android:layout_weight="1"
            android:background="@drawable/shape_et"
            android:gravity="center"
            android:maxLength="1"
            android:textSize="20sp" />
        <EditText
            android:id="@+id/et5"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="2dp"
            android:layout_weight="1"
            android:background="@drawable/shape_et"
            android:gravity="center"
            android:maxLength="1"
            android:textSize="20sp" />
        <EditText
            android:id="@+id/et6"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="2dp"
            android:layout_weight="1"
            android:background="@drawable/shape_et"
            android:gravity="center"
            android:maxLength="1"
            android:textSize="20sp" />
        <EditText
            android:id="@+id/et7"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="2dp"
            android:layout_weight="1"
            android:background="@drawable/shape_et_green"
            android:gravity="center"
            android:hint=""
            android:maxLength="1"
            android:textSize="20sp" />

    </LinearLayout>
    <android.inputmethodservice.KeyboardView
        android:id="@+id/keyboard_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#DCDCDC"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:keyBackground="@drawable/selector_key"
        android:keyTextColor="#000"
        android:keyTextSize="18sp"
        android:paddingTop="8dp"
        android:paddingBottom="8dp"
        android:shadowColor="#FFFFFF"
        android:shadowRadius="0.0"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>

视频效果

自定义车牌

汉字转化

先将目标汉字转换Unicode, 再通过16进制转换成10进制。比如“京” 转换Unicode码为“\u4eac”,再将16进制的“4eac”转换成10进制码为“20140”。

<Key android:codes="20140" android:keyLabel="" />

转换参考下面链接:

汉字转换Unicode网址:http://www.msxindl.com/tools/unicode16.asp
汉字转换Unicode

16进制转10进制网址:https://tool.oschina.net/hexconvert/
16进制转10进制

项目链接

项目gitee链接: https://gitee.com/linvisf/KtDemo

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:53:17  更:2022-10-08 20:53:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 2:42:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码