安卓人机验证View
效果图:
1.添加自定义属性
在values的attrs.xml 中
<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="CaptchaView"><attr name="captchaLength" format="integer" /><attr name="captchaFontSize" format="dimension" /></declare-styleable>
</resources>
2.自定义View
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import androidx.core.content.withStyledAttributes
import kotlin.random.Randomclass CaptchaView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {companion object {private const val DEFAULT_CAPTCHA_LENGTH = 4private const val DEFAULT_WIDTH = 160private const val DEFAULT_HEIGHT = 58private const val DEFAULT_FONT_SIZE = 24fprivate val GRAY = Color.GRAY}private var captchaCode: String = ""private val textPaint = Paint()private val linePaint = Paint()private val random = Random.Default// 自定义属性var captchaLength: Int = DEFAULT_CAPTCHA_LENGTHset(value) {field = valuegenerateNewCaptcha()}var captchaFontSize: Float = DEFAULT_FONT_SIZEset(value) {field = valuetextPaint.textSize = valueinvalidate()}init {// 从XML属性读取设置context.withStyledAttributes(attrs,R.styleable.CaptchaView,defStyleAttr,0) {captchaLength = getInt(R.styleable.CaptchaView_captchaLength,DEFAULT_CAPTCHA_LENGTH)captchaFontSize = getDimension(R.styleable.CaptchaView_captchaFontSize,DEFAULT_FONT_SIZE)}// Initialize paintstextPaint.apply {textSize = captchaFontSizetextAlign = Paint.Align.CENTERisAntiAlias = true}linePaint.apply {color = GRAYstrokeWidth = 1fisAntiAlias = true}generateNewCaptcha()}fun generateNewCaptcha() {captchaCode = generateCaptchaCode(captchaLength)invalidate() // Redraw the view}fun getCaptchaCode(): String = captchaCodeprivate fun generateCaptchaCode(length: Int): String {return (1..length).joinToString("") { Random.nextInt(10).toString() }}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {// 获取XML中指定的宽高或使用默认值val width = resolveSize(DEFAULT_WIDTH, widthMeasureSpec)val height = resolveSize(DEFAULT_HEIGHT, heightMeasureSpec)setMeasuredDimension(width, height)}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)// Set the background color to whitecanvas.drawColor(Color.WHITE)// Calculate the base vertical center of the canvas for the textval baseTextYPos = (height / 2 - (textPaint.descent() + textPaint.ascent()) / 2)val maxVerticalOffset = (captchaFontSize * 0.5f).toInt()// Draw each characterval charWidth = width / captchaCode.length.toFloat()captchaCode.forEachIndexed { index, char ->val xPos = (index + 0.5f) * charWidthval yOffset = random.nextInt(-maxVerticalOffset, maxVerticalOffset + 1)val currentYPos = baseTextYPos + yOffsettextPaint.color = Color.rgb(random.nextInt(256),random.nextInt(256),random.nextInt(256))canvas.drawText(char.toString(), xPos, currentYPos, textPaint)}// Draw some random linesfor (i in 0..3) {val startX = random.nextInt(width)val startY = random.nextInt(height)val endX = random.nextInt(width)val endY = random.nextInt(height)canvas.drawLine(startX.toFloat(),startY.toFloat(),endX.toFloat(),endY.toFloat(),linePaint)}}
}
3.使用
<包名.CaptchaViewandroid:id="@+id/captchaContent"android:layout_width="match_parent"android:layout_height="match_parent"app:captchaFontSize="28sp"app:captchaLength="6" />
//获取显示的code
val code = binding.captchaContent.getCaptchaCode()//刷新
binding.captchaContent.generateNewCaptcha()