Android自定义View实现九宫格图形解锁(Kotlin版)
程序员文章站
2022-03-06 23:48:10
本文实例为大家分享了android自定义view实现九宫格图形解锁的具体代码,供大家参考,具体内容如下效果:代码:package com.example.kotlin_test import andr...
本文实例为大家分享了android自定义view实现九宫格图形解锁的具体代码,供大家参考,具体内容如下
效果:
代码:
package com.example.kotlin_test import android.content.context import android.graphics.canvas import android.graphics.color import android.graphics.paint import android.util.attributeset import android.view.motionevent import android.view.view /** * created by wanglx on 2021/9/8. */ class mylock : view { private var isinit=false private var mpoints:array<array<point?>> = array(3){array<point?>(3){null} } private var mselectpoints=arraylist<point>() private var istouch=false private var code= listof(0,1,2,5,8) //画笔 private lateinit var mnormalpaint:paint private lateinit var mpressedpaint:paint private lateinit var merrorpaint: paint private lateinit var mlinepaint: paint //颜色 private val mnormalcolor=color.black private val mpressedcolor=color.green private val merrorcolor=color.red private 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.centerx var dy=point.centery-mlastpoint.centery var 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=0f private var movingy=0f override fun ontouchevent(event: motionevent?): boolean { movingx=event!!.x movingy=event.y when (event.action) { motionevent.action_down->{ for (i in 0..mselectpoints.size - 1) { mselectpoints[i].setstatusnormal() } mselectpoints.clear() invalidate() //先判断是不是在圆内 var dd=point if (dd != null) { dd.setstatuspressed() mselectpoints.add(dd) istouch=true } } motionevent.action_move->{ //先判断是不是在圆内 var dd=point if (dd != null) { dd.setstatuspressed() if (!mselectpoints.contains(dd)) { mselectpoints.add(dd) } } } motionevent.action_up->{ istouch=false if (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())<mdotradius return isin } private fun initpaint() { //正常画笔 mnormalpaint = paint() mnormalpaint!!.color=mnormalcolor mnormalpaint.style=paint.style.stroke mnormalpaint.isantialias=true mnormalpaint.strokewidth=mdotradius.tofloat()/12 //按下画笔 mpressedpaint = paint() mpressedpaint!!.color=mpressedcolor mpressedpaint.style=paint.style.stroke mpressedpaint.isantialias=true mpressedpaint.strokewidth=mdotradius.tofloat()/9 //错误画笔 merrorpaint = paint() merrorpaint!!.color=merrorcolor merrorpaint.style=paint.style.stroke merrorpaint.isantialias=true merrorpaint.strokewidth=mdotradius.tofloat()/12 //连线画笔 mlinepaint = paint() mlinepaint!!.color=mlinecolor mlinepaint.style=paint.style.stroke mlinepaint.isantialias=true mlinepaint.strokewidth=mdotradius.tofloat()/12 } private fun initdot() { var width=this.width var height=this.height var offsetx=0f//九个宫格为正方形,距离布局左边的距离 var offsety=0f//九宫格为正方形,距离布局顶部的距离 //兼容横竖屏 if (width > height) { offsetx = (width - height).tofloat() / 2 width = 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 } } }
布局:
<?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" tools:context=".mainactivity"> <com.example.kotlin_test.mylock android:layout_width="match_parent" android:layout_height="match_parent" /> </linearlayout>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。