前人栽树后人乘凉!!!
问题:由于个人需求中曲线数据量较大(最多有10万个点),所有点数据在曲线中全部描绘出来,如果点上画圆圈,则无法正常拖动、缩放等;若只点与点连线不会有卡顿情况。并且数据量过大画图也会很耗时,所以拿到数据后可分段画,利用Handler的定时器一段一段的画,同时需要调moveViewToX方法每次画完之后移动到最后位置,有一个正在加载数据的假象。
题外话:
有人会问既然数据量那么大为什么不用Socket实时获取,我的回答是我的想法就是用Socket但不被采纳!!个人认为用Socket画大量数据的图效果会比较好,而且折线图加载显示的效果会比较流畅,用定时器的这种方法相当于仿了一个Socket但效果不流畅
解决方案:通过对曲线缩放比例的监听动态修改点上圆圈是否需要显示出来
新需求:曲线数据会有中断,两点之间时间间隔超过10分钟视为中断,则两点不进行相连;意思就是如果数据有中断,则需要将曲线显示成多个部分。
解决方案:前端使用的是echarts直接把Y轴值置为空即可中断,但Android端用的是Linechart画点需要传Y轴值(Y轴类型为float,默认为0)所以不能直接置空。我的做法是有中断则画多条曲线,addEntry3方法是将曲线进行拼接,如果不拼接则后序的曲线会从0点开始画就会出现叠加的现象;如果需要显示曲线的图例(右下角显示的曲线名称),当前画多条曲线就会有多个图例(这个是没办法解决的,除非不显示图例),当进行曲线切的时候会出现图例没有更新的现象(查看A曲线显示图例A1、图例A1;当切换B曲线则显示图例B1、图例A1),这时就要用到lineChart_quxian.getLineData().removeDataSet(index);切换曲线的时候不光要清空曲线数据还要清空曲线对应的LineDataSet,每次动态创建添加曲线即可(addLine()方法),同时还需要清空lineChart_quxian.setMarker(null);lineChart_quxian.invalidate();曲线上标记点的设置,因为是通过画多条曲线实现的中断,切换曲线的时候如果不清空会报错,重新获取到数据之后重新设置Marker即可。
注意:使用MPAndroidChart-v3.0.1.jar这版jar包就可以(不清楚从哪版改进的),判断两点时间超过10分钟则在两点之间加两个无效值即可Float.NaN,网址:MPAndroidChart实现断线中间不绘制及其如何思考类似的问题_Rex叶然的博客-CSDN博客_mpandroidchart 折线断开
利用的是修改jar包源码,在3.0.1版jar包已经包含进去了这种情况,增加无效值的点就会直接断开;经过多款手机测试发现有的手机无法正常显示折线图,说明这种方法并无法适配所有机型,因此还是建议分段画折线
***后续修改:addEntry3方法中xCount的取值有问题,xCount的值应该为index之前前所有曲线的点的总和。然后再在其后边添加新的点
直接上代码
package com.test.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.listener.ChartTouchListener;
import com.github.mikephil.charting.listener.OnChartGestureListener;
//参考网址:https://blog.csdn.net/u014769864/article/details/72723180?locationNum=7&fps=1
/**
* 自定义LineChart并设置手势滑动事件监听缩放比例(OnChartGestureListener)
*/
public class MyLineChart extends LineChart implements OnChartGestureListener {
private Context context;
public MyLineChart(Context context) {
super(context);
this.context = context;
}
public MyLineChart(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
@Override
protected void init() {
super.init();
setOnChartGestureListener(this);
}
@Override
public void clear() {
super.clear();
//恢复初始缩放比例
scale = 1;scaleTemp = 1;
}
private ScaleGestureDetector mScaleGestureDetector;
private float scale = 1f;
private float scaleTemp = 1;
//手势开始
@Override
public void onChartGestureStart(MotionEvent motionEvent, ChartTouchListener.ChartGesture chartGesture) {
System.out.println("MyLineChart:::手势开始");
}
//手势结束
@Override
public void onChartGestureEnd(MotionEvent motionEvent, ChartTouchListener.ChartGesture chartGesture) {
scaleTemp = scale;
System.out.println("MyLineChart:::手势结束");
}
//手势长按
@Override
public void onChartLongPressed(MotionEvent motionEvent) {
System.out.println("MyLineChart:::手势长按");
}
//手势双击
@Override
public void onChartDoubleTapped(MotionEvent motionEvent) {
System.out.println("MyLineChart:::手势双击");
}
//手势单点
@Override
public void onChartSingleTapped(MotionEvent motionEvent) {
System.out.println("MyLineChart:::手势单点");
}
//手势滚动
@Override
public void onChartFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
System.out.println("MyLineChart:::手势滚动");
}
//手势比例(获取当前缩放比例)
@Override
public void onChartScale(MotionEvent motionEvent, float v, float v1) {
scale = scaleTemp * v;
if (scale<=1.0){
scale = 1;
}
listener.onScale(scale);
System.out.println("MyLineChart:::onChartScale:"+scale);
}
//手势边界
@Override
public void onChartTranslate(MotionEvent motionEvent, float v, float v1) {
System.out.println("MyLineChart:::手势边界:");
}
NowScaleListener listener;
public void setNowScaleList