首先就是在gradle文件中引用
compile 'com.github.PhilJay:MPAndroidChart:v3.0.2'
重写PieChart和PieChartRenderer
-
import android.content.Context; import android.content.res.TypedArray; import android.graphics.PointF; import android.util.AttributeSet; import android.view.MotionEvent; import com.github.mikephil.charting.charts.PieChart; import com.loumeng.intelligencehospital.R; /** * Created by liufang on 2018/12/14. */ public class MyPieChart extends PieChart { public MyPieChart(Context context) { this(context, null); } public MyPieChart(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyPieChart(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); getAttrs(attrs); } private void getAttrs(AttributeSet attrs) { if (attrs != null) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MPAndroidChartUtil); String mode = a.getString(R.styleable.MPAndroidChartUtil_mp_chart_out_value_place_mode); boolean auto_adapt_text_size = a.getBoolean(R.styleable.MPAndroidChartUtil_mp_chart_auto_adapt_text_size, false); a.recycle(); ((MyPieChartRenderer) mRenderer).setMode(mode); ((MyPieChartRenderer) mRenderer).setAuto_adapt_text_size(auto_adapt_text_size); } } @Override protected void init() { super.init(); //此处把mRenderer替换成我们自己的PieChartRenderer mRenderer = new MyPieChartRenderer(this, mAnimator, mViewPortHandler); } }
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.data.PieEntry;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.IPieDataSet;
import com.github.mikephil.charting.renderer.PieChartRenderer;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
import java.util.List;
/**
* Created by liufang on 2018/12/14.
*/
public class MyPieChartRenderer extends PieChartRenderer {
private static final String TAG = "PieChartRendererFixCove";
String text = "2.0%";
private String mode;
private boolean auto_adapt_text_size;
private int measuredHeight;
private float topAndBottomSpace;
public MyPieChartRenderer(PieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
public MyPieChartRenderer setMode(String mode) {
this.mode = mode;
return this;
}
public MyPieChartRenderer setAuto_adapt_text_size(boolean auto_adapt_text_size) {
this.auto_adapt_text_size = auto_adapt_text_size;
return this;
}
@Override
public void drawValues(Canvas c) {
//获取可用高度
measuredHeight = mChart.getMeasuredHeight();
topAndBottomSpace = measuredHeight - mChart.getRadius() * 2;
if (TextUtils.isEmpty(mode) || TextUtils.equals(mode, "1")) {
drawValuesWithAVG(c);
} else if (TextUtils.equals(mode, "2")) {
drawValuesSimple(c);
} else {
drawValuesWithAVG(c);
}
}
/**
* 左右两侧的空间根据数据个数进行等分,如果等分之后,还是会重叠,那说明数据太多了。如果开始自适应模式,则会自动调整字体大小,避免重叠
*
* @param c
*/
public void drawValuesWithAVG(Canvas c) {
MPPointF center = mChart.getCenterCircleBox();
// get whole the radius
float radius = mChart.getRadius();
float rotationAngle = mChart.getRotationAngle();
float[] drawAngles = mChart.getDrawAngles();//每一个数据占据的角度 15 15 15
float[] absoluteAngles = mChart.getAbsoluteAngles();//每一个数据累计后的总角度 15 30 45
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
final float holeRadiusPercent = mChart.getHoleRadius() / 100.f;
float labelRadiusOffset = radius / 10f * 3.6f;
if (mChart.isDrawHoleEnabled()) {
labelRadiusOffset = (radius - (radius * holeRadiusPercent)) / 2f;
}
final float labelRadius = radius - labelRadiusOffset;
PieData data = mChart.getData();
List<IPieDataSet> dataSets = data.getDataSets();
float yValueSum = data.getYValueSum();
boolean drawEntryLabels = mChart.isDrawEntryLabelsEnabled();
float angle;
int xIndex = 0;
c.save();
float offset = Utils.convertDpToPixel(5.f);
for (int i = 0; i < dataSets.size(); i++) {
IPieDataSet dataSet = dataSets.get(i);
final boolean drawValues = dataSet.isDrawValuesEnabled();
if (!drawValues && !drawEntryLabels)
continue;
final PieDataSet.ValuePosition xValuePosition = dataSet.getXValuePosition();
final PieDataSet.ValuePosition yValuePosition = dataSet.getYValuePosition();
// apply the text-styling defined by the DataSet
applyValueTextStyle(dataSet);
float lineHeight = Utils.calcTextHeight(mValuePaint, "Q")
+ Utils.convertDpToPixel(4f);
IValueFormatter formatter = dataSet.getValueFormatter();
int entryCount = dataSet.getEntryCount();
mValueLinePaint.setColor(dataSet.getValueLineColor());
mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth()));
final float sliceSpace = getSliceSpace(dataSet);
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
int rightCount = 0;
int leftCount = 0;
int leftToRightCount = 0;//从左进入到右的个数
int rightToRightCount = 0;//右侧转了180度后到右的个数
int rightToLeftCount = 0;//从右进入到左的个数
int leftToLeftCount = 0;//左侧转了180度后到左侧的个数
//先统计左右两侧的数据数量
for (int j = 0; j < entryCount; j++) {
if (xIndex == 0)
angle = 0.f;
else
angle = absoluteAngles[xIndex - 1] * phaseX;
final float sliceAngle = drawAngles[xIndex];
final float sliceSpaceMiddleAngle = sliceSpace / (Utils.FDEG2RAD * labelRadius);
// offset needed to center the drawn text in the slice
final float angleOffset = (sliceAngle - sliceSpaceMiddleAngle / 2.f) / 2.f;
angle = angle + angleOffset;
final float transformedAngle = rotationAngle + angle * phaseY;
final boolean drawXOutside = drawEntryLabels &&
xValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE;
final boolean drawYOutside = drawValues &&
yValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE;
if (drawXOutside || drawYOutside) {
//左右算法不一样,左边是从下往上排的,即你可以理解为饼图是顺时针方向,从零点排到12点的360度圆形
if (transformedAngle % 360.0 >= 90.0 && transformedAngle % 360.0 <= 270.0) { //左边部分
leftCount++;
if (rotationAngle != 270 && (angle * phaseY % 360.0 <= 180.0 && angle * phaseY % 360.0 >= 0)) {//有转动,且是原本应该在右侧的进入到了左侧
rightToLeftCount++;
} else if (rotationAngle % 360 >= 90 && rotationAngle % 360 <= 270 && rotationAngle != 270 && (angle * phaseY % 360.0 > 180.0 && angle * phaseY % 360.0 < 360.0)) {//有转动,且原本左侧下方的区域进入到右侧时
leftToLeftCount++;
}
} else { /