自定义View饼状图的绘制
package com.loaderman.customviewdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
/**
* Created by MQ on 2016/12/15.
*/
public class CakeView extends View {
//装载的饼状圆数据
private List<CakeBean> beanList;
//画圆的矩形
private RectF mRectF;
//右边的小矩形
private RectF iRectF;
private Paint mPaint;
private int mRWidth, mRHeight;
private float rotateDegree;//每个圆弧的起始角度
private float sumValue = 0;//所有值的和
private float diameter;//圆的直径
private float textY;//绘制文字的Y坐标
private float mRectHeight = 40;//矩形高度
private float mRectWidth = 80;//矩形宽度
private float mMargin = 40;//矩形和圆的距离
private Context mContext;
public CakeView(Context context) {
//CakeView cakeView=new CakeView(context);
// 在代码中new CakeView()会调用这个构造函数
this(context, null);
}
public CakeView(Context context, AttributeSet attrs) {
//InflateLayoutManager时会调用这个构造函数
this(context, attrs, 0);
}
public CakeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
init();
}
private void init() {
beanList = new ArrayList<>();
mRectF = new RectF();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//MeasureSpec封装了父View传递给子View的布局要求
int wMode = MeasureSpec.getMode(widthMeasureSpec);
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
switch (wMode) {
case MeasureSpec.EXACTLY:
//相当于match_parent或者一个具体值
mRWidth = wSize;
break;
case MeasureSpec.AT_MOST:
// 相当于wrap_content 默认会充满父View
// 可以根据子View的大小来计算父View大小,这里先写死大小
mRWidth = (int) DpUtil.dp2px(mContext, 400f);
break;
case MeasureSpec.UNSPECIFIED:
//很少会用到
break;
default:
break;
}
switch (hMode) {
case MeasureSpec.EXACTLY:
//相当于match_parent或者一个具体值
mRHeight = hSize;
break;
case MeasureSpec.AT_MOST:
// 相当于wrap_content 默认会充满父View
// 可以根据子View的大小来计算父View大小,这里先写死大小
mRHeight = (int) DpUtil.dp2px(mContext, 200f);
break;
case MeasureSpec.UNSPECIFIED:
//很少会用到
break;
default:
break;
}
//存储测量好的宽和高
setMeasuredDimension(wSize, hSize);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
diameter = Math.min(mRWidth, mRHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
textY = 0f;
//设置圆形绘制的范围
mRectF.set(0, 0, diameter, diameter);
//画布中心X坐标向右移动(控件宽度-圆直径)之差的八分之一的距离
//画布中心Y坐标向下移动(控件宽度-圆直径)之差的二分之一的距离
canvas.translate((mRWidth - diameter) / 8, (mRHeight - diameter) / 2);
if (beanList.size() > 0 && Float.compare(sumValue, 0.0f) != 0) {
for (int i = 0; i < beanList.size(); i++) {
CakeBean bean = beanList.get(i);
//画圆弧
mPaint.setColor(bean.mColor);
canvas.drawArc(mRectF, rotateDegree, bean.degree, true, mPaint);
rotateDegree += bean.degree;
//画矩形和文字
drawRectAndText(canvas, bean);
}
}
}
private void drawRectAndText(Canvas canvas, CakeBean bean) {
iRectF = new RectF();
//设置画矩形的范围
float left = diameter + mMargin;
float right = diameter + mMargin + mRectWidth;
float bottom = textY + mRectHeight;
iRectF.set(left, textY, right, bottom);
canvas.drawRect(iRectF, mPaint);
//设置颜色
mPaint.setColor(Color.BLACK);
//设置文字大小
mPaint.setTextSize(30);
//画文字
canvas.drawText(bean.name + "(" + new DecimalFormat(".00").format(bean.value / sumValue * 100) + "%)", right + 10, textY + 30, mPaint);
textY += mRectHeight;
}
/**
* 饼状图添加数据
*
* @param beans CakeBean数据
*/
public void setData(List<CakeBean> beans) {
if (beans == null || beans.size() <= 0) return;
for (int i = 0; i < beans.size(); i++) {
CakeBean bean = beans.get(i);
sumValue += bean.value;
}
for (int i = 0; i < beans.size(); i++) {
CakeBean bean = beans.get(i);
bean.degree = bean.value / sumValue * 360;
beanList.add(bean);
}
invalidate();
}
/**
* @param startDegree 设置起始角度
*/
public void setStartDegree(float startDegree) {
this.rotateDegree = startDegree;
invalidate();
}
}
package com.loaderman.customviewdemo;
import java.io.Serializable;
public class CakeBean implements Serializable {
public String name;//名字
public float value;//值
public float degree;//旋转过的角度
public int mColor;//圆弧颜色
}
package com.loaderman.customviewdemo;
import android.app.Activity;
import android.content.Context;
import android.util.DisplayMetrics;
/**
* Created by MQ on 2016/12/16.
*/
public class DpUtil {
/**
* dp转换成px
*
* @param context Context
* @param dp dp
* @return px值
*/
public static float dp2px(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return dp * scale + 0.5f;
}
/**
* sp转换成px
*
* @param context Context
* @param sp sp
* @return px值
*/
public static float sp2px(Context context, float sp) {
final float scale = context.getResources().getDisplayMetrics().scaledDensity;
return sp * scale;
}
/**
* 获得屏幕宽度
*
* @param context Context
* @return 屏幕宽度(像素)
*/
public static int getScreenSizeWidth(Context context) {
DisplayMetrics metric = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metric);
return metric.widthPixels;
}
}
package com.loaderman.customviewdemo;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private List<CakeBean> beans;
private String[] names = {"php", "object-c", "c", "c++", "java", "android", "linux"};
private float[] values = {2f, 2f, 3f, 4f, 5f, 6f, 7f};
private int[] colArrs = {Color.RED, Color.parseColor("#4ebcd3"), Color.MAGENTA, Color.YELLOW, Color.GREEN, Color.parseColor("#f68b2b"), Color.parseColor("#6fb30d")};//圆弧颜色
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CakeView cake_view = (CakeView) findViewById(R.id.cake_view);
initData();
cake_view.setData(beans);
}
private void initData() {
beans = new ArrayList<>();
for (int i = 0; i < 7; i++) {
CakeBean bean = new CakeBean();
bean.name = names[i];
bean.value = values[i];
bean.mColor = colArrs[i];
beans.add(bean);
}
}
}
效果图:

最后,关注【码上加油站】微信公众号后,有疑惑有问题想加油的小伙伴可以码上加入社群,让我们一起码上加油吧!!!
浙公网安备 33010602011771号