android继承view输入框,android自定义View(七)、方形输入框

本文详细介绍了如何通过自定义布局和EditText实现一个动态输入验证码的功能,包括LinearLayout的使用、透明EditText的设计、内容监听与实时更新,以及如何根据需求添加自定义属性进行扩展。关键代码展示了如何动态创建输入框和绑定监听事件。
摘要由CSDN通过智能技术生成

先奉上最终效果图

5f6ba0b0eb92d9e01c03cbbee960b617.png

实现思路分析:

1、 使用一个LinearLayout用来填充每一个小方格,通过动态添加,实现出需要数量的输入框

2、 在LinearLayout上覆盖一层大小和LinearLayout大小完全一致的EditText,用来接口输入信息,设置EditText输入背景和文字为透明,并设置不展示光标,

3、 监听EditText的内容变化,和LinearLayout的内容绑定,实现每次输入都由LinearLayout的子布局展示出来

布局文件

在代码中动态创建LinearLayout子布局填充,并绑定监听

private fun initContainer() {

//动态设置EditText的大小

inputReal = findViewById(R.id.inputReal)

rvContentList = findViewById(R.id.rvContentList)

inputReal.width = (dividerDrawable?.minimumWidth ?: 0 * (verifyCodeLen - 1)) + inputBoxSize * verifyCodeLen

inputReal.height = inputBoxSize

inputReal.setTextSize(TypedValue.COMPLEX_UNIT_PX, inputTextSize * 1.0F)

//禁用光标

inputReal.isCursorVisible = false

inputReal.filters = arrayOf(InputFilter.LengthFilter(verifyCodeLen))

inputTextView.clear()

//动态添加LinearLayout之间的分割线

dividerDrawable?.let {

it.setBounds(0, 0, it.minimumWidth, it.minimumHeight)

rvContentList.dividerDrawable = it

}

for (i in 0 until verifyCodeLen) {

val textView = TextView(context)

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, inputTextSize * 1.0F)

textView.width = inputBoxSize

textView.height = inputBoxSize

textView.gravity = Gravity.CENTER

textView.isFocusable = false

textView.textColor = inputTextColor

textView.backgroundResource = itemSelector

inputTextView.add(textView)

}

inputTextView.forEach {

rvContentList.addView(it)

}

}

inputReal.addTextChangedListener(object : TextWatcher {

override fun afterTextChanged(p0: Editable?) {

setVerifyCodeInputValue(p0.toString())

if (p0.toString().length == verifyCodeLen) {

onCompleteListener?.onComplete(p0.toString())

}

}

override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

}

override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

}

})

private fun setVerifyCodeInputValue(inputText: String) {

inputTextView.forEach {

it.text = ""

it.isSelected = false

}

inputTextView.forEachIndexed { index, textView ->

if (inputText.length > index) {

textView.isSelected = true

textView.text = inputText[index].toString()

}

}

}

核心代码就到这里了,为了方便扩展,可以在加入自定义属性,动态设置扩展效果,这里就不说明了,直接看代码即可

最后放上完整源代码:

package org.fireking.ap.custom.viewgroup.view

import android.content.Context

import android.content.res.TypedArray

import android.graphics.Color

import android.graphics.drawable.Drawable

import android.text.Editable

import android.text.InputFilter

import android.text.Spanned

import android.text.TextWatcher

import android.util.AttributeSet

import android.util.Log

import android.util.TypedValue

import android.view.Gravity

import android.view.LayoutInflater

import android.widget.*

import androidx.core.view.forEach

import androidx.recyclerview.widget.RecyclerView

import org.fireking.ap.R

import org.jetbrains.anko.backgroundColor

import org.jetbrains.anko.backgroundResource

import org.jetbrains.anko.textColor

class VerifyCodeInputLayout(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :

RelativeLayout(context, attrs, defStyleAttr) {

private lateinit var inputReal: EditText

private lateinit var rvContentList: LinearLayout

private var onCompleteListener: OnCompleteListener? = null

private var verifyCodeLen = 0

private var inputTextSize: Int = 0

private var inputTextColor: Int = 0

private var inputBoxSize: Int = 0

private var verifyInputLayoutHeight = 0

private var dividerDrawable: Drawable? = null

private var itemSelector: Int = R.drawable.verify_code_text_selector

private var inputTextView = ArrayList(4)

constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) {

LayoutInflater.from(context).inflate(R.layout.verify_code_input_layout, this, true)

//设置默认值

verifyCodeLen = 4

inputTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16.0F, resources.displayMetrics).toInt()

inputTextColor = Color.parseColor("#FF333333")

inputBoxSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50F, resources.displayMetrics).toInt()

