代码拉取完成,页面将自动刷新
以下只展示关键部分
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
>
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入验证码"
android:textSize="20sp"
android:layout_marginTop="20dp"
android:layout_gravity="center_horizontal"
/>
<com.lujianfei.plugin2_7.CodeEditText
android:id="@+id/edit_verification_code"
android:layout_marginTop="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
package com.lujianfei.plugin2_7
import android.content.Intent
import android.net.Uri
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import com.lujianfei.module_plugin_base.base.BasePluginActivity
import com.lujianfei.module_plugin_base.beans.PluginActivityBean
class MainActivity : BasePluginActivity() {
...
private var edit_verification_code: CodeEditText? = null
override fun resouceId(): Int = R.layout.activity_main
override fun initView() {
edit_verification_code = findViewById(R.id.edit_verification_code)
}
override fun initEvent() {
edit_verification_code?.requestFocus()
edit_verification_code?.showSoftInput()
edit_verification_code?.onInputFinishListener = { code->
Toast.makeText(that, code, Toast.LENGTH_SHORT).show()
}
}
...
}
核心组件类
package com.lujianfei.plugin2_7
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.text.InputFilter
import android.text.InputFilter.LengthFilter
import android.util.AttributeSet
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.widget.AppCompatEditText
import com.lujianfei.module_plugin_base.utils.DensityUtils
/**
*@date 创建时间:2020/10/20
*@name 作者:陆键霏
*@describe 描述:
*/
class CodeEditText @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatEditText(context, attrs, defStyleAttr) {
// 验证码文本颜色
private var mTextColor = 0
// 输入的最大长度
private val mMaxLength = 4
// 边框宽度
private val mStrokeWidth = DensityUtils.dip2px(60f)
// 边框高度
private val mStrokeHeight = DensityUtils.dip2px(60f)
// 边框之间的距离
private val mStrokePadding = DensityUtils.dip2px(20f)
// 用矩形来保存方框的位置、大小信息
private val mRect = Rect()
/**
* 输入结束监听
*/
var onInputFinishListener: ((String)->Unit)? = null
// 方框的背景
private var mStrokeDrawable: Drawable? = null
init {
// 只允许数字
inputType = EditorInfo.TYPE_CLASS_NUMBER
// 创建 enable 和 focused 状态下的 drawable
val normalDrawable = DrawableHelper.createDrawable(
fillColor = 0xffffffff.toInt(),
roundRadius = DensityUtils.dip2px(5f).toFloat(),
strokeWidth = DensityUtils.dip2px(1f),
strokeColorIn = 0xffdddddd.toInt()
)
val focusedDrawable = DrawableHelper.createDrawable(
fillColor = 0xffffffff.toInt(),
roundRadius = DensityUtils.dip2px(5f).toFloat(),
strokeWidth = DensityUtils.dip2px(1f),
strokeColorIn = 0xfff89b09.toInt()
)
// 将 drawable 合成为 selector, 使其同时具备 enable 和 focused 不同状态的样式
val selector = DrawableHelper.createSelector(enableDrawable = normalDrawable, focusedDrawable = focusedDrawable, normalDrawable = normalDrawable)
mStrokeDrawable = selector
// 最大字数
setMaxLength(mMaxLength)
// 去掉背景颜色
setBackgroundColor(Color.TRANSPARENT)
// 不显示光标
isCursorVisible = false
isFocusableInTouchMode = true
isFocusable = true
}
/**
* 设置最大长度
*/
private fun setMaxLength(maxLength: Int) {
filters = if (maxLength >= 0) {
arrayOf<InputFilter>(LengthFilter(maxLength))
} else {
arrayOfNulls(0)
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
// 当前输入框的宽高信息
var width = measuredWidth
var height = measuredHeight
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
val heightMode = MeasureSpec.getMode(heightMeasureSpec)
// 判断高度是否小于推荐高度
if (height < mStrokeHeight) {
height = mStrokeHeight
}
// 输入框宽度 = 边框宽度 * 数量 + 边框间距 *(数量-1)
val recommendWidth = mStrokeWidth * mMaxLength + mStrokePadding * (mMaxLength - 1)
// 判断宽度是否小于推荐宽度
if (width < recommendWidth) {
width = recommendWidth
}
val widthMeasureSpecAfter = MeasureSpec.makeMeasureSpec(width, widthMode)
val heightMeasureSpecAfter = MeasureSpec.makeMeasureSpec(height, heightMode)
// 设置测量布局
setMeasuredDimension(widthMeasureSpecAfter, heightMeasureSpecAfter)
}
override fun onDraw(canvas: Canvas?) {
mTextColor = currentTextColor
// 在画支持设置文本颜色,把系统化的文本透明掉,相当于覆盖
setTextColor(Color.TRANSPARENT)
// 系统画的方法
super.onDraw(canvas)
// 重新设置文本颜色
setTextColor(mTextColor)
// 重绘背景颜色
drawStrokeBackground(canvas)
// 重绘文本
drawText(canvas)
}
override fun onTextContextMenuItem(id: Int): Boolean {
return false
}
/**
* 绘制方框
*/
private fun drawStrokeBackground(canvas: Canvas?) {
if (canvas == null) return
// 下面绘制方框背景颜色
// 确定反馈位置
mRect.left = 0
mRect.top = 0
mRect.right = mStrokeWidth
mRect.bottom = mStrokeHeight
val count = canvas.saveCount // 当前画布保存的状态
canvas.save() // 保存画布
for (i in 0 until mMaxLength) {
mStrokeDrawable?.apply {
bounds = mRect // 设置位置
state = intArrayOf(android.R.attr.state_enabled) // 设置图像状态
draw(canvas) // 画到画布上
}
// 确定下一个方框的位置
val dx = mRect.right + mStrokePadding.toFloat() // X坐标位置
// 保存画布
canvas.save()
// [注意细节] 移动画布到下一个位置
canvas.translate(dx, 0f)
}
// [注意细节] 把画布还原到画反馈之前的状态,这样就还原到最初位置了
canvas.restoreToCount(count)
// 画布归位
canvas.translate(0f, 0f)
// 下面绘制高亮状态的边框
// 当前高亮的索引
val activatedIndex = 0.coerceAtLeast(editableText.length)
mRect.left = mStrokeWidth * activatedIndex + mStrokePadding * activatedIndex
mRect.right = mRect.left + mStrokeWidth
mStrokeDrawable?.apply {
state = intArrayOf(android.R.attr.state_focused)
bounds = mRect
draw(canvas)
}
}
/**
* 重绘文本
*/
private fun drawText(canvas: Canvas?) {
if (canvas == null) return
val count = canvas.saveCount
canvas.translate(0f, 0f)
val length = editableText.length
for (i in 0 until length) {
val text = editableText[i].toString()
val textPaint = paint
textPaint.color = mTextColor
// 获取文本大小
textPaint.getTextBounds(text, 0, 1, mRect)
// 计算(x,y) 坐标
val x = mStrokeWidth / 2 + (mStrokeWidth + mStrokePadding) * i - mRect.centerX()
val y = canvas.height / 2 + mRect.height() / 2
canvas.drawText(text, x.toFloat(), y.toFloat(), textPaint)
}
canvas.restoreToCount(count)
}
override fun onTextChanged(
text: CharSequence?,
start: Int,
lengthBefore: Int,
lengthAfter: Int
) {
super.onTextChanged(text, start, lengthBefore, lengthAfter)
// 当前文本长度
val textLength = editableText.length
if (textLength == mMaxLength) {
hideSoftInput()
onInputFinishListener?.invoke(editableText.toString())
}
}
private fun hideSoftInput() {
val imm =
context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(
windowToken,
InputMethodManager.HIDE_NOT_ALWAYS
)
}
fun showSoftInput() {
val inputManager= context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputManager.showSoftInput(this, 0)
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。