实战酷毙了的自定义View(二)

Gtihub传送门

Canvas的高级使用

在个人Github开源库中,今天刚写好了一个饼图的绘制,这里主要就是对饼图绘制的一个讲解了。ios

以前咱们讲过了一个Path,可是若是全用Path去实现,也不是说不可以实现,可是并不适用于不少的场景状况。git

这里的话,咱们主要讲的就是关于Canvas的使用了。以前咱们在Path中用到过这样的一个函数moveTo,也就是把路径从当前的位置移动到新的坐标上。那咱们的Canvas是否有这样的功能呢?github

天然是有的了,这里直接做出一个解答,他的函数就是translate,可是有一点要注意!!!这个函数是一个相对移动,而不是绝对移动。canvas

canvas?.translate(60f, 80f)
paint?.let { canvas?.drawCircle(0f, 0f, 100f, it) }
canvas?.translate(60f, 80f)paint?.color = Color.BLUE
paint?.let { canvas?.drawCircle(0f, 0f, 100f, it) }
复制代码

上述就是实现代码以及一个贴图了。你能够直观的感觉到这个移动实际上是基于当前的基础来完成的。可是读者会说了,这种效果彻底可让我经过Path来完成啊,不必经过Canvas,ok,确实能够,你也能够经过Path来实现。函数

可是难点如今才来,下图的样式该怎么实现??工具

在知道怎么写代码以前,那咱们要知道确定是他的组成成分究竟是什么了。布局

  1. 两条线的组合。从直观上就能够看出,这个折线应该是两条直线进行组合
  2. 两行文字的组合。也就是图片中的描述四和6.0%

若是让咱们直接去获取绝对坐标,而后进行绘制,那是否是会很是麻烦呢?因此这里要引入一个Canavs的操做方法。post

Canvas操做

在使用以前须要注意,画布是须要保存的,否则画布将不断的保留上一次的状态进行绘制,那总体就会呈现一种叠加混乱的局面。而这个方法就是save()restore()的成对使用。学习

for (i in 0..2) {
        canvas?.save()
        paint?.color = Color.BLUE
        canvas?.translate(60f, 80f)
        canvas?.scale(0.5f, 0.5f)
        paint?.let { canvas?.drawCircle(0f, 0f, 100f, it) }
        canvas?.restore()
    }
复制代码
使用前 使用后

你能够把这个操做理解为画布归位,或者说画布重置。而这个重置对应的就是保存了save()以前的操做过程。ui

Scale

这个效果再也不赘述了。

Rotate

和其余的都是同样的会有两种画布的操做函数

  1. rotate(float degrees, float px, float py),就是自定义旋转圆心
  2. rotate(float degrees),画布当前位置做为旋转圆心
canvas?.save()
paint?.color = Color.BLUE
canvas?.translate(60f, 80f)
canvas?.rotate(45f)
// 以自身中心做为圆点旋转
// canvas?.rotate(45f,30f, 40f)
paint?.let { canvas?.drawRect(0f, 0f, 100f, 100f, it) }
canvas?.restore()
复制代码

饼图的实现其实就是基于这个函数来完成的。

Shew

和其余的不一样了,他并再也不经过咱们的坐标圆心,而是对标咱们XY

canvas?.save()
paint?.color = Color.BLUE
canvas?.translate(60f, 80f)
canvas?.skew(0f, 1f)
paint?.let { canvas?.drawRect(0f, 0f, 100f, 100f, it) }
canvas?.restore()
复制代码

传入的数据其实就是分别与XY轴的正切值,经过截图工具,你可以明显的发现这个问题。画了绿色框框的部分,你能够看到的是正好一个45度的大小。

经过画图你也能够这样理解,就是Y轴顺时针方向旋转45度。

饼图绘制的基本思路

上面讲过了画布的一些基本操做,那咱们要具体讲一下这个饼图咱们该怎么绘制了。讲实话,我代码里已经基本注释了,因此具体的以代码为准,这里只作简单的讲解。几个考虑部分:

  1. 圆和文字怎么兼容,这是一个重难点,我也只能说经过屡次尝试,到圆为0.3倍的宽度最为合适了。由于0.5倍,正好占满;0.4倍,文字过小。这个值你能够自行作一个修改处理。
  2. 上面说过的介绍线怎么画。文字的的布局确定直接根据介绍线来变更了,那这个介绍线就是相当重要的一点了。
  3. 弧形的颜色怎么变换。

基本就是以上问题,问题1我已经作出来回答,后续两个问题将一个个做出解释。

介绍线怎么画

在个人代码中,其实分为两块,一是圆弧,一是介绍,这也是他们的绘制顺序了。可是须要考虑一个问题:介绍线的位置肯定?

这个问题你须要看一下个人图例了,你有没有注意到,个人介绍线,好像都是关于单个圆弧居中的呢?

那咱们的方案其实就来了,上面咱们讲到过了什么?Rotate还记得这个函数嘛!!经过数据运算,有了每一个圆弧的大小,那咱们还不能去进行绘制嘛?不就是先划线,再旋转吗。而后旋转就是这样的一个公式要去计算。

// 旋转角度 = 前面的弧度 + 当前弧度的一半
private fun getRatioSum(j: Int): Float {
        var sum = 0f
        for (i in 0 until j) {
            sum += mRatios!![i]
        }
        return sum
    }

    private fun getRatioHalfSumDegrees(j: Int): Float {
        var sum = getRatioSum(j)
        sum += mRatios!![j] / 2
        return sum * 360
    }
复制代码

弧形的颜色怎么变换

跟前面的圆弧同样,可是是一个个圆弧来组成圆,那这个时候,就是要知道前面的弧度,而后对当前的弧度的计算,也就是扫过的区间进行计算了。

private fun drawArc(canvas: Canvas) {
        val drawArc = 360 * scale
        for (i in mRatios!!.indices) {
            mArcPaint?.color = mArcColors!![i]
            mArcPaint?.let {
                canvas.drawArc(
                    arcRect!!,
                    getRatioSum(i) * drawArc,
                    mRatios!![i] * drawArc,
                    true,
                    it
                )
            }
        }
    }
复制代码

基本上就是靠上述的两个来完成的,是否是仍是比较简单的呢。冲冲冲,Demo抄起来,你就有一份本身的饼图绘制了。

以上就是个人学习成果,若是有什么我没有思考到的地方或是文章内存在错误,欢迎与我分享。


相关文章推荐:

实战酷毙了的自定义View(一)

【从零冲击音视频开发】FFmpeg的介绍和基本使用

【从零冲击音视频开发】移动环境搭建

相关文章
相关标签/搜索