dividerDrawable = context.resources.getDrawable(R.drawable.linearlayout_divider)

//获取自定义属性值

val a = context.obtainStyledAttributes(attrs, R.styleable.VerifyCodeInputLayout)

if (a.hasValue(R.styleable.VerifyCodeInputLayout_textSize)) {

inputTextSize = a.getDimensionPixelSize(R.styleable.VerifyCodeInputLayout_textSize, inputTextSize)

}

if (a.hasValue(R.styleable.VerifyCodeInputLayout_textColor)) {

inputTextColor = a.getColor(R.styleable.VerifyCodeInputLayout_textColor, Color.parseColor("#FF333333"))

}

if (a.hasValue(R.styleable.VerifyCodeInputLayout_inputBoxSize)) {

inputBoxSize = a.getDimensionPixelSize(

R.styleable.VerifyCodeInputLayout_inputBoxSize,

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 44F, resources.displayMetrics).toInt()

)

}

if (a.hasValue(R.styleable.VerifyCodeInputLayout_dividerDrawable)) {

dividerDrawable = a.getDrawable(R.styleable.VerifyCodeInputLayout_dividerDrawable)

}

if (a.hasValue(R.styleable.VerifyCodeInputLayout_itemSelector)) {

itemSelector = a.getResourceId(R.styleable.VerifyCodeInputLayout_itemSelector, itemSelector)

}

if (a.hasValue(R.styleable.VerifyCodeInputLayout_maxLength)) {

verifyCodeLen = a.getInt(R.styleable.VerifyCodeInputLayout_maxLength, 4)

}

a.recycle()

}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec)

verifyInputLayoutHeight = measuredHeight

}

fun setOnCompleteListener(onCompleteListener: OnCompleteListener) {

this.onCompleteListener = onCompleteListener

}

override fun onFinishInflate() {

super.onFinishInflate()

initContainer()

initListener()

}

private fun initListener() {

inputReal.addTextChangedListener(object : TextWatcher {

override fun afterTextChanged(p0: Editable?) {

setVerifyCodeInputValue(p0.toString())

if (p0.toString().length == verifyCodeLen) {

onCompleteListener?.onComplete(p0.toString())

}

}

override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

}

override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

}

})

}

private fun setVerifyCodeInputValue(inputText: String) {

inputTextView.forEach {

it.text = ""

it.isSelected = false

}

inputTextView.forEachIndexed { index, textView ->

if (inputText.length > index) {

textView.isSelected = true

textView.text = inputText[index].toString()

}

}

}

private fun initContainer() {

inputReal = findViewById(R.id.inputReal)

rvContentList = findViewById(R.id.rvContentList)

inputReal.width = (dividerDrawable?.minimumWidth ?: 0 * (verifyCodeLen - 1)) + inputBoxSize * verifyCodeLen

inputReal.height = inputBoxSize

inputReal.setTextSize(TypedValue.COMPLEX_UNIT_PX, inputTextSize * 1.0F)

inputReal.isCursorVisible = false

inputReal.filters = arrayOf(InputFilter.LengthFilter(verifyCodeLen))

inputTextView.clear()

dividerDrawable?.let {

it.setBounds(0, 0, it.minimumWidth, it.minimumHeight)

rvContentList.dividerDrawable = it

}

for (i in 0 until verifyCodeLen) {

val textView = TextView(context)

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, inputTextSize * 1.0F)

textView.width = inputBoxSize

textView.height = inputBoxSize

textView.gravity = Gravity.CENTER

textView.isFocusable = false

textView.textColor = inputTextColor

textView.backgroundResource = itemSelector

inputTextView.add(textView)

}

inputTextView.forEach {

rvContentList.addView(it)

}

}

interface OnCompleteListener {

fun onComplete(content: String)

}

}

自定义属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值