Android自定义View实现九宫格图形解锁(Kotlin版)
本文实例为大家分享了Android自定义View实现九宫格图形解锁的具体代码,供大家参考,具体内容如下
效果:
文章图片
代码:
package com.example.kotlin_test import android.content.Contextimport android.graphics.Canvasimport android.graphics.Colorimport android.graphics.Paintimport android.util.AttributeSetimport android.view.MotionEventimport android.view.View /** * Created by wanglx on 2021/9/8. */class MyLock : View {private var isInit=falseprivate var mPoints:Array> = Array(3){Array(3){null} }private var mSelectPoints=ArrayList()private var isTouch=falseprivate var code= listOf(0,1,2,5,8) //画笔private lateinit var mNormalPaint:Paintprivate lateinit var mPressedPaint:Paintprivate lateinit var mErrorPaint: Paintprivate lateinit var mLinePaint: Paint //颜色private val mNormalColor=Color.BLACKprivate val mPressedColor=Color.GREENprivate val mErrorColor=Color.REDprivate val mLineColor=Color.BLACK //外圆半径private var mDotRadius=0 constructor(context: Context) : super(context)constructor(context: Context, attrs: AttributeSet) : super(context, attrs)constructor(context: Context, attrs: AttributeSet, defaultStyle: Int):super(context,attrs,defaultStyle) override fun onDraw(canvas: Canvas?) {//初始化if (!isInit) {initDot()initPaint()isInit=true} //绘制drawShow(canvas) } private fun drawShow(canvas: Canvas?) {for (i in 0..2) {for (j in 0..2) {var point = mPoints[i][j]when(point!!.status){PointStatus.NORMAL->{//先画外圆,再画内圆canvas!!.drawCircle(point.centerX,point.centerY,mDotRadius.toFloat(),mNormalPaint)canvas!!.drawCircle(point.centerX,point.centerY,mDotRadius.toFloat()/6,mNormalPaint)}PointStatus.PRESSED->{canvas!!.drawCircle(point.centerX,point.centerY,mDotRadius.toFloat(),mPressedPaint)canvas!!.drawCircle(point.centerX,point.centerY,mDotRadius.toFloat()/6,mPressedPaint)}PointStatus.ERROR->{canvas!!.drawCircle(point.centerX,point.centerY,mDotRadius.toFloat(),mErrorPaint)canvas!!.drawCircle(point.centerX,point.centerY,mDotRadius.toFloat()/6,mErrorPaint) }} }} //画连线drawLine(canvas) } private fun drawLine(canvas: Canvas?) {if (mSelectPoints.size > 0) {var mLastPoint = mSelectPoints[0]//两点连线if (mSelectPoints.size > 1) {for (i in 1..mSelectPoints.size-1) {var point = mSelectPoints[i]realDrawLine(mLastPoint, point, canvas, mLinePaint)mLastPoint=point}} //手指和某个点的连线var isInner=checkInRound(mLastPoint.centerX,mLastPoint.centerY,movingX,movingY,mDotRadius/6)if (!isInner&&isTouch) {realDrawLine(mLastPoint,Point(movingX,movingY,-1),canvas,mLinePaint)}} } private fun realDrawLine(mLastPoint: Point,point: Point,canvas: Canvas?,mLinePaint: Paint) {//不是从圆心坐标开始画,而是距离圆心有一定的距离var dx=point.centerX-mLastPoint.centerXvar dy=point.centerY-mLastPoint.centerYvar pointDistance = Math.sqrt((dx * dx + dy * dy).toDouble()) var offsetX = (dx / pointDistance) * (mDotRadius / 6)var offsetY=(dy/pointDistance)*(mDotRadius/6) canvas!!.drawLine((mLastPoint.centerX+offsetX).toFloat(),(mLastPoint.centerY+offsetY).toFloat(),(point.centerX-offsetX).toFloat(), (point.centerY-offsetY).toFloat(),mLinePaint)} private var movingX=0fprivate var movingY=0foverride fun onTouchEvent(event: MotionEvent?): Boolean {movingX=event!!.xmovingY=event.ywhen (event.action) {MotionEvent.ACTION_DOWN->{for (i in 0..mSelectPoints.size - 1) {mSelectPoints[i].setStatusNormal()}mSelectPoints.clear()invalidate()//先判断是不是在圆内var dd=pointif (dd != null) {dd.setStatusPressed()mSelectPoints.add(dd)isTouch=true}}MotionEvent.ACTION_MOVE->{//先判断是不是在圆内var dd=pointif (dd != null) {dd.setStatusPressed()if (!mSelectPoints.contains(dd)) {mSelectPoints.add(dd)}}}MotionEvent.ACTION_UP->{isTouch=falseif (mSelectPoints.size == code.size) {for (i in 0..mSelectPoints.size - 1) {if (mSelectPoints[i].index != code[i]) {for (i in 0..mSelectPoints.size - 1) {//密码不对,设置为错误状态mSelectPoints[i].setStatusError()}break}}} else {for (i in 0..mSelectPoints.size - 1) {mSelectPoints[i].setStatusError()}}}} invalidate()return true} //扩展属性,遍历九个圆,看手指的按在哪个圆里面val point:Point?get() {for (i in 0..2) {for (j in 0..2) {var point = mPoints[i][j]if (checkInRound(point!!.centerX, point.centerY, movingX, movingY, mDotRadius)) {return point}}}return null}//判断是不是在圆内private fun checkInRound(centerX: Float,centerY: Float,movingX: Float,movingY: Float,mDotRadius: Int): Boolean {var isIn=Math.sqrt(((centerX-movingX)*(centerX-movingX)+(centerY-movingY)*(centerY-movingY)).toDouble())height) {offsetX = (width - height).toFloat() / 2width = height} else {offsetY = (height - width).toFloat() / 2 } //每个方格的大小var squareWidth=width/3 mDotRadius=squareWidth/4 //九个宫格,存于数组Point[3][3]mPoints[0][0] = Point(squareWidth/2+offsetX,squareWidth/2+offsetY,0)mPoints[0][1] = Point(squareWidth*3/2+offsetX,squareWidth/2+offsetY,1)mPoints[0][2] = Point(squareWidth*5/2+offsetX,squareWidth/2+offsetY,2)mPoints[1][0] = Point(squareWidth/2+offsetX,squareWidth*3/2+offsetY,3)mPoints[1][1] = Point(squareWidth*3/2+offsetX,squareWidth*3/2+offsetY,4)mPoints[1][2] = Point(squareWidth*5/2+offsetX,squareWidth*3/2+offsetY,5)mPoints[2][0] = Point(squareWidth/2+offsetX,squareWidth*5/2+offsetY,6)mPoints[2][1] = Point(squareWidth*3/2+offsetX,squareWidth*5/2+offsetY,7)mPoints[2][2] = Point(squareWidth*5/2+offsetX,squareWidth*5/2+offsetY,8) } //圆的状态enum class PointStatus{NORMAL,PRESSED,ERROR} class Point(var centerX: Float, var centerY: Float, var index: Int){//默认状态var status = PointStatus.NORMAL fun setStatusNormal() {status=PointStatus.NORMAL} fun setStatusPressed() {status=PointStatus.PRESSED}fun setStatusError() {status=PointStatus.ERROR}} }
布局:
【Android自定义View实现九宫格图形解锁(Kotlin版)】以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
推荐阅读
- android第三方框架(五)ButterKnife
- Android中的AES加密-下
- 带有Hilt的Android上的依赖注入
- SpringBoot调用公共模块的自定义注解失效的解决
- python自定义封装带颜色的logging模块
- 列出所有自定义的function和view
- android|android studio中ndk的使用
- tableView|tableView 头视图下拉放大 重写
- Android事件传递源码分析
- RxJava|RxJava 在Android项目中的使用(一)