MPAndroidChart攻略第一步——LineChart的点点滴滴。
带你入门折线图的基本使用,各种属性的设置,自定义轴上的标签,及去除边框线与轴线,和MarkView提示的使用。
MPAndroidChart_折线图的那些事
MPAndroidChart_饼图的那些事
MPAndroidChart_动态柱状图
MPAndroidChart_水平条形图的那些事
MPAndroidChart_并列柱状图,及如何实现点击隐藏掉不需要的条目。
目录
1. 从简易折线图开始
2. LineDataSet折线的设置
3. Lengend图例
4. 限制线的用法
5. 网格线的用法
-1. 先来看看x轴网格线
-2. y轴的用法
6. 去掉边框线以及轴线
7. 多条折线的设置
8. 自定义x轴显示的标签
9. MarkView提示
-1. 创建一个类继承自MarkerView
-2. 创建布局
-3. 使用
10. 动画等属性的使用
11. 可以优化改进的地方
话不多说,代码走起,我们先写一个最简易的折线图,代码如下:
public class MainActivity extends AppCompatActivity {
private LineChart lineChart;
private LineDataSet set;
private ArrayList list = new ArrayList<>(); //数据集合
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lineChart = findViewById(R.id.chart);
for (int i = 0; i < 10; i++) {
list.add(new Entry(i, (float) (Math.random() * 80)));
}
setData(list);
}
private void setData(ArrayList list) {
set = new LineDataSet(list, "Label");
LineData data = new LineData(set);
//设置数据
lineChart.setData(data);
}
看效果还挺不错吧,但是我们实际开发时,往往需求没这么简单,下面,我们来对折线图各种方法进行一个总结。
具体方法注释都在代码里写着。
private void setLine(LineDataSet set) {
//设置线条的颜色
set.setColor(Color.RED);
//虚线模式下绘制直线
set.enableDashedLine(20f, 5f, 0f);
//点击后高亮线的显示颜色
set.enableDashedHighlightLine(50f, 15f, 0f);
//设置数据小圆点的颜色
set.setCircleColor(Color.GREEN);
//设置圆点是否有空心
set.setDrawCircles(true);
//设置线条的宽度,最大10f,最小0.2f
set.setLineWidth(1f);
//设置小圆点的半径,最小1f,默认4f
set.setCircleRadius(5f);
//设置是否显示小圆点
set.setDrawCircles(true);
//设置字体颜色
set.setValueTextColor(Color.BLUE);
//设置字体大小
set.setValueTextSize(20f);
//设置是否填充
set.setDrawFilled(true);
}
效果如下
下面设置一下Lengend图例,也就是左下角那个小方框
private void setLenged(){
Legend legend=lineChart.getLegend();
legend.setTextColor(Color.RED);
legend.setTextSize(20f);
//设置图例垂直对齐
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
//设置图例居中
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
//设置图例方向
legend.setOrientation(Legend.LegendOrientation.HORIZONTAL);
//设置图例是在图内还是图外绘制
legend.setDrawInside(false);
//图例条目之间距离
legend.setXEntrySpace(4f);
//设置图例可否换行
legend.setWordWrapEnabled(true);
//设置图例现状为线.默认为方形
// legend.setForm(Legend.LegendForm.LINE);
//是否隐藏图例/true_否,false_是
legend.setEnabled(true);
}
效果如下
private void maxLine(){
//设置限制线
LimitLine l1=new LimitLine(60f,"限制线");
l1.setLineWidth(4f);
l1.setTextSize(20f);
l1.setLineColor(Color.RED);
//允许在虚线模式下绘制(线段长度,分隔长度,偏移量)
l1.enableDashedLine(10f,10f,0f);
//设置限制线标签的位置
l1.setLabelPosition(LimitLine.LimitLabelPosition.RIGHT_TOP);
l1.setTextSize(10f);
//添加限制线
lineChart.getAxisLeft().addLimitLine(l1);
//是否隐藏限制线/true_否,false_是
l1.setEnabled(true);
}
private void XwangGe(){
//设置x轴网格线
XAxis xAxis=lineChart.getXAxis();
//以虚线模式画网格线
xAxis.enableGridDashedLine(10f,10f,0f);
//设置x轴最大值
xAxis.setAxisMaximum(200f);
//设置x轴最小值
xAxis.setAxisMinimum(0f);
//撤销设置的最大值,让轴自动计算
xAxis.resetAxisMaximum();
//撤销设置的最小值,让轴自动计算
xAxis.resetAxisMinimum();
// //设置x轴标签数,默认为6个
xAxis.setLabelCount(10);
// //设置x轴标签数,若强制启用true,可能导致轴上的数字不均匀
// xAxis.setLabelCount(10,true);
//设置x轴之间的最小间隔。用于在图表放大后标签不至于重合
xAxis.setGranularity(1f);
//设置x轴轴线的宽度
xAxis.setAxisLineWidth(1f);
//设置轴线的颜色
xAxis.setAxisLineColor(Color.BLUE);
//设置x轴显示位置在底部
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
}
//绘制Y轴网格线,有些方法上面也有,这里就不多加了
private void YwangGe(){
//y轴默认显示两个轴线,左右
//获取图表左边y轴
YAxis left=lineChart.getAxisLeft();
//是否绘制0所在的网格线/默认false绘制
left.setDrawZeroLine(true);
//将网格线设置为虚线模式
left.enableGridDashedLine(10f,10f,0f);
//获取图表右边y轴
YAxis right=lineChart.getAxisRight();
//禁用图表右边y轴
right.setEnabled(false);
}
有些时候我们的需求需要去掉边框线,这时候可以用以下办法
private void yingcang() {
//关闭边框矩形
lineChart.setDrawBorders(false);
//不绘制y轴左边的线
lineChart.getAxisLeft().setDrawAxisLine(false);
//不绘制y轴右边的线
// lineChart.getAxisRight().setDrawAxisLine(false);
//禁用图表右边y轴
lineChart.getAxisRight().setEnabled(false);
//禁用x轴
lineChart.getXAxis().setEnabled(false);
//隐藏图表左边y轴标签
lineChart.getAxisLeft().setDrawLabels(false);
//关闭x轴网格线./即竖线
// lineChart.getXAxis().setDrawGridLines(false);
//隐藏图表右下角显示内容
Description description = new Description();
description.setEnabled(false);
lineChart.setDescription(description);
}
方法也很简单,就是两个LineDataSet而已,我们修改上面的setData方法
private void setData(String name1,String name2) {
//这里随机数了两个集合
ArrayList list=new ArrayList<>();
ArrayList list2=new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(new Entry(i, (float) (Math.random() * 80)));
}
for (int i = 0; i < 10; i++) {
list2.add(new Entry(i, (float) (Math.random() * 80)));
}
//这里两条线
LineDataSet set1 = new LineDataSet(list, name1);
LineDataSet set2 = new LineDataSet(list2, name2);
setLine(set1);
setLine(set2);
//避免看不清,将折线2的颜色更改
set2.setColor(Color.BLACK);
//创建一个数据集
ArrayList dataSets=new ArrayList<>();
dataSets.add(set1);
dataSets.add(set2);
LineData data = new LineData(dataSets);
//设置数据
lineChart.setData(data);
}
现在我们自定义一下x轴上显示的文字,y轴同理
private void Dif(){
//为了演示更清楚,我们将x轴标签位于底部
final String[] data={"周一","周二","周三","周四","周五","周六","周日"};
XAxis xAxis=lineChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
//格式化标签
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
return data[(int) value];
}
});
}
为什么会这样呢?
原因是我们当初在随机数的时候,里面是10个数,而这里的自定义标签数组却只有7个,所以才产生数组越界。
也就是说,我们在自定义标签的时候,数组的下标一定要与你set数据的下标对应。我们现在修改一下setData()方法
for (int i = 0; i < 7; i++) {
list.add(new Entry(i, (float) (Math.random() * 80)));
}
for (int i = 0; i < 7; i++) {
list2.add(new Entry(i, (float) (Math.random() * 80)));
}
运行一下,好了,所以细节问题要注意,还有一个问题就是,有时候如果产生下标个数不正确的情况,用下面这个方法
//也就是强制平分x轴,但可能会造成数据位置偏差
xAxis.setLabelCount(7,true);
有些时候,我们可能需要点一下数据圆点,让放大显示,这个应该怎样做呢?
设置MarkView提示,如下操作
public class MyMarkerView extends MarkerView {
/**
* Constructor. Sets up the MarkerView with a custom layout resource.
*
* @param context
* @param layoutResource the layout resource to use for the MarkerView
*/
private TextView textView;
private IAxisValueFormatter IAxisValueFormatter;
private DecimalFormat format;
public MyMarkerView(Context context) {
super(context, R.layout.xk); //第二个参数为布局
textView=findViewById(R.id.textview);
format=new DecimalFormat("##0");
}
@SuppressLint("SetTextI18n")
@Override
public void refreshContent(Entry e, Highlight highlight) {
textView.setText(format.format(e.getY()));
super.refreshContent(e, highlight);
}
public MPPointF getOffset(){
return new MPPointF(-(getWidth()/2),-getHeight());
}
}
布局里面也很简单,就一个textview
然后在onCreate方法里使用
MyMarkerView myMarkerView = new MyMarkerView(this);
myMarkerView.setChartView(lineChart);
lineChart.setMarker(myMarkerView);
//设置绘制折线的动画时间
lineChart.animateX(2500);
lineChart.animateY(2500);
//设置折线为圆滑折线(加在上面的setLine方法里)
set.setMode(LineDataSet.Mode.CUBIC_BEZIER);
//设置数值选择监听
lineChart.setOnChartValueSelectedListener(this);
//后台绘制
lineChart.setDrawGridBackground(false);
//设置支持触控手势
lineChart.setTouchEnabled(false);
//设置缩放
lineChart.setDragEnabled(false);
//设置推动
lineChart.setScaleEnabled(false);
//如果禁用,扩展可以在x轴和y轴分别完成
lineChart.setPinchZoom(true);
在setData方法里面增加判断,避免多次重新加载
给setData方法中添加如下代码
//判断表中原来是否有数据
if (lineChart.getData() != null && lineChart.getData().getDataSetCount() > 0) {
//获取数据
set = (LineDataSet) lineChart.getData().getDataSetByIndex(0);
set.setValues(list);
//刷新数据
lineChart.getData().notifyDataChanged();
lineChart.notifyDataSetChanged();
}else{
....
}
关于折线图的画法及常用的方法以上差不多了,下一次,我会将柱状图的画法及需要注意的地方进行一个总结,当然,柱状图与折线图使用差距并不是很大,如果有帮到你的地方,不胜荣幸。