android 自定义view 画饼图
实现难点
通过canvas.drawArc()来画出扇形,关键在于角度的计算和计算表述线的位置。具体的实现逻辑看下面的分解
实现逻辑
for (int j = 0; j < i; j++) {
//计算之前的角度之和
degree += mBeanList.get(j).getF();
}
int arcDegree = (int) (mBeanList.get(i).getF() * 360);
canvas.drawArc(xWidth - radius, yHeight - radius, xWidth + radius, yHeight + radius, (float) (degree * 360), arcDegree, true, mPaint);
int lineDegree = (int) (degree * 360 + (arcDegree / 2));
float x = (float) (radius * Math.cos(Math.toRadians(lineDegree)));
float y = (float) (radius * Math.sin(Math.toRadians(lineDegree)));
- 移动到当前点,然后画线,其中xM表示短的表述线x轴的长度,xxM表示长的表述线x轴的长度,yM表示长的表述线的y轴的长度,通过对角度的判断,选择表述线的方向。
mPath.moveTo(xWidth + x, yHeight + y);
int xM = 30;
int xxM = 110;
int yM = 80;
if (lineDegree > 90 && lineDegree < 180) {
xM = -xM;
xxM = -xxM;
} else if (lineDegree >= 180 && lineDegree <= 270) {
xM = -xM;
xxM = -xxM;
yM = -yM;
}
mPath.lineTo(xWidth + x + xM, yHeight + y);
mPath.lineTo(xWidth + x + xxM, yHeight + y + yM);
mPaint.setColor(Color.BLACK);
canvas.drawPath(mPath, mPaint);
canvas.drawText(mBeanList.get(i).getName(), xWidth + x + xxM, yHeight + y + yM, mPaint)
mPath.reset();
View源码
public class XunView extends View {
List<Bean> mBeanList;
Paint mPaint;
Path mPath;
int width;
int height;
int radius;
public XunView(Context context) {
this(context, null);
}
public XunView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public XunView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mBeanList = new ArrayList<>();
mPaint = new Paint();
mPath = new Path();
radius = 200;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
this.width = getWidth();
this.height = getHeight();
}
public List<Bean> getBeanList() {
return mBeanList;
}
public void setBeanList(List<Bean> beanList) {
mBeanList = beanList;
this.invalidate();
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int xWidth = width / 2;
int yHeight = height / 2;
for (int i = 0; i < mBeanList.size(); i++) {
mPaint.setColor(mBeanList.get(i).getColor());
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(30);
mPaint.setStrokeWidth(5);
double degree = 0;
for (int j = 0; j < i; j++) {
degree += mBeanList.get(j).getF();
}
int arcDegree = (int) (mBeanList.get(i).getF() * 360);
canvas.drawArc(xWidth - radius, yHeight - radius, xWidth + radius, yHeight + radius, (float) (degree * 360), arcDegree, true, mPaint);
int lineDegree = (int) (degree * 360 + (arcDegree / 2));
float x = (float) (radius * Math.cos(Math.toRadians(lineDegree)));
float y = (float) (radius * Math.sin(Math.toRadians(lineDegree)));
mPaint.setStyle(Paint.Style.STROKE);
mPath.moveTo(xWidth + x, yHeight + y);
int xM = 30;
int xxM = 110;
int yM = 80;
if (lineDegree > 90 && lineDegree < 180) {
xM = -xM;
xxM = -xxM;
} else if (lineDegree >= 180 && lineDegree <= 270) {
xM = -xM;
xxM = -xxM;
yM = -yM;
}
mPath.lineTo(xWidth + x + xM, yHeight + y);
mPath.lineTo(xWidth + x + xxM, yHeight + y + yM);
mPaint.setColor(Color.BLACK);
canvas.drawPath(mPath, mPaint);
canvas.drawText(mBeanList.get(i).getName(), xWidth + x + xxM, yHeight + y + yM, mPaint);
mPaint.setStyle(Paint.Style.FILL);
mPath.reset();
}
}
}
bean实体
public class Bean {
private double f;
private int mColor;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getF() {
return f;
}
public void setF(double f) {
this.f = f;
}
public int getColor() {
return mColor;
}
public void setColor(int color) {
mColor = color;
}
}
Activity中的调用
public class MainActivity extends AppCompatActivity {
XunView mXunView
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mXunView = (XunView) findViewById(R.id.bing_view)
ArrayList<Bean> list = new ArrayList<>()
Bean bean = new Bean()
bean.setColor(Color.argb(255, 255, 154, 50))
bean.setF(0.2)
bean.setName("JAVA")
Bean bean1 = new Bean()
bean1.setColor(Color.argb(255, 101, 50, 151))
bean1.setF(0.2)
bean1.setName("GB")
Bean bean2 = new Bean()
bean2.setColor(Color.argb(255, 0, 153, 49))
bean2.setF(0.2)
bean2.setName("C++")
Bean bean3 = new Bean()
bean3.setColor(Color.argb(255, 0, 204, 253))
bean3.setF(0.3)
bean3.setName("C#")
Bean bean4 = new Bean()
bean4.setColor(Color.argb(255, 254, 0, 0))
bean4.setF(0.1)
bean4.setName("VB")
list.add(bean)
list.add(bean1)
list.add(bean2)
list.add(bean3)
list.add(bean4)
mXunView.setBeanList(list)
}
}
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:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.moneyview.MainActivity"
>
<com.example.moneyview.XunView
android:id="@+id/bing_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
效果图