Demo补充中(UpDating): https://github.com/JinBoy23520/MPAndroidChartDemoByJin
本文出自: http://blog.csdn.net/dt235201314/article/details/54135182
MPAndroidChart项目实战(一)——实现对比性柱状图
MPAndroidChart项目实战(二)——双平滑曲线(双折线图)和MarkView实现
MPAndroidChart项目实战(三)——饼状图实现和文字重合问题解决
MPAndroidChart项目实战(四)——柱状图实现及X轴文字不显示问题和柱状图上显示文字一丶先看效果图
Gif图大小限制,效果不是很清晰,高清效果是特别帅的
二丶先说一下功能点
1.双折线图(平滑曲线),展现对比效果
2.X轴单位,默认显示在1(月)
3.Y轴单位(%)或者其他,但文字写上去总是有点丑,就没放在Y轴
4.MarkView这里的不同点在于,点击一个点显示相同X轴对比的数据
5.新版MPAndroidChart支持两条折现X长度不一样,就是有一条为null就只显示另一条,当长度不一同样可以显示,老版本(jar包版本)就不行。
6.解决MPAndroidChart在ViewPage+fragment里的滑动冲突
三丶看代码
MPAndroidChart库的导入与基本属性:(参考刘某人MPAndroidChart专栏),写得很详细(自己想写的但又落在别人后面,又少了增粉蹭浏览量的好机会)
Android图表库MPAndroidChart(十四)——在ListView种使用相同的图表
1.项目复用率很高,先得有个BaseChartEntry.Java
public abstract class BaseChartEntity<T extends Entry> { protected BarLineChartBase mChart; protected List<T>[] mEntries; protected String[] labels; protected int []mChartColors; protected float mTextSize; protected int mValueColor; protected BaseChartEntity(BarLineChartBase chart, List<T> []entries, String[] labels, int []chartColor, int valueColor, float textSize) { this.mChart = chart; this.mEntries = entries; this.labels = labels; this.mValueColor = valueColor; this.mChartColors = chartColor; // this.mTextSize = textSize; this.mTextSize = 11f; initChart(); } /** * <p>初始化chart</p> */ protected void initChart() { initProperties(); setChartData(); initLegend(Legend.LegendForm.LINE, mTextSize, mValueColor); initXAxis(mValueColor, mTextSize); initLeftAxis(mValueColor, mTextSize); } private void initLeftAxis(int color, float textSize) { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTextColor(color); leftAxis.setTextSize(textSize); float yMax = mChart.getData().getYMax() == 0 ? 100f : mChart.getData().getYMax(); leftAxis.setAxisMaximum(yMax + yMax * 0.007f); // leftAxis.setAxisMinimum(0f); leftAxis.setDrawGridLines(false); leftAxis.setGranularityEnabled(false); leftAxis.setDrawZeroLine(false); leftAxis.setLabelCount(6); leftAxis.setAxisLineWidth(1f); leftAxis.setAxisLineColor(mValueColor); mChart.getAxisRight().setEnabled(false); } private void initXAxis(int color, float textSize) { XAxis xAxis = mChart.getXAxis(); xAxis.setTextSize(textSize); xAxis.setAxisMinimum(0); xAxis.setTextColor(color); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(true); xAxis.setDrawLabels(true); xAxis.setAxisLineWidth(1f); xAxis.setLabelCount(8); xAxis.setDrawLimitLinesBehindData(true); xAxis.setAxisLineColor(mValueColor); xAxis.setCenterAxisLabels(false); xAxis.setAxisMinimum(mChart.getData().getXMin()); xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); } /** * <p>初始化属性信息</p> */ private void initProperties() { mChart.setNoDataText(""); // no description text mChart.getDescription().setEnabled(false); // enable touch gestures mChart.setTouchEnabled(true); mChart.setDragDecelerationFrictionCoef(0.9f); // enable scaling and dragging mChart.setDragEnabled(true); mChart.setScaleXEnabled(true); mChart.setPinchZoom(false); mChart.setVisibleXRangeMaximum(6); mChart.setScaleYEnabled(false); mChart.setDrawGridBackground(false); mChart.setHighlightPerDragEnabled(false); // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(false); } /** * <p>初始化Legend展示信息</p> * @param form 样式 * @param legendTextSize 文字大小 * @param legendColor 颜色值 */ public void initLegend(Legend.LegendForm form, float legendTextSize, int legendColor) { // get the legend (only possible after setting data) Legend l = mChart.getLegend(); // modify the legend ... l.setForm(form); l.setTextSize(legendTextSize); l.setTextColor(legendColor); //l.setYOffset(11f); updateLegendOrientation(Legend.LegendVerticalAlignment.BOTTOM, Legend.LegendHorizontalAlignment.RIGHT, Legend.LegendOrientation.HORIZONTAL); } /** * <p>图例说明</p> * @param vertical 垂直方向位置 默认底部 * @param horizontal 水平方向位置 默认右边 * @param orientation 显示方向 默认水平展示 */ public void updateLegendOrientation (Legend.LegendVerticalAlignment vertical, Legend.LegendHorizontalAlignment horizontal, Legend.LegendOrientation orientation) { Legend l = mChart.getLegend(); l.setVerticalAlignment(vertical); l.setHorizontalAlignment(horizontal); l.setOrientation(orientation); l.setDrawInside(false); } /** * 图表value显示开关 */ public void toggleChartValue () { List<BaseDataSet> sets = mChart.getData().getDataSets(); for (BaseDataSet iSet : sets) { iSet.setDrawValues(!iSet.isDrawValuesEnabled()); } mChart.invalidate(); } public void setMarkView (MarkerView markView) { markView.setChartView(mChart); // For bounds control mChart.setMarker(markView); // Set the marker to the chart mChart.invalidate(); } /** * x/ylabel显示样式 * @param xvalueFromatter x * @param leftValueFromatter y */ public void setAxisFormatter(IAxisValueFormatter xvalueFromatter, IAxisValueFormatter leftValueFromatter) { mChart.getXAxis().setValueFormatter(xvalueFromatter); mChart.getAxisLeft().setValueFormatter(leftValueFromatter); mChart.invalidate(); } protected abstract void setChartData(); /** * value显示格式设置 * @param valueFormatter IValueFormatter */ public void setDataValueFormatter(IValueFormatter valueFormatter) { mChart.getData().setValueFormatter(valueFormatter); } }
这里设置了一些简单属性和方法类似setMarkView等,方便统一使用。需要修改时重写方法修改就行。
2.下面这个类就厉害了,基本是根据设计图样式添加的一些属性方法(对应图表一的基本属性),同样修要修改时重写方法就可以哒
public class LineChartEntity extends BaseChartEntity<Entry> { public LineChartEntity (LineChart lineChart, List<Entry> []entries, String[] labels, int []chartColor, int valueColor, float textSize) { super(lineChart, entries, labels, chartColor, valueColor, textSize); } @Override protected void initChart() { super.initChart(); mChart.getAxisLeft().setDrawGridLines(true); mChart.getAxisLeft().enableGridDashedLine(10f, 15f, 0f); mChart.getAxisLeft().setGridLineWidth(0.5f); mChart.getAxisLeft().setGridColor(Color.parseColor("#f5f5f5")); mChart.getAxisLeft().setDrawZeroLine(false); mChart.getAxisRight().setDrawZeroLine(false); mChart.getAxisRight().setZeroLineWidth(0f); mChart.getAxisLeft().setZeroLineWidth(0f); mChart.getAxisLeft().setDrawAxisLine(false); mChart.getXAxis().setDrawAxisLine(false); // mChart.setScaleMinima(1.38f, 1f); // mChart.getXAxis().setDrawGridLines(true); // mChart.getXAxis().enableGridDashedLine(20f, 20f, 0f); } @Override protected void setChartData() { LineDataSet []lineDataSet = new LineDataSet[mEntries.length]; if (mChart.getData() != null && mChart.getData().getDataSetCount() == mEntries.length) { for(int index = 0, len = mEntries.length; index < len; index ++) { List<Entry> list = mEntries[index]; lineDataSet[index] = (LineDataSet) mChart.getData().getDataSetByIndex(index); lineDataSet[index].setValues(list); } mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { for (int index = 0, len = mEntries.length; index < len; index ++) { lineDataSet[index] = new LineDataSet(mEntries[index], labels[index]); lineDataSet[index].setAxisDependency(YAxis.AxisDependency.LEFT); lineDataSet[index].setColor(mChartColors[index]); lineDataSet[index].setLineWidth(1.5f); lineDataSet[index].setCircleRadius(3.5f); lineDataSet[index].setCircleColor(mChartColors[index]); lineDataSet[index].setFillAlpha(25); // lineDataSet[index].enableDashedLine(10f, 15f, 0f); // lineDataSet[index].enableDashedHighlightLine(10f, 15f, 0f); lineDataSet[index].setDrawCircleHole(false); lineDataSet[index].setValueTextColor(mChartColors[index]); // lineDataSet[index].setFillColor(ColorTemplate.colorWithAlpha(Color.YELLOW, 200)); } // create a data object with the datasets LineData data = new LineData(lineDataSet); data.setValueTextSize(mTextSize); // set data mChart.setData(data); mChart.animateX(2000, Easing.EasingOption.EaseInOutQuad); } } /** * <p>填充曲线以下区域</p> * @param drawable 填充drawable * @param filledColor 填充颜色值 * @param fill true:填充 */ public void toggleFilled(Drawable []drawable, int []filledColor, boolean fill) { List<ILineDataSet> sets = ((LineChart)mChart).getData().getDataSets(); for (int index = 0, len = sets.size(); index < len; index ++ ) { LineDataSet set = (LineDataSet) sets.get(index); if (drawable != null) { set.setFillDrawable(drawable[index]); } else if (filledColor != null){ set.setFillColor(filledColor[index]); } set.setDrawFilled(fill); } mChart.invalidate(); } /** * <p>绘制曲线上点</p> * @param draw true:绘制 */ public void drawCircle ( boolean draw) { List<ILineDataSet> sets = ((LineChart)mChart).getData().getDataSets(); for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; set.setDrawCircles(draw); } mChart.invalidate(); } /** * 设置图表颜色值 * @param mode LineDataSet.Mode */ public void setLineMode (LineDataSet.Mode mode) { List<ILineDataSet> sets = ((LineChart)mChart).getData().getDataSets(); for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; set.setMode(mode); } mChart.invalidate(); } public void setEnableDashedLine (boolean enable) { List<ILineDataSet> sets = ((LineChart)mChart).getData().getDataSets(); for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; if (enable) { set.disableDashedLine(); } else { // set.setFormLineWidth(1f); // set.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f)); // set.setFormSize(15.f); set.enableDashedLine(10f, 5f, 0f); set.enableDashedHighlightLine(10f, 5f, 0f); } } mChart.invalidate(); } /**设置x缩放的最小最大值*/ public void setMinMaxScaleX(float minScaleX, float maxScaleX) { mChart.getViewPortHandler().setMinMaxScaleX(minScaleX, maxScaleX); } }
每个方法上都有所标注,功能方法填充背景啊,绘制动画啊,折现类型啊,缩放最大值最小值啊等
说一下这个最大值最小值,当图标控件宽设为martch,那么1就是屏幕宽度,1.5就是1.5个屏幕宽度
当都设为同一个值时是就是不允许缩放,大于1可滑动,都等于1就是不可缩放不可滑动
3.V层应用重要方法
public void updateLineData (LineChart mChart ) { List<ILineDataSet> sets = mChart.getData().getDataSets(); for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; set.setFillAlpha(255); set.setDrawCircleHole(true); } mChart.getAxisLeft().setDrawGridLines(true); mChart.getAxisLeft().enableGridDashedLine(10f, 0f, 0f); mChart.getAxisLeft().setGridLineWidth(0.5f); mChart.getAxisLeft().setGridColor(Color.parseColor("#f5f5f5")); mChart.getXAxis().setDrawGridLines(true); mChart.getXAxis().enableGridDashedLine(10f, 0f, 0f); mChart.getXAxis().setGridLineWidth(0.5f); mChart.getXAxis().setGridColor(Color.parseColor("#f5f5f5")); mChart.invalidate(); }
这个方法就是重写折线图样式,相对于GIF图二,这里将圆点改为空心,填充背景透明度改为255最大就是没有
然后就是绘制X和Y轴网格,enableGridLines属性本来是绘制虚线属性,当后面两位都为0时就成了实线
好现在上最重要的方法(传入双折线图数值,线色,背景填充,X轴,Y轴样式,MarkView展现)
private void updateLinehart(final List<FansMonthListEntity> fansMonthList, LineChart lineChart, int[] colors, Drawable[] drawables, final String unit, List<Entry> values1, List<Entry> values2, final String[] labels) { List<Entry>[] entries = new ArrayList[2]; entries[0] = values1; entries[1] = values2; LineChartEntity lineChartEntity = new LineChartEntity(lineChart, entries, labels, colors, Color.parseColor("#999999"), 12f); lineChartEntity.drawCircle(true); lineChart.setScaleMinima(1.0f, 1.0f); // toggleFilled(lineChartEntity, drawables, colors); lineChartEntity.setLineMode(LineDataSet.Mode.LINEAR); lineChartEntity.initLegend(Legend.LegendForm.CIRCLE, 12f, Color.parseColor("#999999")); lineChartEntity.updateLegendOrientation(Legend.LegendVerticalAlignment.TOP, Legend.LegendHorizontalAlignment.RIGHT, Legend.LegendOrientation.HORIZONTAL); lineChartEntity.setAxisFormatter( new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { if (value == 1.0f) { return mFormat.format(value) + mContext.getResources().getString(R.string.line_x_unit_month); } String monthStr = mFormat.format(value); if (monthStr.contains(".")) { return ""; } else { return monthStr; } // return mMonthFormat.format(value); } }, new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(value) + unit; } }); lineChartEntity.setDataValueFormatter(new IValueFormatter() { @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { return mFormat.format(value) + unit; } }); final NewMarkerView markerView = new NewMarkerView(mContext, R.layout.custom_marker_view_layout); markerView.setCallBack(new NewMarkerView.CallBack() { @Override public void onCallBack(float x, String value) { int index = (int) (x); if (index < 0) { return; } if (index > fansMonthList.size()) { return; } String textTemp = ""; String monthUnit = mContext.getResources().getString(R.string.home_text_month); if (index <= fansMonthList.size()) { textTemp += labels[0] + "(" + index + monthUnit + ")" + ":" + mFormat.format(Float.parseFloat(fansMonthList.get(index - 1).getFansNum())) + unit; textTemp += "\n"; textTemp += labels[1] + "(" + index + monthUnit + ")" + ":" + mFormat.format(Float.parseFloat(fansMonthList.get(index - 1).getFansRealNum())) + unit; } markerView.getTvContent().setText(textTemp); } }); lineChartEntity.setMarkView(markerView); lineChart.getData().setDrawValues(false); }
好,重要的代码都展现在这里。
不好意思贴掉了一个类NewMarkerView详情见博客:
MPAndroidChart项目实战——MarkerView显示问题解决
最后谈一谈开发时遇到的一些bug
1.lineChart滑动冲突
参考: MPAndroidChart在ViewPager+Fragment滑动冲突解决
2.当数据都为0时,X轴成一条直线,有时还出现负数,Y轴被压缩,文字重复显示,特别丑
mChart.getAxisLeft().setAxisMinimum(0); mChart.getAxisLeft().setAxisMaximum((float) (mChart.getData().getYMax() *1.1 + 20));
解决方法设置Y轴最小值为0,最大值为获得的最大值得1.1倍加20
这样既不会出现负数Y轴数值也不会压缩在一起
3.日月图表切换时,月表无辜变特别长,日X轴30~31个点,月12个点
解决方法:日月切换时重新设定缩放倍数
linechart.getViewPortHandler().setMinMaxScaleX(2,2);
4.markview,这个是真难,代码如上,但是大神帮忙解决的
总结:
MPAndroidChart是很好的开源库,新老版本改变差别较大,各有利弊。但jar包版(老版本)和新版本能共存,可解决很多问题
当开源库不能达到需求时,就要修改开源库,这个对于目前的我太难了,而同事能做到,这方便要加强,对开源源码的解读要加强
文章写到这里希望对大家能有帮助,不懂的地方直接评论问,另外,文章画了不少时间希望能成为我的第一篇技术文章,希望大家支持
以上所述就是小编给大家介绍的《MPAndroidChart项目实战(二)——双平滑曲线(双折线图)和MarkView实现》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Flutter 实现平滑曲线折线图
- 模型评估指标可视化,自动画Loss、Accuracy曲线图工具,无需人工参与!
- iOS 沿曲线线性渐变的贝塞尔曲线
- 利用Python中的numpy包实现PR曲线和ROC曲线的计算
- 有趣的椭圆曲线加密
- 极坐标系下的曲线
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。