需求:做一个饼图,在显示数据的时候不显示百分比样式,而是要显示原来的数据,UI如下:
拿到需求后时看到 MPAndroidChart 这个开源框架,然后就下载了 demo 看着和需求是高度吻合(此时还不知道需求要显示原始数字数据),然后就拿过来直接做了,等做完了需求说要在饼图上显示原始数据,从提供的 api 里找了半天也没找到怎么修改,后来在网上找到一种方法挺好用的,就整理了一下。
处理方法:不使用 Pie Chart 原始的数据格式 PercentFormatter,根据 [PercentFormatter] 的样式重新写一个,使用
pieData.setValueFormatter(new DefaultValueFormate("万"))
替换 :
pieData.setValueFormatter(new PercentFormatter());
就正常了,示例图可以看上面的UI。
部分代码如下:
自定义数据格式类 PercentFormatter(可根据需要自行修改):
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.utils.ViewPortHandler;
import java.text.DecimalFormat;
public class DefaultValueFormate implements IValueFormatter {
/**
* DecimalFormat for formatting
*/
protected DecimalFormat mFormat;
public DefaultValueFormate() {
setup("");
}
/**
* @param endDes 数字后添加的 单位
*/
public DefaultValueFormate(String endDes) {
setup(endDes);
}
private void setup(String endDes) {
if (TextUtils.isEmpty(endDes)) {
// ###.## 表示可以精确到小数点后两位,即 double 类型
mFormat = new DecimalFormat("###.##");
} else {
mFormat = new DecimalFormat("###.##" + endDes);
}
}
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
return mFormat.format(value);
}
/**
* Returns the number of decimal digits this formatter uses.
* @return
*/
public int getDecimalDigits() {
return 1;
}
}
使用代码如下:
// 设置 pie chart
public void setPieChart() {
pieChart.getDescription().setEnabled(false);//设置描述
pieChart.setExtraOffsets(25, 10, 25, 25); //设置边距
pieChart.setDragDecelerationFrictionCoef(0.1f);//设置摩擦系数(值越小摩擦系数越大)
pieChart.setRotationEnabled(true);//是否可以旋转
pieChart.setDrawCenterText(false);//设置绘制环中文字
//这个方法为true就是环形图,为false就是饼图
pieChart.setDrawHoleEnabled(false);
pieChart.animateY(1200, Easing.EaseInOutQuad);
//TODO 设置 legend
Legend l = pieChart.getLegend();
l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
l.setOrientation(Legend.LegendOrientation.VERTICAL);
l.setDrawInside(false);
l.setXEntrySpace(0f);
l.setYEntrySpace(0f);
l.setYOffset(0f);
l.setTextSize(15f);
l.setTextColor(Color.parseColor("#e3d321"));
//设置饼图数据
setPieChartData();
}
//TODO 设置 数据
private void setPieChartData() {
List<PieEntry> entries = new ArrayList<>();
entries.add(new PieEntry(300f,"金融"));
entries.add(new PieEntry(600f,"基金"));
entries.add(new PieEntry(1200f,"黄金"));
entries.add(new PieEntry(150,"收支"));
PieDataSet dataSet = new PieDataSet(entries, "");
ArrayList<Integer> colors = new ArrayList<>();
colors.add(Color.rgb(221,131,241));
colors.add(Color.rgb(242,173,173));
colors.add(Color.rgb(53,186,232));
colors.add(Color.rgb(0,205,131));
dataSet.setColors(colors);//设置饼块的颜色
//设置数据显示方式有见图
dataSet.setValueLinePart1OffsetPercentage(80f);//数据连接线距图形片内部边界的距离,为百分数
dataSet.setValueLinePart1Length(0.3f);
dataSet.setValueLinePart2Length(0.4f);
dataSet.setValueLineColor(Color.YELLOW);//设置连接线的颜色
dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
PieData pieData = new PieData(dataSet);
pieData.setValueTextSize(11f);
pieData.setValueTextColor(Color.DKGRAY);
//TODO 设置不显示百分比时,如果是数字会在数字后面自动添加了一个%,这个是在源码中写的,有兴趣可以看看
pieChart.setUsePercentValues(false);
//使用下面的格式替换 PercentFormatter
// pieData.setValueFormatter(new PercentFormatter());
pieData.setValueFormatter(new DefaultValueFormate("万"));//自己修改的方法
pieChart.setData(pieData);
pieChart.highlightValues(null);
pieChart.invalidate();
}
到此处显示原始数据的问题就圆满解决了。
本以为这样就结束了,然而并没有。。。。。。
需求又说了,还要给饼图中的每一个扇形添加点击页面跳转事件,然后就找到了下面这个方法:
pieChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, Highlight h) {
}
@Override
public void onNothingSelected() {
}
});
测试的时候发现这个点击事件是有效的,并且还能让该点击的扇形区域有一个放大效果,但是,回到饼图页面的时候发现再次点击饼图,执行了 OnChartValueSelectedListener 的 onNothingSelected() 方法,没有执行 onValueSelected(Entry e, Highlight h)方法,要再点击一次才能执行 onValueSelected(Entry e, Highlight h) 方法,一开始以为是因为这个 Highlighting(github 官网有说明) 这个属性导致的,然后就把这个东西使用下面方式给关闭:
pieChart.setHighlightPerTapEnabled(false);
关掉之后,这个“放大”的效果确实没有了,但是扇形区域的点击事件也没有了。
通过 pieChart 的 setOnChartValueSelectedListener 这个方法找到 chart 类中的源码:
/**
* Highlights the value selected by touch gesture. Unlike
* highlightValues(...), this generates a callback to the
* OnChartValueSelectedListener.
*
* @param high - the highlight object
* @param callListener - call the listener
*/
public void highlightValue(Highlight high, boolean callListener) {
Entry e = null;
if (high == null)
mIndicesToHighlight = null;
else {
if (mLogEnabled)
Log.i(LOG_TAG, "Highlighted: " + high.toString());
e = mData.getEntryForHighlight(high);
if (e == null) {
mIndicesToHighlight = null;
high = null;
} else {
// set the indices to highlight
mIndicesToHighlight = new Highlight[]{
high
};
}
}
setLastHighlighted(mIndicesToHighlight);
if (callListener && mSelectionListener != null) {
if (!valuesToHighlight())
mSelectionListener.onNothingSelected();
else {
// notify the listener
mSelectionListener.onValueSelected(e, high);
}
}
// redraw the chart
invalidate();
}
接着就对这个方法在进行设置,发现没有起作用,目前还没解决这个问题,看到这是不是很郁闷,没解决还写这么长[顺着网线来找我吧],好吧,就是记录一下,以后要是找到解决方法的话再来完善,或者有好的方法的话可以提供一下。