Android 自定义手势解锁View

  • Post author:
  • Post category:其他


直接上代码了:

/**
 *
 *@ClassName:GraphicsView
 *@author:WYL
 *@Date:2022/9/29
 */
class GraphicsView : View {

    private var mWidth = 0

    private var mHeight = 0

    /**
     * 圆的半径
     */
    private var radius = 80f

    //默认的点
    private val graphicsPoints = mutableListOf<GraphicsPoint>()

    //选中的点
    private val checkGraphicsPoints = mutableListOf<GraphicsPoint>()

    private val mPaint: Paint by lazy {
        Paint(Paint.ANTI_ALIAS_FLAG).apply {
            isAntiAlias = true
            style = Paint.Style.FILL
            isDither = true
        }
    }

    private val linePaint: Paint by lazy {
        Paint(Paint.ANTI_ALIAS_FLAG).apply {
            isAntiAlias = true
            style = Paint.Style.FILL
            isDither = true
            strokeWidth = 10f
            mPaint.pathEffect = CornerPathEffect(10f)
            color = Color.parseColor("#FF575E")
            strokeCap = Paint.Cap.ROUND
        }
    }

    constructor(context: Context?) : this(context, null)

    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        init()
    }

    private fun init() {
        graphicsPoints.clear()
        graphicsPoints.add(GraphicsPoint(1))
        graphicsPoints.add(GraphicsPoint(2))
        graphicsPoints.add(GraphicsPoint(3))
        graphicsPoints.add(GraphicsPoint(4))
        graphicsPoints.add(GraphicsPoint(5))
        graphicsPoints.add(GraphicsPoint(6))
        graphicsPoints.add(GraphicsPoint(7))
        graphicsPoints.add(GraphicsPoint(8))
        graphicsPoints.add(GraphicsPoint(9))
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)
        mWidth = Math.min(width, height)
        mHeight = mWidth
        setMeasuredDimension(mWidth, mHeight)
    }

    /**
     * 选中颜色
     */
    private val selectColor = Color.parseColor("#FF575E")
    private val selectColorTransparent = Color.parseColor("#32FF575E")
    private val unselectColor = Color.parseColor("#BCC6CE")

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

        val averageWidth = mWidth / 3f

        val averageHeight = mHeight / 3f

        for (i in 0 until 3) {
            for (j in 0 until 3) {
                graphicsPoints[i * 3 + j].apply {
                    x = (averageWidth * (j + 1)) - averageWidth / 2f
                    y = (averageHeight * (i + 1)) - averageHeight / 2f
                }
            }
        }

        var startX = 0f
        var startY = 0f
        var stopX = 0f
        var stopY = 0f

        checkGraphicsPoints.forEachIndexed { index, it ->
            if (index > 0) {
                stopX = it.x
                stopY = it.y
                canvas?.drawLine(startX, startY, stopX, stopY, linePaint)
                startX = stopX
                startY = stopY
            } else {
                startX = it.x
                startY = it.y
            }
        }

        if (continueJudge) {
            canvas?.drawLine(startX, startY, currentX, currentY, linePaint)
        }

        graphicsPoints.forEach {
            if (it.isSelect) {
                mPaint.color = selectColorTransparent
                canvas?.drawCircle(it.x, it.y, radius, mPaint)
                mPaint.color = selectColor
                canvas?.drawCircle(it.x, it.y, radius/3, mPaint)
            } else {
                mPaint.color = unselectColor
                canvas?.drawCircle(it.x, it.y, radius/3, mPaint)
            }
        }

    }

    /**
     * 判断滑动时是否去判断
     */
    private var continueJudge = false

    private var currentX = 0f

    private var currentY = 0f

    override fun onTouchEvent(event: MotionEvent): Boolean {

        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                graphicsPoints.forEach {
                    if (judgeCircle(it, event.x, event.y)) {
                        //Log.e(GraphicsView::class.java.canonicalName, "在圆点里面!!!!!!!!!!!!!")
                        continueJudge = true
                        it.isSelect = true
                        checkGraphicsPoints.add(it)
                        currentX = event.x
                        currentY = event.y
                        invalidate()
                        return@forEach
                    }
                }
            }
            MotionEvent.ACTION_MOVE -> {
                if (continueJudge) {
                    currentX = event.x
                    currentY = event.y
                    invalidate()
                }
                graphicsPoints.forEach {
                    if (judgeCircle(it, event.x, event.y) && !it.isSelect) {
                        //Log.e(GraphicsView::class.java.canonicalName, "在圆点里面!!!!!!!!!!!!!")
                        it.isSelect = true
                        checkGraphicsPoints.add(it)
                        if (!continueJudge) {
                            currentX = event.x
                            currentY = event.y
                            continueJudge = true
                        }
                        invalidate()
                        return@forEach
                    }
                }
            }
            MotionEvent.ACTION_UP -> {
                val selects = checkGraphicsPoints.filter { it.isSelect }
                if(selects.isNotEmpty()){
                    val subString = StringBuffer()
                    selects.forEach {
                        subString.append("${it.type}")
                    }
                    //ToastUtils.showShort(subString)
                    onResultListener?.onResult(subString.toString())
                }
                continueJudge = false
                checkGraphicsPoints.clear()
                graphicsPoints.forEach {
                    it.isSelect = false
                }
                invalidate()
            }
        }

        return true
    }

    /**
     * 判断触点是否在圆里面
     */
    fun judgeCircle(p: GraphicsPoint, m_x: Float, m_y: Float): Boolean {
        val c = Math.pow(
            Math.pow(
                p.x.toDouble() - m_x.toDouble(),
                2.0
            ) + Math.pow(p.y.toDouble() - m_y.toDouble(), 2.0), 0.5
        )
        return (c < radius)
    }

    inner class GraphicsPoint {

        var x = 0f

        var y = 0f

        var type: Int = -1

        var isSelect = false

        constructor(x: Float, y: Float, type: Int) {
            this.x = x
            this.y = y
            this.type = type
        }

        constructor(type: Int) {
            this.type = type
        }

    }

    var onResultListener:OnResultListener? = null

    interface OnResultListener{
        fun onResult(password:String)
    }

}

效果图:



版权声明:本文为z18374453733原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。