效果展示
设计图

最终实现

要实现阴影效果需要自定义PieChartRenderer
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.data.PieEntry;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.datasets.IPieDataSet;
import com.github.mikephil.charting.renderer.PieChartRenderer;
import com.github.mikephil.charting.utils.ViewPortHandler;
public class CustomPieChartRenderer extends PieChartRenderer {
public CustomPieChartRenderer(PieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
@Override
protected void drawDataSet(Canvas c, IPieDataSet dataSet) {
c.save();
float rotationAngle = mChart.getRotationAngle();
float radius = mChart.getRadius();
int entryCount = dataSet.getEntryCount();
float totalAngle = 360f;
float totalValue = 0f;
for (int i = 0; i < entryCount; i++) {
totalValue += dataSet.getEntryForIndex(i).getValue();
}
float currentStartAngle = rotationAngle;
for (int i = 0; i < entryCount; i++) {
PieEntry entry = dataSet.getEntryForIndex(i);
int pieColor = dataSet.getColor(i);
Paint renderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Paint highlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
int lighterShadowColor = lightenColor(pieColor, 0.1f);
renderPaint.setColor(pieColor);
renderPaint.setShadowLayer(40f, 0f, 0f, lighterShadowColor);
float sliceAngle = totalAngle * (entry.getValue() / totalValue);
if (isEntryHighlighted(i)) {
highlightPaint.setColor(pieColor);
highlightPaint.setShadowLayer(60f, 0f, 0f, lightenColor(pieColor, 0.1f));
c.drawArc(
mChart.getCircleBox(),
currentStartAngle,
sliceAngle,
true,
highlightPaint
);
} else {
c.drawArc(
mChart.getCircleBox(),
currentStartAngle,
sliceAngle,
true,
renderPaint
);
}
currentStartAngle += sliceAngle;
}
c.restore();
}
private boolean isEntryHighlighted(int index) {
Highlight[] highlights = mChart.getHighlighted();
if (highlights != null && highlights.length > 0) {
for (Highlight highlight : highlights) {
if ((int) highlight.getX() == index) {
return true;
}
}
}
return false;
}
private int lightenColor(int color, float factor) {
int red = (int) ((Color.red(color) * (1 - factor) + 255 * factor));
int green = (int) ((Color.green(color) * (1 - factor) + 255 * factor));
int blue = (int) ((Color.blue(color) * (1 - factor) + 255 * factor));
return Color.rgb(red, green, blue);
}
}
统一设置圆饼图样式PieChartManager
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.SpannableString;
import android.view.View;
import com.github.mikephil.charting.animation.Easing;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.components.Legend;
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.PercentFormatter;
import com.limestone.auspicious.R;
import com.limestone.auspicious.XRJYApplication;
import java.util.List;
public class PieChartManager {
private PieChart pieChart;
private SpannableString CenterText;
private Context mContext;
public PieChartManager(PieChart pieChart, Context context, SpannableString CenterText) {
this.pieChart = pieChart;
this.CenterText=CenterText;
this.mContext=context;
initPieChart();
}
private void initPieChart() {
pieChart.setDrawHoleEnabled(false);
pieChart.setHoleRadius(40f);
pieChart.setHoleColor(mContext.getResources().getColor(R.color.transparent));
pieChart.setNoDataText("暂无数据");
pieChart.setRotationAngle(0);
pieChart.setRotationEnabled(true);
pieChart.setUsePercentValues(true);
pieChart.getDescription().setEnabled(false);
pieChart.setHighlightPerTapEnabled(true);
pieChart.setDrawEntryLabels(false);
pieChart.setEntryLabelColor(mContext.getResources().getColor(R.color.black));
pieChart.setEntryLabelTextSize(10);
pieChart.setEntryLabelTypeface(Typeface.DEFAULT_BOLD);
pieChart.setExtraOffsets(10, 10, 10, 10);
pieChart.setBackgroundColor(Color.TRANSPARENT);
pieChart.setDragDecelerationFrictionCoef(0.75f);
pieChart.animateY(1400, Easing.EaseInOutQuad);
Legend legend = pieChart.getLegend();
legend.setEnabled(false);
legend.setOrientation(Legend.LegendOrientation.VERTICAL);
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
legend.setXEntrySpace(7f);
legend.setYEntrySpace(10f);
legend.setYOffset(10f);
legend.setXOffset(10f);
legend.setTextColor(Color.parseColor("#a1a1a1"));
legend.setTextSize(13);
}
public void showSolidPieChart(List<PieEntry> yvals, List<Integer> colors) {
PieDataSet dataset = new PieDataSet(yvals, "");
dataset.setColors(colors);
dataset.setDrawValues(true);
dataset.setValueTextSize(14);
dataset.setValueTextColor(mContext.getResources().getColor(R.color.black));
dataset.setValueTypeface(Typeface.DEFAULT_BOLD);
dataset.setValueLinePart1Length(0.4f);
dataset.setValueLinePart2Length(0.4f);
dataset.setValueLinePart1OffsetPercentage(80f);
dataset.setValueLineColor(Color.parseColor("#61d2d2"));
dataset.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
dataset.setValueLineVariableLength(true);
dataset.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
dataset.setSliceSpace(0);
dataset.setSelectionShift(5f);
PieData pieData = new PieData(dataset);
pieData.setValueFormatter(new PercentFormatter());
pieChart.setData(pieData);
}
public void showRingPieChart(List<PieEntry> yVals, List<Integer> colors,String centerName){
pieChart.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
pieChart.setDrawHoleEnabled(true);
pieChart.setHoleRadius(70f);
pieChart.setHoleColor(Color.parseColor("#FFFFFF"));
pieChart.setTransparentCircleRadius(0);
pieChart.setDrawCenterText(true);
pieChart.setCenterTextSize(14f);
pieChart.setCenterText(centerName);
pieChart.setCenterTextTypeface(Typeface.DEFAULT_BOLD);
pieChart.setCenterTextColor(XRJYApplication.getApplication().getResources().getColor(R.color.black));
pieChart.setHighlightPerTapEnabled(true);
PieDataSet dataset = new PieDataSet(yVals, "");
dataset.setColors(colors);
dataset.setDrawValues(false);
dataset.setValueTextSize(10);
dataset.setValueTextColor(mContext.getResources().getColor(R.color.black));
dataset.setValueTypeface(Typeface.DEFAULT_BOLD);
dataset.setValueLinePart1Length(0.4f);
dataset.setValueLinePart2Length(0.8f);
dataset.setValueLinePart1OffsetPercentage(80f);
dataset.setValueLineColor(Color.parseColor("#61d2d2"));
dataset.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
dataset.setValueLineVariableLength(true);
dataset.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
dataset.setSliceSpace(0);
dataset.setSelectionShift(5f);
PieData pieData = new PieData(dataset);
pieData.setValueFormatter(new PercentFormatter());
pieChart.setData(pieData);
}
private int lightenColor(int color, float factor) {
int red = (int) ((Color.red(color) * (1 - factor) + 255 * factor));
int green = (int) ((Color.green(color) * (1 - factor) + 255 * factor));
int blue = (int) ((Color.blue(color) * (1 - factor) + 255 * factor));
return Color.rgb(red, green, blue);
}
}
使用方式
private List<PieEntry> yVals1 = new ArrayList<>();
private List<PieEntry> yVals2 = new ArrayList<>();
private List<Integer> colors = new ArrayList<>();
private PieChartManager pieChartManager1;
private PieChartManager pieChartManager2;
binding.layoutPositionRatio.chart1.setTouchEnabled(false);
binding.layoutPositionRatio.chart2.setTouchEnabled(false);
binding.layoutPositionRatio.chart1.setNoDataText("暂无数据");
binding.layoutPositionRatio.chart2.setNoDataText("暂无数据");
binding.layoutPositionRatio.chart1.setRenderer(new CustomPieChartRenderer(binding.layoutPositionRatio.chart1, binding.layoutPositionRatio.chart1.getAnimator(), binding.layoutPositionRatio.chart1.getViewPortHandler()));
binding.layoutPositionRatio.chart2.setRenderer(new CustomPieChartRenderer(binding.layoutPositionRatio.chart2, binding.layoutPositionRatio.chart2.getAnimator(), binding.layoutPositionRatio.chart2.getViewPortHandler()));
pieChartManager1 = new PieChartManager(binding.layoutPositionRatio.chart1, mContext, generateCenterSpannableText());
pieChartManager2 = new PieChartManager(binding.layoutPositionRatio.chart2, mContext, generateCenterSpannableText());
yVals2.add(pieEntry3);
yVals2.add(pieEntry4);
colors.add(ContextCompat.getColor(mContext, R.color.color_1BBE8A));
colors.add(ContextCompat.getColor(mContext, R.color.color_F14A4B));
pieChartManager1.showRingPieChart(yVals1, colors, cnSymbol1);
pieChartManager2.showRingPieChart(yVals2, colors, cnSymbol2);
binding.layoutPositionRatio.chart1.highlightValue(0, 0);
binding.layoutPositionRatio.chart2.highlightValue(0, 0);
binding.layoutPositionRatio.chart1.invalidate();
binding.layoutPositionRatio.chart2.invalidate();
private SpannableString generateCenterSpannableText() {
SpannableString s = new SpannableString("MPAndroidChart\ndeveloped by Philipp Jahoda");
s.setSpan(new RelativeSizeSpan(1.7f), 0, 14, 0);
s.setSpan(new StyleSpan(Typeface.NORMAL), 14, s.length() - 15, 0);
s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, s.length() - 15, 0);
s.setSpan(new RelativeSizeSpan(.8f), 14, s.length() - 15, 0);
s.setSpan(new StyleSpan(Typeface.ITALIC), s.length() - 14, s.length(), 0);
s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), s.length() - 14, s.length(), 0);
return s;
}
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/chart1"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="@dimen/dp_150"
/>
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/chart2"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="@dimen/dp_150"
/>
</LinearLayout>