美文网首页待写安卓开发博客
Android 从 0 开始学习自定义 View(十一) 自定义

Android 从 0 开始学习自定义 View(十一) 自定义

作者: 是刘航啊 | 来源:发表于2021-06-22 14:25 被阅读0次

    效果图

    实现分析

    1. 画 9 个圆
    2. 根据手指触摸的坐标更改圆的颜色
    3. 画线
    4. 处理手指抬起的状态

    后面的文章大部分应该都会使用 Kotlin ,随着 JetPack 和 Compose 的广泛使用,Kotlin 慢慢成为了趋势。如果对 Kotlin 还不了解的推荐一下郭神的 《第一行代码》Kotlin 版,比较容易上手的 Koltin 入门书籍。

    1、画 9 个圆

    private fun initDot() {
        //初始化9宫格
        //记录点的状态,回掉密码
    
        //九宫格总宽度
        var width = this.width
        //九宫格总高度
        var height = this.height
    
        var offSetY = 0
        var offSetX = 0
        //兼容横竖屏
        if (height > width) {
            //Y轴偏移量
            offSetY = (height - width) / 2
            height = width
        } else {
            //X轴偏移量
            offSetX = (width - height) / 2
            width = height
        }
    
        //单元格宽度
        var pointWidth = width / 3
    
        //外圆大小
        outDotWidth = width / 12f
        //内圆大小
        inDotWidth = outDotWidth / 6
    
        //点的位置
        mPoints[0][0] = Point(offSetX + pointWidth / 2, offSetY + pointWidth / 2, 0)
        mPoints[0][1] = Point(offSetX + pointWidth * 3 / 2, offSetY + pointWidth / 2, 1)
        mPoints[0][2] = Point(offSetX + pointWidth * 5 / 2, offSetY + pointWidth / 2, 2)
        mPoints[1][0] = Point(offSetX + pointWidth / 2, offSetY + pointWidth * 3 / 2, 3)
        mPoints[1][1] = Point(offSetX + pointWidth * 3 / 2, offSetY + pointWidth * 3 / 2, 4)
        mPoints[1][2] = Point(offSetX + pointWidth * 5 / 2, offSetY + pointWidth * 3 / 2, 5)
        mPoints[2][0] = Point(offSetX + pointWidth / 2, offSetY + pointWidth * 5 / 2, 6)
        mPoints[2][1] = Point(offSetX + pointWidth * 3 / 2, offSetY + pointWidth * 5 / 2, 7)
        mPoints[2][2] = Point(offSetX + pointWidth * 5 / 2, offSetY + pointWidth * 5 / 2, 8)
    }
    

    图画得不是很标准,放一张图方便理解

    1. 考虑到横竖屏的问题,所以会设置两个方向的偏移量。如果是竖屏对应 y 轴偏移量为 0,如果是横屏对应 x 轴偏移量为0
    2. 九宫格在屏幕的中间,所以对应的竖屏偏移量为 ( height - width ) / 2,横屏为( width - height ) / 2
    3. 一个圆占屏幕的 1/3,所以圆的直径为 width / 3 ,半径为 width / 6
    4. 得到上面的数据,依次就可以算出 9 宫格每个中心点的坐标,最后将大圆和小圆绘制出来

    2、手指触摸更改圆的颜色

    override fun onTouchEvent(event: MotionEvent): Boolean {
        mMoveX = event.x
        mMoveY = event.y
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                val point = point
                if (point != null) {
                    isTouchPoint = true
                    selectPoint.add(point)
                    point.setStatusPress()
                }
            }
            MotionEvent.ACTION_MOVE -> {
                if (isTouchPoint) {
                    val point = point
                    if (point != null) {
                        if (!selectPoint.contains(point)) {
                            selectPoint.add(point)
                        }
                        point.setStatusPress()
                    }
                }
            }
        }
        invalidate()
        return true
    }
    
    1. 首先确定手指触摸的范围是否在圆内,如果不在圆内则不处理,如果在圆内就修改当前点的状态
    2. 当手指在屏幕上移动时,判断移动的位置是否包含了点,如果没有包含则将点添加并修改状态,如果有则不处理。

    3、画线

    private fun drawLine(start: Point, end: Point, canvas: Canvas, paint: Paint) {
        //拿到2点的坐标和坐标差
        val startX = start.centerX
        val startY = start.centerY
        val endX = end.centerX
        val endY = end.centerY
        val dx = endX - startX
        val dy = endY - startY
        //计算2点的位置
        val d = (sqrt((dx * dx + dy * dy).toDouble())).toFloat()
    
        val rx = dx / d * inDotWidth
        val ry = dy / d * inDotWidth
    
        canvas.drawLine(startX + rx, startY + ry, endX - rx, endY - ry, paint)
    
    }
    

    如果从点中间会稍微影响九宫格的美观,所以要减去多余的长度。贴一张图,方便理解计算规则

    4、处理手指抬起

    MotionEvent.ACTION_UP -> {
        isTouchPoint = false
        when {
            selectPoint.size == 1 -> {
                 clearSelectPoints()
            }
            
            selectPoint.size <= 4 -> {
                showSelectError()
            }
          
            else -> {
                showSelectRight()
            }
        }
    }
    

    这里处理比较简单:当只存在 1 个点时清空状态;小于 4 个点时显示错误;其他情况就显示正确

    自定义九宫格就介绍到这里了,如果有什么写得不对的,可以在下方评论留言,我会第一时间改正。

    Github 源码链接

    相关文章

      网友评论

        本文标题:Android 从 0 开始学习自定义 View(十一) 自定义

        本文链接:https://www.haomeiwen.com/subject/cuuzeltx.html