# 自定义控件之圆形统计图表

## 思路篇：

`class Element(@ColorInt val color: Int, val progress: Float)`

```override fun onDraw(canvas: Canvas?)
{
var angle = startAngle//起始画的角度
paint.strokeWidth = strokeWidth;//画笔的宽度
var allValue = 0f//list里所有值得总数
multiElement.all { entry -> //这里把所有遍历，拿到总数
allValue += entry.value
true
}
for (entry in multiElement)
{
val sweepAngle = (entry.value.toFloat() / allValue) * 360//这里算出当前值除以总和，再乘以360度，得出本次item所占的角度
paint.color = entry.key//设置颜色
canvas?.drawArc(rectf, angle, sweepAngle, false, paint)//开始画
angle += sweepAngle//下一个画的开始，则是这次的结尾，因为需要衔接起来画一个圆
}
super.onDraw(canvas)
}```

```private val rectf by lazy {
when
{
mWidth > mHeight  -> RectF(mWidth / 2 - mHeight / 2 + strokeWidth / 2, 0f + strokeWidth / 2, mWidth / 2 - mHeight / 2 + mHeight - strokeWidth / 2, mHeight - strokeWidth / 2)
mWidth == mHeight -> RectF(0f + strokeWidth / 2, 0f + strokeWidth / 2, min(mWidth, mHeight) - strokeWidth / 2, min(mWidth, mHeight) - strokeWidth / 2)
else              -> RectF(0f + strokeWidth / 2, mHeight / 2 - mWidth / 2 + strokeWidth / 2, mWidth - strokeWidth / 2, mHeight / 2 - mWidth / 2 + mWidth - strokeWidth / 2)
}
}```

## 代码篇

```package com.yongxing.HuYing.widgets

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.support.annotation.ColorInt
import android.support.v4.util.ArrayMap
import android.util.AttributeSet
import android.view.View
import com.yongxing.HuYing.utils.DensityUtil
import kotlin.math.min

/**
* Created by xiaolei on 2017/11/29.
*/

class MultiElementProgress @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr)
{
private var strokeWidth = 20f //画笔宽度
private var startAngle = -45f //开始角度
private val paint by lazy {
Paint().apply {
isAntiAlias = true
color = Color.RED
style = Paint.Style.STROKE
strokeWidth = this@MultiElementProgress.strokeWidth
}
}
private val rectf by lazy {
when
{
mWidth > mHeight  -> RectF(mWidth / 2 - mHeight / 2 + strokeWidth / 2, 0f + strokeWidth / 2, mWidth / 2 - mHeight / 2 + mHeight - strokeWidth / 2, mHeight - strokeWidth / 2)
mWidth == mHeight -> RectF(0f + strokeWidth / 2, 0f + strokeWidth / 2, min(mWidth, mHeight) - strokeWidth / 2, min(mWidth, mHeight) - strokeWidth / 2)
else              -> RectF(0f + strokeWidth / 2, mHeight / 2 - mWidth / 2 + strokeWidth / 2, mWidth - strokeWidth / 2, mHeight / 2 - mWidth / 2 + mWidth - strokeWidth / 2)
}
}
private val multiElement by lazy { ArrayMap<Int, Float>() }
private var mHeight: Float = 0f
private var mWidth: Float = 0f

init
{
multiElement.put(Color.parseColor("#f9a844"), 50f)
multiElement.put(Color.parseColor("#b5db39"), 50f)
strokeWidth = DensityUtil.dip2px(context, 16f).toFloat()
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
{
mHeight = View.MeasureSpec.getSize(heightMeasureSpec).toFloat()
mWidth = View.MeasureSpec.getSize(widthMeasureSpec).toFloat()
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}

override fun onDraw(canvas: Canvas?)
{
var angle = startAngle
paint.strokeWidth = strokeWidth;
var allValue = 0f
multiElement.all { entry ->
allValue += entry.value
true
}
for (entry in multiElement)
{
val sweepAngle = (entry.value.toFloat() / allValue) * 360
paint.color = entry.key
canvas?.drawArc(rectf, angle, sweepAngle, false, paint)
angle += sweepAngle
}
super.onDraw(canvas)
}

/**
* 设置每一个选项的 Item
*/
public fun setProgress(elements: List<Element>)
{
multiElement.clear()
for (element in elements)
{
multiElement.put(element.color, element.progress)
}
postInvalidate()
}

/**
* 设置画笔宽度
*/
public fun setStrokeWidth(strokeWidth: Float)
{
this.strokeWidth = strokeWidth
postInvalidate()
}

/**
* 设置开始画的角度
*/
public fun setStartAngle(startAngle: Float)
{
this.startAngle = startAngle
postInvalidate()
}

public class Element(@ColorInt val color: Int, val progress: Float)

}```

64 篇文章25 人订阅

0 条评论

## 相关文章

1412

### Palette状态栏颜色提取，写的不错就分享了

Palette 说Palette之前先说下前面提到的Pager。ViewPager是什么大家应该都是知道的了，一般ViewPager、xxxTabStrip...

2346

4662

1.1K8

### Android开发之View动画

Android动画主要分为3种 View动画 帧动画 属性动画 何为View动画？ View动画主要是对View对象进行变换所达到的动画效果，如平移、缩放、旋转...

2765

1063

### View的位置参数及其Scroller类的理解

x和y是View左上角的坐标，translationX和translationY是View左上角相对于容器的偏移量。这几个参数都是相对于父容器的坐标。

1204

2092

2965

4257