【hellochart】真hellochart动态绘制折线图

先吐槽下csdn搜到的动态折线图,几乎全都是先一次性加载完数据,然后一点点绘制,比如有个动态心电图,有个动态气温,真的忍不住想问你们既然已经知道了所有数据,又何必动态加载呢?

时隔半年,终于把代码贴上来了。后来我又发现了MPChart的动态图更好画,但是不如helloChart好看,并且性能更好。但是始终还有一个问题没解决,helloChart刷新过程中不支持手势放大缩小,所以我也试过用+-两个按钮改变试图范围,但是不如手势方便。

正文:现在的代码只需要三个操作。

1.调一个构造方法,传入参数

2.不断的加入新数据

3.销毁这个对象

是不是非常简单好用,如果你有什么定制的需求,欢迎在我的代码上进行修改,如果有不清楚的评论就好了

public class MyLineChart {
    private LineChartView lineChartView;
    private int lineNum = 1;
    private int MAX_VIEW_POINT_COUNT = 100;
    private int period = 20;
    private int[] colors = {Color.RED, Color.BLACK, Color.BLUE, Color.YELLOW, Color.GREEN};

    private OnChartValueSelectListener listener;

    private List<LinkedList<PointValue>> points;
    private List<Line> lines;
    private LineChartData lineChartData;
    private float[] dataSize;

    public MyLineChart(LineChartView lineChartView, int lineNum, int MAX_VIEW_POINT_COUNT, int period, OnChartValueSelectListener listener, int... colors){
        this.lineChartView = lineChartView;
        if (lineNum > 1){
            this.lineNum = lineNum;
        }
        if (MAX_VIEW_POINT_COUNT > 0){
            this.MAX_VIEW_POINT_COUNT = MAX_VIEW_POINT_COUNT;
        }
        if (period > 20){
            this.period = period;
        }
        if (listener != null){
            this.listener = listener;
        }
        if (colors.length > 0){
            this.colors = colors;
        }

        init();
        handler.postDelayed(runnable,period);
    }

    //每20ms刷新一次,相当于50Hz
    private Handler handler = new Handler();
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            updateView();
            handler.postDelayed(runnable,period);
        }
    };

    private void init() {
        lineChartView.setInteractive(false);
        lineChartView.setBackgroundColor(Color.TRANSPARENT);
        lineChartView.setValueTouchEnabled(true);
        lineChartView.setViewportCalculationEnabled(false);//打开就会自动计算y轴范围,现在是人工计算
        lineChartView.setZoomType(ZoomType.HORIZONTAL);
        lineChartView.setOnValueTouchListener(new LineChartOnValueSelectListener() {
            @Override
            public void onValueSelected(int position, int value, PointValue pointValue) {
                if (listener != null){
                    listener.onChartValueSelect(position, value, pointValue);
                }
            }

            @Override
            public void onValueDeselected() {

            }
        });

        lineChartData = new LineChartData();
        lineChartData.setAxisYLeft(new Axis().setHasLines(true).setInside(true).setMaxLabelChars(6).setName("y"));
        lineChartData.setAxisXBottom(new Axis().setHasLines(false).setName("x"));

        lines = new ArrayList<Line>();
        points = new ArrayList<LinkedList<PointValue>>();
        dataSize = new float[lineNum];
        int j = 0;
        for (int i = 0; i < lineNum; i++) {
            if (j > colors.length){
                j = 0;
            }
            Line line = new Line();
            line.setColor(colors[j]);
            line.setShape(ValueShape.CIRCLE);
            line.setPointRadius(1);
            line.setStrokeWidth(1);
            line.setCubic(false);
            line.setFilled(false);
            line.setHasLabels(false);
            line.setHasLines(true);
            line.setHasPoints(false);
            lines.add(line);

            LinkedList<PointValue> pointValues = new LinkedList<>();
            points.add(pointValues);
            j++;
        }
    }

    public void add(float[] value) {
        for (int i = 0; i < lineNum; i++){
            LinkedList<PointValue> pointValues = points.get(i);
            pointValues.add(new PointValue(dataSize[i], value[i]));
            if (dataSize[i] > MAX_VIEW_POINT_COUNT){
                pointValues.removeFirst();
            }
            dataSize[i]++;
        }
    }

    private void updateView(){
        List<Float> tmp = new ArrayList<>();
        for (int i  = 0; i < lineNum; i++){
            tmp.add(dataSize[i]);
            LinkedList<PointValue> pointValues = points.get(i);
            Line line = lines.get(i);
            line.setValues(pointValues);
        }
        float size = Collections.max(tmp);
        if (size <= 0){
            return;
        }
        lineChartData.setLines(lines);
        lineChartView.setLineChartData(lineChartData);

        size += MAX_VIEW_POINT_COUNT >> 2;
        float[] y = setChartHeight();
        Viewport viewport;
        if (size > MAX_VIEW_POINT_COUNT){
            viewport = new Viewport(size - MAX_VIEW_POINT_COUNT, y[0], size, y[1]);
        }else {
            viewport = new Viewport(0, y[0], size, y[1]);
        }
        lineChartView.setCurrentViewport(viewport);
        lineChartView.setMaximumViewport(viewport);
    }

    /**
     * 使用两个全局变量来更新y轴上下限,避免数值跳动太大
     */
    private float top;
    private float bottom;
    private float[] setChartHeight(){
        List<Float> tmp = new ArrayList<>();
        for (int i = 0; i < lineNum; i++){
            List<PointValue> pointValues = points.get(i);
            for (PointValue value : pointValues){
                tmp.add(value.getY());
            }
        }
        float max_top = Collections.max(tmp);
        float min_bottom = Collections.min(tmp);

        if (max_top == min_bottom){
            if (max_top == 0) {
                return new float[]{1, -1};
            }else {
                return new float[]{max_top + Math.abs(max_top) * 0.2f,min_bottom - Math.abs(min_bottom) * 0.2f};
            }
        }else {
            if (top == 0){
                top = max_top;
            }else if (top < max_top - Math.abs(max_top) * 0.03f){
                top = top + Math.abs(top - max_top) * 0.03f;
            }else if (top > max_top + Math.abs(max_top) * 0.03f){
                top = top - Math.abs(top - max_top) * 0.03f;
            }else {
                top = max_top;
            }
            if (bottom == 0){
                bottom = min_bottom;
            }else if (bottom > min_bottom + Math.abs(min_bottom * 0.03f)){
                bottom = bottom - Math.abs(bottom - min_bottom) * 0.03f;
            }else if (bottom < min_bottom - Math.abs(min_bottom * 0.03f)){
                bottom = bottom + Math.abs(bottom - min_bottom) * 0.03f;
            }else {
                bottom = min_bottom;
            }
        }

        float y = top - bottom;
        return new float[]{top + y * 0.2f, bottom - y * 0.2f};
    }

    public interface OnChartValueSelectListener {
        void onChartValueSelect(int position, int value, PointValue pointValue);
    }
}

如果你看到这里觉得有用的话,欢迎去我兄弟的博客寻宝,点下边的博客就可以了,感谢支持

https://blog.csdn.net/ma598214297?utm_source=feed

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值