Kotlin自定义实现支付密码数字键盘的方法实例

 更新时间:2018年07月22日 15:44:39   作者:loading  
这篇文章主要给大家介绍了关于Kotlin如何自定义实现支付密码数字键盘的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

你能学到什么

  • kotlin的使用, 扩展特性的写法等
  • 自定义ViewGroup的一些基础知识
  • xml属性的编写和读取

因为每个按键都考虑到需要支持背景设置等其他个性设置和Touch手势的处理, 所以我决定采用 每个按键 对应一个View的思路实现. 否则可以使用Canvas.drawText实现

这样可以提高扩展性和可自定义性

1.根据效果图先定义按键

//首先定义需要的那些按键
//顺序打乱,展示的时候也就是乱序的,可以更安全.
//特殊按键-> "":表示空白占位按键; "-1":表示回退键, 也就是删除.
var keys = arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "-1")

更新对应的按键, 创建对应的view

 keys.forEach {
  val keyView: View = when (it) {
   "-1" -> {
    //删除
    imageView(R.drawable.keyboard_del, R.drawable.keyboard_del_press).apply {
     background = null
     setBackgroundColor(Color.parseColor("#E2E7ED"))
    }
   }
   "" -> {
    //占位View
    View(context).apply {
     setBackgroundColor(Color.parseColor("#E2E7ED"))
    }
   }
   else -> {
    createKeyView(it)
   }
  }

  keyView.tag = it //通过tag, 保存按键对应的值
  addView(keyView)
 }

private fun createKeyView(key: String): View {
  return if (useImageKey) {
   val keyRes = when (key) {
    "1" -> R.drawable.keyboard_1
    "2" -> R.drawable.keyboard_2
    "3" -> R.drawable.keyboard_3
    "4" -> R.drawable.keyboard_4
    "5" -> R.drawable.keyboard_5
    "6" -> R.drawable.keyboard_6
    "7" -> R.drawable.keyboard_7
    "8" -> R.drawable.keyboard_8
    "9" -> R.drawable.keyboard_9
    else -> R.drawable.keyboard_0
   }
   imageView(keyRes)
  } else {
   textView(key)
  }
 }

 private fun imageView(res: Int, pressRes: Int = -1): ImageView {
  return ImageView(context).apply {

   if (pressRes == -1) {
    setImageResource(res)
   } else {
    setImageResource(res)
    //setImageDrawable(ResUtil.selector(getDrawable(res), getDrawable(pressRes)))
   }

   scaleType = ImageView.ScaleType.CENTER

   keyViewBGDrawable?.let {
    background = it.constantState.newDrawable()
   }

   setOnClickListener(this@KeyboardLayout)
  }
 }

 private fun textView(text: String): TextView {
  return TextView(context).apply {
   gravity = Gravity.CENTER
   this.text = text
   setTextSize(TypedValue.COMPLEX_UNIT_PX, keyTextSize)

   keyViewBGDrawable?.let {
    background = it.constantState.newDrawable()
   }
   setTextColor(Color.BLACK)

   setOnClickListener(this@KeyboardLayout)
  }
 }

2.按键元素创建好之后, 开始自定义ViewGroup的标准操作

onMeasure:测量每个按键的宽度和高度

 override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
  //super.onMeasure(widthMeasureSpec, heightMeasureSpec)
  var widthSize = MeasureSpec.getSize(widthMeasureSpec)
  val widthMode = MeasureSpec.getMode(widthMeasureSpec)
  var heightSize = MeasureSpec.getSize(heightMeasureSpec)
  val heightMode = MeasureSpec.getMode(heightMeasureSpec)

  if (widthMode != MeasureSpec.EXACTLY) {
   widthSize = resources.displayMetrics.widthPixels
  }

  if (heightMode != MeasureSpec.EXACTLY) {
   heightSize = (4 * keyViewHeight + 3 * vSpace).toInt()
  }

  childWidth = ((widthSize - 2 * hSpace - paddingLeft - paddingRight) / 3).toInt()
  childHeight = ((heightSize - 3 * vSpace - paddingTop - paddingBottom) / 4).toInt()
  childs { _, view ->
   view.measure(exactlyMeasure(childWidth), exactlyMeasure(childHeight))
  }
  setMeasuredDimension(widthSize, heightSize)
 }

onLayout:决定按键在ViewGroup中的坐标位置

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
 //一行一行布局, 共4行
 for (line in 0..3) {

  var top: Int = (paddingTop + line * (childHeight + vSpace)).toInt()

  //3列
  for (i in 0..2) {
   var left: Int = (paddingLeft + i * (childWidth + hSpace)).toInt()

   getChildAt(line * 3 + i).layout(left, top, left + childWidth, top + childHeight)
  }
 }
}

