最近项目中有这个需求,将总资产的组成以图形的形态展现出来,所以就写了个自定义View来实现这个需求。
其实试下这个思路还是挺简单的,因为只需要在onDraw方法中使用画笔画出一个又一个的扇形,就能实现这样的效果。
以下是我的思路,首先介绍下canvas.drawArc()方法。
RectF rectF = new RectF(100, 100, 500, 500);
//绘制扇形
canvas.drawArc(rectF, startAngle, endAngle, true, paint);
参数说明:
rectF:绘制扇形的区域
startAngle:扇形的开始绘制的角度(是角度值不是弧度值)
endAngle:扇形绘制结束的角度值
true:是否从圆心开始画扇形
paint:画笔
所以实现起来的思路就是:
通过给定的数据值,也就是一个包含数字的数组,然后算出每个数字的比重,乘上360度,算出每个数字所占的扇形的角度值,然后通过给不同数字的画上颜色不同的扇形,当处理完所有的数据后,就可以看到由不同颜色扇形所组成的一个圆,这当然不是我们所想要的,所以在最后,以相同的圆心画一个白色的圆,当然这个圆的半径要比刚刚那个彩色的圆的半径要小,最后剩下的就是我们想要的结果,最后在扇形的中间写上我们需要的文字即可。
这个是画上几个扇形后的效果。
在中间画一个白色的圆之后就变成这样的了
其实这个时候就已经初见成效了。最后加上文字就好了。
最后提供自定义的控件。
SelfStatistics.java
package com.cretin.testprogress.views;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/**
* Created by cretin on 16/6/23.
*/
public class SelfStatistics extends View {
private Paint paint;
//对外提供注入数据的变量
private float[] datas;
//自定义view内部存储数据信息
private List<Infos> listDatas = new ArrayList<>();
//默认统计图的颜色配置 如果数据大于4 则颜色轮询
private String colorRes[] = new String[]{"#fdb128", "#4a90e2", "#89c732", "#f46950"};
private int mPanelWidth;
public SelfStatistics(Context context) {
super(context);
init();
}
private void init() {
paint = new Paint();
}
public SelfStatistics(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SelfStatistics(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SelfStatistics(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public float[] getDatas() {
return datas;
}
public void startDraw() {
invalidate();
}
public void setDatas(float[] datas) {
this.datas = datas;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (datas != null && datas.length > 0) {
calculateDatas();
//获取圆心的x坐标
int center = mPanelWidth / 2;
//圆环的半径
int radius = center - 10;
//消除锯齿
paint.setAntiAlias(true);
//给外圈设置样式
paint.setStyle(Paint.Style.FILL_AND_STROKE);
//设置StrokeWidth
paint.setStrokeWidth(20);
//给外圈设置颜色
paint.setColor(Color.WHITE);
//画最外层的圈
canvas.drawCircle(center, center, radius, paint);
//设置进度的颜色
for (Infos infos : listDatas) {
//定义一个RectF类
paint.setColor(Color.parseColor(infos.getColor()));
RectF rectF = new RectF(center - radius, center - radius, center + radius, center + radius);
//绘制扇形
canvas.drawArc(rectF, infos.getStartAngle(), infos.getEndAngle(), true, paint);
}
//画最外层的圈
paint.setColor(Color.WHITE);
canvas.drawCircle(center, center, radius - 50, paint);
drawTexts(canvas, center);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = Math.min(widthSize, heightSize);
if (widthMode == MeasureSpec.UNSPECIFIED) {
width = heightSize;
} else if (heightMode == MeasureSpec.UNSPECIFIED) {
width = widthSize;
}
setMeasuredDimension(width, width);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mPanelWidth = Math.min(w,h);
}
private void drawTexts(Canvas canvas, int center) {
float total = 0;
for (int i = 0; i < datas.length; i++) {
total += datas[i];
}
String totalStr = total + "元";
paint.setStrokeWidth(2);
//设置进度扇形的样式
paint.setStyle(Paint.Style.FILL);
//设置文字的大小
paint.setTextSize(35);
int widthStr1 = (int) paint.measureText("总资产");
int widthStr2 = (int) paint.measureText(totalStr);
paint.setColor(Color.parseColor("#333333"));
float baseX = center - widthStr1 / 2;
float baseY = center + 20 / 4;
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;
float offY = fontTotalHeight / 2 - fontMetrics.bottom - 30;
float newY = baseY + offY;
canvas.drawText("总资产", baseX, newY, paint);
paint.setColor(Color.parseColor("#fc561f"));
float baseX1 = center - widthStr2 / 2;
float baseY1 = center + 20 / 4;
Paint.FontMetrics fontMetrics1 = paint.getFontMetrics();
float fontTotalHeight1 = fontMetrics1.bottom - fontMetrics1.top;
float offY1 = fontTotalHeight1 / 2 - fontMetrics1.bottom + 30;
float newY1 = baseY1 + offY1;
canvas.drawText(totalStr, baseX1, newY1, paint);
}
//为绘画做基本的计算
private void calculateDatas() {
float total = 0;
float tempAngle = 270;
//计算出总数
for (int i = 0; i < datas.length; i++) {
total += datas[i];
}
//创建不同的Infos对象
Infos infos;
for (int i = 0; i < datas.length; i++) {
infos = new Infos();
float currData = datas[i];
float startAngle = tempAngle;
float endAngle = (float) (currData * 100 / total * 3.6);
infos.setStartAngle(startAngle);
infos.setEndAngle(endAngle);
infos.setColor(colorRes[i % colorRes.length]);
tempAngle = endAngle + tempAngle;
listDatas.add(infos);
}
}
class Infos {
private float startAngle;
private float endAngle;
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public float getStartAngle() {
return startAngle;
}
public void setStartAngle(float startAngle) {
this.startAngle = startAngle;
}
public float getEndAngle() {
return endAngle;
}
public void setEndAngle(float endAngle) {
this.endAngle = endAngle;
}
}
}
最后提供使用的方法:
布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.cretin.testprogress.MainActivity">
<com.cretin.testprogress.views.SelfStatistics
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
主函数的调用:
package com.cretin.testprogress;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.cretin.testprogress.views.SelfStatistics;
public class MainActivity extends AppCompatActivity {
private SelfStatistics selfStatistics;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
selfStatistics = (SelfStatistics) findViewById(R.id.progress);
float datas[] = new float[]{4000,3000,7000,8000};
selfStatistics.setDatas(datas);
selfStatistics.startDraw();
}
}
最后我写了一个demo,欢迎下载,重在分享,不要积分哦,哈哈
下载地址为:http://download.csdn.net/detail/u010998327/9557747