Commit 244ff136 authored by lidawei1's avatar lidawei1

add 新增数字校验布局

parent 84550edf
package com.yidian.shenghuoquan.newscontent.widget
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
import android.widget.TextView
import com.yidian.shenghuoquan.newscontent.R
import com.yidian.utils.ToastUtil
/**
* author : lidawei
* date : 2021/6/1
* description :
*/
class NumberCheckView @JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet?=null,
defStyle: Int=0
) : LinearLayout(context, attributeSet, defStyle) {
private var onNumberMatch: (() -> Unit)? = null
private var onTextChange: ((Boolean, String) -> Unit)? = null
private var tvStart:TextView
private var etCheck:NumberWithBorderEditText
private var tvEnd:TextView
private var originalNumber = ""
private var start = ""
private var end = ""
init {
LayoutInflater.from(context).inflate(R.layout.layout_number_check,this,true)
tvStart = findViewById(R.id.tv_start)
tvEnd = findViewById(R.id.tv_end)
etCheck = findViewById(R.id.et_check)
etCheck.setOnTextChangeListener {
if (originalNumber.isEmpty()) return@setOnTextChangeListener
val numberC = "$start$it$end"
if (numberC == originalNumber){
onNumberMatch?.invoke()
}
onTextChange?.invoke(numberC == originalNumber,numberC)
}
}
fun setOriginalNumber(number:String){
originalNumber = number
//简单校验
if (originalNumber.length != 11) {
ToastUtil.showToast(context,"手机号异常")
return
}
start = originalNumber.substring(0,3)
end = originalNumber.substring(11-4)
tvStart.text = start
tvEnd.text = end
}
/**
* 号码输入时监听
*/
fun setOnTextChangListener(onTextChange:(/*输入结果是否正确*/Boolean,String)->Unit){
this.onTextChange =onTextChange
}
/**
* 号码完全匹配监听
*/
fun setOnNumberMatchListener(onNumberMatch:()->Unit){
this.onNumberMatch =onNumberMatch
}
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.widget
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
import android.text.InputFilter
import android.text.InputType
import android.text.Spanned
import android.util.AttributeSet
import android.view.Gravity
import androidx.appcompat.widget.AppCompatEditText
import com.yidian.common.utils.YdUiUtils
import com.yidian.shenghuoquan.newscontent.R
import java.util.regex.Pattern
/**
* author : lidawei
* date : 2021/6/1
* description :
*/
@Suppress("DEPRECATION")
class NumberWithBorderEditText @JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null,
defStyle: Int = 0
) : AppCompatEditText(context, attributeSet, defStyle) {
private var onTextChange: ((String) -> Unit)? = null
//输入的数字个数
private val inputCount = 4
//间距
private val gap = YdUiUtils.dip2px(4, context)
private var borderPaint: Paint
private var textPaint: Paint
private val textSizeReal = 16
private var borderStroke =3f
private val selectedBorderColor = context.resources.getColor(R.color.edit_text_border_blue)
private val normalBorderColor = context.resources.getColor(R.color.edit_text_border_gray)
private val textColor = context.resources.getColor(R.color.gray_333)
private val borderWidth = YdUiUtils.dip2px(24, context)
private val borderList by lazy { ArrayList<RectF>() }
private val numberList by lazy { ArrayList<Triple<String,Float,Float>>() }
private var content:String?=null
private var startX = 0f
private var startY = 0f
init {
isLongClickable = false
setTextIsSelectable(false)
isCursorVisible = false
background = null
inputType = InputType.TYPE_CLASS_PHONE or InputType.TYPE_NUMBER_VARIATION_NORMAL
gravity = Gravity.START or Gravity.CENTER_VERTICAL
textSize = textSizeReal.toFloat()
borderPaint = Paint()
borderPaint.isAntiAlias = true
borderPaint.strokeWidth = borderStroke
borderPaint.style = Paint.Style.STROKE
textPaint = Paint()
textPaint.isAntiAlias = true
textPaint.textSize = YdUiUtils.dip2px(textSizeReal,context).toFloat()
textPaint.color = textColor
textPaint.style = Paint.Style.FILL
content = ""
repeat(inputCount) {
borderList.add(RectF())
}
filters = arrayOf(InputFilter.LengthFilter(inputCount),NumberFilter())
}
fun getContentText():String{
return content?:""
}
fun setOnTextChangeListener(onTextChange:(String)->Unit){
this.onTextChange = onTextChange
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
// 强制设置宽度为wrap_content
val heightMode = MeasureSpec.getMode(heightMeasureSpec)
var heightSize = MeasureSpec.getSize(heightMeasureSpec)
val widthReal:Int = (borderWidth * inputCount + (inputCount - 1) + gap +borderStroke * inputCount*2).toInt()
if (heightMode == MeasureSpec.AT_MOST || heightSize < borderWidth) {
heightSize = (borderWidth+borderStroke*2).toInt()
}
calculatePerBorderPosition(heightSize)
setMeasuredDimension(widthReal, heightSize)
}
override fun onTextChanged(
text: CharSequence?,
start: Int,
lengthBefore: Int,
lengthAfter: Int
) {
if (content == null || text==null) return
if (text.length>inputCount){
setText(content)
setSelection(content?.length?:0)
inputType = InputType.TYPE_CLASS_PHONE
return
}
content = text.toString()
numberList.clear()
//计算每个文字的绘制的宽高
calculatePerBorderPosition(height)
calculatePerNumPosition(content?:"")
onTextChange?.invoke(content?:"")
}
private fun calculatePerBorderPosition(height: Int) {
//让输入框在居中位置
startY = ((height - borderWidth) / 2).toFloat()
startX = borderStroke/2
//初始化输入框
borderList.forEach {
it.set(startX, startY, (startX + borderWidth), startY + borderWidth)
startX += borderWidth + gap
}
}
private fun calculatePerNumPosition(content: String) {
var startX = 0f
content.forEach{c ->
val measureText = textPaint.measureText(c.toString())
val textStartX = startX+(borderWidth-measureText)/2
numberList.add(Triple(c.toString(),textStartX,baseline.toFloat()))
startX += borderWidth +gap
}
}
override fun onDraw(canvas: Canvas?) {
borderList.forEachIndexed { index, rectF ->
if (index<content?.length?:0){
borderPaint.color = selectedBorderColor
}else{
borderPaint.color = normalBorderColor
}
canvas?.drawRect(rectF,borderPaint)
}
numberList.forEach {
canvas?.drawText(it.first,it.second,it.third,textPaint)
}
}
class NumberFilter : InputFilter {
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence {
if (source.isNullOrEmpty()) return ""
if (Pattern.matches("[0-9]*",source)) return source
return ""
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:parentTag="LinearLayout"
android:gravity="center_vertical"
>
<TextView
android:id="@+id/tv_start"
tools:text="182"
android:letterSpacing="0.3"
android:textColor="@color/gray_333"
android:textSize="16sp"
android:layout_marginEnd="2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.yidian.shenghuoquan.newscontent.widget.NumberWithBorderEditText
android:id="@+id/et_check"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_marginStart="2dp"
android:id="@+id/tv_end"
tools:text="5678"
android:letterSpacing="0.3"
android:textColor="@color/gray_333"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</merge>
\ No newline at end of file
...@@ -39,4 +39,6 @@ ...@@ -39,4 +39,6 @@
<color name="red_account_tips">#FF3A3A</color> <color name="red_account_tips">#FF3A3A</color>
<color name="account_hint">#c2c2c2</color> <color name="account_hint">#c2c2c2</color>
<color name="base">#FF1852F1</color> <color name="base">#FF1852F1</color>
<color name="edit_text_border_blue">#1852F1</color>
<color name="edit_text_border_gray">#cccccc</color>
</resources> </resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment