先看下效果
在上一篇随笔中, 我们用到了画弧的方法,
1 /** 2 * <p> 3 * Draw the specified arc, which will be scaled to fit inside the specified oval. 4 * </p> 5 * <p> 6 * If the start angle is negative or >= 360, the start angle is treated as start angle modulo 7 * 360. 8 * </p> 9 * <p> 10 * If the sweep angle is >= 360, then the oval is drawn completely. Note that this differs 11 * slightly from SkPath::arcTo, which treats the sweep angle modulo 360. If the sweep angle is 12 * negative, the sweep angle is treated as sweep angle modulo 360 13 * </p> 14 * <p> 15 * The arc is drawn clockwise. An angle of 0 degrees correspond to the geometric angle of 0 16 * degrees (3 o'clock on a watch.) 17 * </p> 18 * 19 * @param startAngle Starting angle (in degrees) where the arc begins 20 * @param sweepAngle Sweep angle (in degrees) measured clockwise 21 * @param useCenter If true, include the center of the oval in the arc, and close it if it is 22 * being stroked. This will draw a wedge 23 * @param paint The paint used to draw the arc 24 */ 25 public void drawArc(float left, float top, float right, float bottom, float startAngle, 26 float sweepAngle, boolean useCenter, @NonNull Paint paint) { 27 super.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint); 28 }
我们注意到这里的 useCenter如果为true的话, canvas就会帮我们把弧形闭合
那么我们很容易想到,饼图不就是一个个闭合的弧么
1 private val RADIUS = 150f.toPx 2 private val SWEEP_ANGLES = arrayListOf(50f, 90f,30f, 120f,70f) 3 private val COLORS = arrayListOf("#FF6200EE", "#FF03DAC5","#FF000000", "#FFBB86FC","#FF0080") 4 private val OFF_LENGTH= 20f.toPx 5 class PieView(context: Context, attributeSet: AttributeSet): View(context, attributeSet) { 6 7 val paint = Paint(Paint.ANTI_ALIAS_FLAG) 8 override fun onDraw(canvas: Canvas) { 9 var startAngle = 0f 10 SWEEP_ANGLES.forEachIndexed { index, fl -> 11 paint.color = Color.parseColor(COLORS[index]) 12 //偏移的两种方式 13 // if(index == 0){ 14 // //先保存之前的canvas 15 // canvas.save() 16 // //canvas偏移 17 // canvas.translate((OFF_LENGTH*cos(Math.toRadians((fl/2).toDouble()))).toFloat(), 18 // (OFF_LENGTH* sin(Math.toRadians((fl/2).toDouble()))).toFloat() 19 // ) 20 // } 21 // canvas.drawArc(width/2f- RADIUS, height/2f- RADIUS, width/2f + RADIUS, height/2f + RADIUS, 22 // startAngle, fl, true, paint 23 // ) 24 // if (index == 0){ 25 // //偏移完之后再还原回来 26 // canvas.restore() 27 // } 28 if(index == 0){ 29 canvas.drawArc(width/2f- RADIUS + (OFF_LENGTH*cos(Math.toRadians((fl/2).toDouble()))).toFloat(), 30 height/2f- RADIUS + (OFF_LENGTH* sin(Math.toRadians((fl/2).toDouble()))).toFloat(), 31 width/2f + RADIUS + (OFF_LENGTH*cos(Math.toRadians((fl/2).toDouble()))).toFloat(), 32 height/2f + RADIUS + (OFF_LENGTH* sin(Math.toRadians((fl/2).toDouble()))).toFloat(), 33 startAngle, fl, true, paint 34 ) 35 }else { 36 canvas.drawArc(width/2f- RADIUS, height/2f- RADIUS, width/2f + RADIUS, height/2f + RADIUS, 37 startAngle, fl, true, paint 38 ) 39 } 40 startAngle += fl 41 } 42 } 43 }
代码比较简单,不再赘述
注意一点, 当我们使用 canvas.translate(x, y)去进行偏移时, 需要在偏移完成之后进行restore(),所以偏移之前要调用canvas.save()保存状态