3:事件监听和回调

 override fun onClick(v: View?) {
  if (onKeyboardInputListener == null) {
   return
  }

  v?.let { view ->
   val tag = view.tag
   if (tag is String) {
    val isDel = "-1" == tag
    onKeyboardInputListener?.onKeyboardInput(tag, isDel)
   }
  }
 }

4:xml中的属性声明

需要在 values 文件夹中创建一个任意文件名的xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="KeyboardLayout">
  <attr name="r_key_height" format="dimension"/>
  <attr name="r_key_width" format="dimension"/>
  <attr name="r_key_text_size" format="dimension"/>
  <attr name="r_key_background" format="reference"/>
  <attr name="r_background" format="reference"/>
  <attr name="r_use_image_key" format="boolean"/>
 </declare-styleable>
</resources>

declare-styleable 都是标准写法, name对应的就是自定义view的类型, 都是标准写法, 不同的format对应不同的get方法. 熟悉了就很容易使用.

5:xml中的属性读取

 init {
  val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.KeyboardLayout) //注意1:
  keyViewHeight = typedArray.getDimensionPixelOffset(R.styleable.KeyboardLayout_r_key_height, keyViewHeight)
  //typedArray.getDimensionPixelOffset(R.styleable.KeyboardLayout_r_key_width, keyViewHeight)
  keyTextSize = typedArray.getDimension(R.styleable.KeyboardLayout_r_key_text_size, keyTextSize)
  useImageKey = typedArray.getBoolean(R.styleable.KeyboardLayout_r_use_image_key, useImageKey)

  keyViewBGDrawable = typedArray.getDrawable(R.styleable.KeyboardLayout_r_key_background)

  if (keyViewBGDrawable == null) {
   keyViewBGDrawable = getDrawable(R.drawable.base_white_bg_selector)
  }
  mBackgroundDrawable = typedArray.getDrawable(R.styleable.KeyboardLayout_r_background)
  if (mBackgroundDrawable == null) {
   mBackgroundDrawable = ColorDrawable(getColor(R.color.base_chat_bg_color))
  }

  setWillNotDraw(false)
  typedArray.recycle() //注意2
 }

注意1,2: 都是必备的写法, 中间部分才是对应的属性读取操作.

源码地址 https://github.com/angcyo/KeyboardLayout (本地下载

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • Android使用AudioRecord判断是否有音频输入

    Android使用AudioRecord判断是否有音频输入

    这篇文章主要介绍了Android使用AudioRecord判断是否有音频输入的实例代码,非常不错,具有参考借鉴价值,需要的的朋友参考下吧
    2017-01-01
  • Android实现欢迎滑动页面

    Android实现欢迎滑动页面

    这篇文章主要为大家详细介绍了Android实现欢迎滑动页面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • Flutter实现编写富文本Text的示例代码

    Flutter实现编写富文本Text的示例代码

    这篇文章主要为大家详细介绍了如何通过Flutter实现编写富文本Text,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-11-11
  • 微信小程序在安卓的白屏问题原因及改进讲解

    微信小程序在安卓的白屏问题原因及改进讲解

    今天小编就为大家分享一篇关于微信小程序在安卓的白屏问题原因及改进讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • android实现状态栏添加图标的函数实例

    android实现状态栏添加图标的函数实例

    这篇文章主要介绍了android实现状态栏添加图标的函数,较为详细的分析了Android状态栏添加及删除图标的具体实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • Android studio so库找不到问题解决办法

    Android studio so库找不到问题解决办法

    这篇文章主要介绍了Android studio so库找不到问题解决办法的相关资料,希望通过本文能帮助到大家解决出现的这种问题,需要的朋友可以参考下
    2017-10-10
  • 详解Android 全局弹出对话框SYSTEM_ALERT_WINDOW权限

    详解Android 全局弹出对话框SYSTEM_ALERT_WINDOW权限

    本篇文章主要介绍了详解Android 全局弹出对话框SYSTEM_ALERT_WINDOW权限,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • Android Studio ADB网络调试汇总

    Android Studio ADB网络调试汇总

    这篇文章主要为大家详细介绍了Android Studio ADB网络调试的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Android开发中Signal背后的bug与解决

    Android开发中Signal背后的bug与解决

    这篇文章主要为大家介绍了Android开发中Signal背后的bug与解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Android DataBinding的官方双向绑定示例

    Android DataBinding的官方双向绑定示例

    本篇文章主要介绍了Android DataBinding的官方双向绑定示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10

最新评论