<|start_filename|>app/src/main/java/com/linheimx/app/lchart/MultiLineActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;
import com.linheimx.app.library.utils.Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MultiLineActivity extends AppCompatActivity {

    private final static int LINE_NUM = 3;

    LineChart _lineChart;
    SeekBar _SeekBar;
    TextView _tvLineNum;

    Line.CallBack_OnEntryClick onEntryClick = new Line.CallBack_OnEntryClick() {
        @Override
        public void onEntry(Line line, Entry entry) {
            Toast.makeText(MultiLineActivity.this, line.getName() + "    \r\n" + entry.toString(), Toast.LENGTH_SHORT).show();
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_multi_line);

        getSupportActionBar().setTitle("折线图：多条折线");

        _lineChart = (LineChart) findViewById(R.id.chart);
        _SeekBar = (SeekBar) findViewById(R.id.sb_line_more);
        _tvLineNum = (TextView) findViewById(R.id.tv_line_nums);
        CheckBox cb = (CheckBox) findViewById(R.id.cb_cb);

        setChartData(_lineChart, LINE_NUM);

        // 1. 折线的数目
        _tvLineNum.setText("折线的数目:" + LINE_NUM);
        _SeekBar.setProgress(LINE_NUM);

        _SeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                _tvLineNum.setText("折线的数目:" + progress);
                setChartData(_lineChart, progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        // 2. 点击折线上的点 ，回调
        cb.setChecked(true);
        cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                Lines lines = _lineChart.getlines();
                for (Line line : lines.getLines()) {
                    if (isChecked) {
                        line.setOnEntryClick(onEntryClick);
                    } else {
                        line.setOnEntryClick(null);
                    }
                }
            }
        });
    }

    private void setChartData(LineChart lineChart, int lineCount) {

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态，每条折线图想要获取点击回调，highlight需要启用
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y:" + Math.round(value);
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
        xAxis.set_unit("s");

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("m");

        Lines lines = new Lines();

        for (int i = 0; i < lineCount; i++) {

            // 线的颜色
            int color = Color.argb(255,
                    (new Double(Math.random() * 256)).intValue(),
                    (new Double(Math.random() * 256)).intValue(),
                    (new Double(Math.random() * 256)).intValue());

            Line line = createLine(i, color);
            lines.addLine(line);
        }

        lineChart.setLines(lines);
    }


    private Line createLine(int order, int color) {

        final Line line = new Line();
        List<Entry> list = new ArrayList<>();

        Random random = new Random();
        for (int i = 0; i < 10 + order; i++) {
            double x = i;
            double y = random.nextDouble() * 100;
            list.add(new Entry(x, y));
        }

        line.setEntries(list);
        line.setDrawLegend(true);//设置启用绘制图例
        line.setLegendWidth((int)Utils.dp2px(60));//设置图例的宽
//        line.setLegendHeight((int)Utils.dp2px(60));//设置图例的高
//        line.setLegendTextSize((int)Utils.dp2px(19));//设置图例上的字体大小
        line.setName("_line:" + order);
        line.setLineColor(color);
        line.setOnEntryClick(onEntryClick);

        return line;
    }


    /**
     * 光标左移动
     */
    void goLeft() {

//        handler.postDelayed(new Runnable() {
//            @Override
//            public void run() {
//                goLeft();
//            }
//        },3000);

        _lineChart.highLightLeft();
    }
}


<|start_filename|>library/src/main/java/com/linheimx/app/library/data/Line.java<|end_filename|>
package com.linheimx.app.library.data;

import android.graphics.Color;

import com.linheimx.app.library.utils.Utils;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/11/13.
 */

public class Line {

    private List<Entry> entries = new ArrayList<>();


    private double mYMax = Double.MIN_VALUE;
    private double mYMin = Double.MAX_VALUE;
    private double mXMax = Double.MIN_VALUE;
    private double mXMin = Double.MAX_VALUE;

    private int lineColor = Color.BLACK;
    private int lineWidth = 1;
    private int circleColor = Color.RED;
    private int circleR = 4;

    private boolean isFilled = false;
    private int lineAlpha = 50;

    private boolean isEnable = true;
    private boolean isDrawCircle = true;
    private boolean isDrawLegend = false;
    private int legendWidth = 50;
    private int legendHeight = 17;
    private int legendTextSize = 8;
    private String name = "line";

    private CallBack_OnEntryClick onEntryClick;

    public Line() {
        this(null);
    }

    public Line(List<Entry> entries) {

        circleR = (int) Utils.dp2px(circleR);
        legendWidth = (int) Utils.dp2px(legendWidth);
        legendTextSize = (int) Utils.dp2px(legendTextSize);
        legendHeight = (int) Utils.dp2px(legendHeight);

        if (entries != null) {
            setEntries(entries);
        }
    }

    private void calMinMax(List<Entry> entries) {

        mYMax = -Double.MAX_VALUE;
        mYMin = Double.MAX_VALUE;
        mXMax = -Double.MAX_VALUE;
        mXMin = Double.MAX_VALUE;

        for (Entry entry : entries) {

            if (entry.getX() < mXMin) {
                mXMin = entry.getX();
            }
            if (entry.getX() > mXMax) {
                mXMax = entry.getX();
            }

            if (entry.getY() < mYMin) {
                mYMin = entry.getY();
            }
            if (entry.getY() > mYMax) {
                mYMax = entry.getY();
            }
        }
    }

    /**
     * 在数组的前面添加数据
     *
     * @param entry
     */
    public void addEntryInHead(Entry entry) {
        if (entries == null) {
            entries = new ArrayList<>();
        }
        entries.add(0, entry);

        // 计算最大最小
        if (entry.getX() < mXMin) {
            mXMin = entry.getX();
        }
        if (entry.getX() > mXMax) {
            mXMax = entry.getX();
        }

        if (entry.getY() < mYMin) {
            mYMin = entry.getY();
        }
        if (entry.getY() > mYMax) {
            mYMax = entry.getY();
        }
    }

    public void addEntry(Entry entry) {
        if (entries == null) {
            entries = new ArrayList<>();
        }
        entries.add(entry);

        // 计算最大最小
        if (entry.getX() < mXMin) {
            mXMin = entry.getX();
        }
        if (entry.getX() > mXMax) {
            mXMax = entry.getX();
        }

        if (entry.getY() < mYMin) {
            mYMin = entry.getY();
        }
        if (entry.getY() > mYMax) {
            mYMax = entry.getY();
        }
    }

    public List<Entry> getEntries() {
        return entries;
    }

    public void setEntries(List<Entry> entries) {
        // check
        if (entries == null) {
            throw new IllegalArgumentException("entries must be no null");
        }

        this.entries = entries;

        calMinMax(entries);
    }


    /**
     * 根据提供的 x数值，找出list中离它最近的数，返回其下标。
     * --------------
     * 考虑到性能的原因，采用二分查找法。(速度很快，不错！)
     *
     * @param entries
     * @param hitValue
     * @param rounding
     * @return
     */
    public static int getEntryIndex(List<Entry> entries, double hitValue, Rounding rounding) {

        if (entries == null || entries.isEmpty())
            return -1;

        int low = 0;
        int high = entries.size() - 1;
        int closet = low;

        while (low < high) {
            int m = (low + high) / 2;

            double fm = entries.get(m).getX();// middle
            double fr = entries.get(m + 1).getX();// right

            if (hitValue >= fm && hitValue <= fr) {

                // 中_右
                double d1 = Math.abs(hitValue - fm);
                double d2 = Math.abs(hitValue - fr);

                if (d1 <= d2) {
                    closet = m;
                } else {
                    closet = m + 1;
                }

                low = high = closet;
                break;

            } else if (hitValue < fm) {

                if (m >= 1) {
                    double fl = entries.get(m - 1).getX();// left

                    if (hitValue >= fl && hitValue <= fm) {
                        // 中_左
                        double d0 = Math.abs(hitValue - fl);
                        double d1 = Math.abs(hitValue - fm);

                        if (d0 <= d1) {
                            closet = m - 1;
                        } else {
                            closet = m;
                        }

                        low = high = closet;
                        break;
                    }
                }

                high = m - 1;
                closet = high;
            } else if (hitValue > fr) {
                low = m + 1;
                closet = low;
            }
        }

        // trick
        high++;
        low--;
        closet = Math.min(Math.max(closet, 0), entries.size() - 1);

        int result = low;
        if (rounding == Rounding.UP) {
            result = Math.min(high, entries.size() - 1);//多一个
        } else if (rounding == Rounding.DOWN) {
            result = Math.max(low, 0);//少一个
        } else if (rounding == Rounding.CLOSEST) {
            result = closet;
        }
        return result;
    }


    public double getmYMax() {
        return mYMax;
    }

    public void setmYMax(double mYMax) {
        this.mYMax = mYMax;
    }

    public double getmYMin() {
        return mYMin;
    }

    public void setmYMin(double mYMin) {
        this.mYMin = mYMin;
    }

    public double getmXMax() {
        return mXMax;
    }

    public void setmXMax(double mXMax) {
        this.mXMax = mXMax;
    }

    public double getmXMin() {
        return mXMin;
    }

    public void setmXMin(double mXMin) {
        this.mXMin = mXMin;
    }

    public int getLineColor() {
        return lineColor;
    }

    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
    }

    public int getLineWidth() {
        return lineWidth;
    }

    public void setLineWidth(int lineWidth) {
        this.lineWidth = lineWidth;
    }

    public boolean isEnable() {
        return isEnable;
    }

    public void setEnable(boolean enable) {
        isEnable = enable;
    }

    public boolean isDrawCircle() {
        return isDrawCircle;
    }

    public void setDrawCircle(boolean drawCircle) {
        isDrawCircle = drawCircle;
    }

    public int getLegendHeight() {
        return legendHeight;
    }

    public void setLegendHeight(int legendHeight) {
        this.legendHeight = legendHeight;
    }

    public int getLegendTextSize() {
        return legendTextSize;
    }

    public void setLegendTextSize(int legendTextSize) {
        this.legendTextSize = legendTextSize;
    }

    public int getLegendWidth() {
        return legendWidth;
    }

    public void setLegendWidth(int legendWidth) {
        this.legendWidth = legendWidth;
    }

    public boolean isDrawLegend() {
        return isDrawLegend;
    }

    public void setDrawLegend(boolean drawLegend) {
        isDrawLegend = drawLegend;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCircleR() {
        return circleR;
    }

    public void setCircleR(int circleR) {
        this.circleR = circleR;
    }

    public int getCircleColor() {
        return circleColor;
    }

    public void setCircleColor(int circleColor) {
        this.circleColor = circleColor;
    }

    public CallBack_OnEntryClick getOnEntryClick() {
        return onEntryClick;
    }

    public void setOnEntryClick(CallBack_OnEntryClick onEntryClick) {
        this.onEntryClick = onEntryClick;
    }

    public boolean isFilled() {
        return isFilled;
    }

    public void setFilled(boolean filled) {
        isFilled = filled;
    }

    public int getLineAlpha() {
        return lineAlpha;
    }

    public void setLineAlpha(int lineAlpha) {
        this.lineAlpha = lineAlpha;
    }

    public enum Rounding {
        UP,
        DOWN,
        CLOSEST,
    }

    public interface CallBack_OnEntryClick {
        void onEntry(Line line, Entry entry);
    }

}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/RealTimeActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.linheimx.app.library.adapter.DefaultValueAdapter;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;
import com.linheimx.app.library.utils.RectD;

public class RealTimeActivity extends AppCompatActivity {

    LineChart _lineChart;
    Line _line;
    Button _btnStart, _btnStop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_real_time);

        getSupportActionBar().setTitle("折线图：实时趋势");

        _lineChart = (LineChart) findViewById(R.id.chart);
        _btnStart = (Button) findViewById(R.id.btn_start);
        _btnStop = (Button) findViewById(R.id.btn_stop);


        setChartData(_lineChart);

        _btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // 如果已经在采集了，不继续执行啦
                if (_go) {
                    return;
                }

                _go = true;

                addData();
            }
        });

        _btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                _go = false;
            }
        });
    }

    private void setChartData(LineChart lineChart) {

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y:" + value;
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
        xAxis.set_unit("单位：个");
        xAxis.set_ValueAdapter(new DefaultValueAdapter(0));

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("单位：m");
        yAxis.set_ValueAdapter(new DefaultValueAdapter(1));// 默认精度到小数点后2位,现在修改为0位精度

        // 数据
        _line = new Line();
        _line.setDrawCircle(false);

        Lines lines = new Lines();
        lines.addLine(_line);

        lineChart.setLines(lines);
    }

    boolean _go;
    int i = 0;

    /**
     * 向line中添加数据
     */
    private void addData() {

        if (!_go) {
            return;
        }

        _go = true;
        i++;


        _btnStart.postDelayed(new Runnable() {
            @Override
            public void run() {

                _line.addEntry(new Entry(i, Math.random() * 100));
                _lineChart.notifyDataChanged();

                if (_line.getmXMax() > 100) {
                    // 设置当前可视的viewport
                    RectD viewport = _lineChart.get_currentViewPort();
                    viewport.right = _line.getmXMax();
                    viewport.left = viewport.right - 100;
                    _lineChart.set_currentViewPort(viewport);
                }

                _lineChart.invalidate();

                addData();
            }
        }, 10);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();

        _go = false;
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/WarnLinesActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.linheimx.app.library.adapter.DefaultValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.WarnLine;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;

import java.util.ArrayList;
import java.util.List;

public class WarnLinesActivity extends AppCompatActivity {

    LineChart _lineChart;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_warn_lines);

        getSupportActionBar().setTitle("折线图：预警线");

        _lineChart = (LineChart) findViewById(R.id.chart);

        setChartData(_lineChart);
    }

    private void setChartData(LineChart lineChart) {

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(false);// 启用高亮显示  默认为启用状态

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
        xAxis.set_unit("单位：s");
        xAxis.set_ValueAdapter(new DefaultValueAdapter(1));

        //---> x轴上的预警线
        List<WarnLine> xWarns = new ArrayList<>();
        xWarns.add(new WarnLine(2, Color.BLUE));
        xWarns.add(new WarnLine(3.5));
        xAxis.setListWarnLins(xWarns);

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("单位：m");

        //---> y轴上的预警线
        List<WarnLine> yWarns = new ArrayList<>();
        yWarns.add(new WarnLine(4, Color.GREEN));
        yWarns.add(new WarnLine(5.5));
        yAxis.setListWarnLins(yWarns);


        // 数据
        Line line = new Line();
        List<Entry> list = new ArrayList<>();
        list.add(new Entry(1, 5));
        list.add(new Entry(2, 4));
        list.add(new Entry(3, 2));
        list.add(new Entry(4, 3));
        list.add(new Entry(10, 8));
        line.setEntries(list);

        Lines lines = new Lines();
        lines.addLine(line);


        lineChart.setLines(lines);
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/AnimateActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import com.linheimx.app.library.adapter.DefaultValueAdapter;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;

import java.util.ArrayList;
import java.util.List;

public class AnimateActivity extends AppCompatActivity {

    LineChart _lineChart;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animate);

        getSupportActionBar().setTitle("折线图：动画");

        _lineChart = (LineChart) findViewById(R.id.chart);

        setChartData(_lineChart);
    }

    private void setChartData(LineChart lineChart) {

//        lineChart.get_MappingManager().setFatFactor(1f);//设置 可见视图与原始数据视图的比例
//        lineChart.setCanY_zoom(false);//设置只能y方向是否能缩放！

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y:" + value;
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
//        xAxis.setCalWay(Axis.CalWay.every); // 轴线上label的计算方式
        xAxis.set_unit("单位：s");
        xAxis.set_ValueAdapter(new DefaultValueAdapter(1));

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("单位：m");
//        yAxis.set_enableUnit(false);
        yAxis.set_ValueAdapter(new DefaultValueAdapter(2));// 默认精度到小数点后2位,现在修改为3位精度

        // 数据
        Line line = new Line();
        line.setLineColor(Color.MAGENTA);
        line.setDrawCircle(false);
        List<Entry> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            list.add(new Entry(i, (float) Math.random()));
        }
        line.setEntries(list);

        Lines lines = new Lines();
        lines.addLine(line);

        lineChart.setLines(lines);
//        lineChart.setYMax_Min(2, 20);//手动设置，x和y方向上的数据范围
//        lineChart.setXAix_MaxMin(1, 10);
    }

    public void animateY(View view) {
        _lineChart.animateY();
    }

    public void animateX(View view) {
        _lineChart.animateX();
    }

    public void animateXY(View view) {
        _lineChart.animateXY();
    }

}


<|start_filename|>library/src/main/java/com/linheimx/app/library/data/Entry.java<|end_filename|>
package com.linheimx.app.library.data;

/**
 * Created by lijian on 2016/11/13.
 */

public class Entry {

    double x;
    double y;

    boolean isNull_Y = false;

    public Entry(double x, double y) {
        this.x = x;
        this.y = y;
    }


    public double getX() {
        return x;
    }

    public Entry setX(double x) {
        this.x = x;
        return this;
    }

    public double getY() {
        return y;
    }

    public Entry setY(double y) {
        this.y = y;
        return this;
    }

    public boolean isNull_Y() {
        return isNull_Y;
    }

    public Entry setNull_Y() {
        isNull_Y = true;
        return this;
    }

    @Override
    public String toString() {
        return "entry x:" + x + " y:" + y;
    }
}


<|start_filename|>library/src/main/java/com/linheimx/app/library/charts/Chart.java<|end_filename|>
package com.linheimx.app.library.charts;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.linheimx.app.library.touch.TouchListener;
import com.linheimx.app.library.utils.Utils;

/**
 * Created by lijian on 2016/11/13.
 */

public abstract class Chart extends View {

    public Chart(Context context) {
        this(context, null, 0);
    }

    public Chart(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public Chart(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }


    protected void init(Context context, AttributeSet attrs) {
        // 采用硬件加速
        setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int size = 100;
        int width = resolveSize(size, widthMeasureSpec);
        int height = resolveSize(size, heightMeasureSpec);

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }
}


<|start_filename|>library/src/main/java/com/linheimx/app/library/render/LineRender.java<|end_filename|>
package com.linheimx.app.library.render;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.graphics.Shader;

import com.linheimx.app.library.animate.LAnimator;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.manager.MappingManager;
import com.linheimx.app.library.utils.SingleF_XY;
import com.linheimx.app.library.utils.Utils;

import java.util.List;

/**
 * Created by lijian on 2016/11/17.
 */

public class LineRender extends BaseRender {

    LineChart lineChart;
    Lines _lines;

    Paint _PaintLine;
    Paint _PaintCircle;
    Paint _PaintLegend;

    Path _PathLine;

    LAnimator _LAnimator;

    Bitmap _drawBitmap;
    Canvas softwareCanvas = new Canvas();

    public LineRender(RectF rectMain, MappingManager _MappingManager, Lines _lines, LineChart lineChart) {
        super(rectMain, _MappingManager);
        this._lines = _lines;
        this.lineChart = lineChart;
        this._LAnimator = lineChart.get_LAnimator();

        _PaintLine = new Paint(Paint.ANTI_ALIAS_FLAG);
        _PaintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
        _PaintLegend = new Paint(Paint.ANTI_ALIAS_FLAG);

        _PathLine = new Path();
    }


    public void onChartSizeChanged(int w, int h) {
        if (w > 0 && h > 0) {
            _drawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            softwareCanvas.setBitmap(_drawBitmap);
        }
    }


    public void render(Canvas canvasSrc) {

        if (_lines == null) {
            return;
        }

        Canvas canvas = null;

        // layout editor 状态下 _drawBitmap 是没有的
        if (null != _drawBitmap) {
            canvas = softwareCanvas;
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        } else {
            canvas = canvasSrc;
        }


        canvas.save();
        canvas.clipRect(_rectMain); // 限制绘制区域

        // 绘制折线 和 折线上的圆点
        for (Line line : _lines.getLines()) {
            if (!line.isEnable()) {
                continue;
            }
            drawLine_Circle(canvas, line);
        }

        canvas.restore();

        // 绘制每条线的 legend
        for (int i = 0; i < _lines.getLines().size(); i++) {
            Line line = _lines.getLines().get(i);
            if (!line.isEnable()) {
                continue;
            }
            drawLegend(canvas, line, i);
        }

        if (_drawBitmap != null) {
            canvasSrc.drawBitmap(_drawBitmap, 0, 0, null);
        }
    }

    private void drawLine_Circle(Canvas canvas, Line line) {

        _PaintLine.setStrokeWidth(line.getLineWidth());
        _PaintLine.setColor(line.getLineColor());
        _PaintLine.setStyle(Paint.Style.STROKE);

        _PaintCircle.setStrokeWidth(line.getLineWidth());
        _PaintCircle.setColor(line.getLineColor());

        List<Entry> list = line.getEntries();

        // check
        if (list == null || list.size() == 0) {
            return;
        }

        // 考虑只有一个点的情况
        if (list.size() == 1) {
            Entry hit = list.get(0);
            SingleF_XY xy = _MappingManager.getPxByEntry(hit);
            canvas.drawCircle(xy.getX(), xy.getY(), line.getCircleR(), _PaintCircle);
            return;
        }

        double xMin_Visiable = lineChart.getVisiableMinX();
        double xMax_Visiable = xMin_Visiable + (lineChart.getVisiableMaxX() - xMin_Visiable) * _LAnimator.get_hitValueX();// 考虑动画

        int minIndex = Line.getEntryIndex(list, xMin_Visiable, Line.Rounding.DOWN);
        int maxIndex = Line.getEntryIndex(list, xMax_Visiable, Line.Rounding.UP);

        if (Math.abs(maxIndex - minIndex) == 0) {
            return;
        }

        if ((maxIndex - minIndex) > 1500) {
            _PaintLine.setAntiAlias(false);// 考虑性能
        } else {
            _PaintLine.setAntiAlias(true);
        }

        _PathLine.reset();

        int breakI = -1;

        for (int i = minIndex; i <= maxIndex; i++) {
            Entry entry = list.get(i);

            // 考虑这个点是否断掉
            if (entry.isNull_Y()) {
                breakI = i;
                continue;
            }

            float sx = _MappingManager.v2p_x(entry.getX());
            float sy = getAnimateY(_MappingManager.v2p_y(entry.getY()));

            if (i == minIndex || i == breakI + 1) {
                _PathLine.moveTo(sx, sy);
            } else {
                _PathLine.lineTo(sx, sy);
            }

            if (line.isDrawCircle()) {
                SingleF_XY xy = _MappingManager.getPxByEntry(entry);
                canvas.drawCircle(xy.getX(), getAnimateY(xy.getY()), line.getCircleR(), _PaintCircle);

                // 把最后点一个绘制出来
                if (i == maxIndex - 1) {
                    Entry last = list.get(maxIndex);
                    xy = _MappingManager.getPxByEntry(last);
                    /////////////////////////////////////////////  考虑动画效果  //////////////////////////////////////////
                    canvas.drawCircle(xy.getX(), getAnimateY(xy.getY()), line.getCircleR(), _PaintCircle);
                }
            }
        }

        canvas.drawPath(_PathLine, _PaintLine);

        // 有断掉的点，就不考虑填充了
        if (breakI != -1) {
            return;
        }

        // 考虑填充
        if (line.isFilled()) {
            Entry start = list.get(minIndex);
            Entry end = list.get(maxIndex);
            float sx = _MappingManager.v2p_x(start.getX());
            float sy = getAnimateY(_MappingManager.v2p_y(start.getY()));
            float ex = _MappingManager.v2p_x(end.getX());
            float ey = getAnimateY(_MappingManager.v2p_y(end.getY()));

            float maxY = Math.max(sy, ey);

            _PathLine.lineTo(ex, lineChart.get_MainPlotRect().bottom);
            _PathLine.lineTo(sx, lineChart.get_MainPlotRect().bottom);

            _PathLine.close();

            _PaintLine.setStyle(Paint.Style.FILL);
            _PaintLine.setAlpha(50);

            Shader shader = new LinearGradient(0, maxY, 0, 0, line.getLineColor(), line.getLineColor() / 50, Shader.TileMode.CLAMP);
            _PaintLine.setShader(shader);

            canvas.drawPath(_PathLine, _PaintLine);
            _PaintLine.setStyle(Paint.Style.STROKE);
            _PaintLine.setShader(null);
        }
    }


    RectF _RectFBuffer = new RectF();

    private void drawLegend(Canvas canvas, Line line, int order) {

        if (!line.isDrawLegend()) {
            return;
        }

        _PaintLegend.setColor(line.getLineColor());
        _PaintLegend.setTextSize(line.getLegendTextSize());

        String name = line.getName();
        float txtH = Utils.textHeight(_PaintLegend);
        float cubic = 20;

        _RectFBuffer.left = order * line.getLegendWidth();
        _RectFBuffer.top = line.getLegendHeight() - cubic - txtH / 2;
        _RectFBuffer.right = _RectFBuffer.left + cubic;
        _RectFBuffer.bottom = _RectFBuffer.top + cubic;


        canvas.drawRect(_RectFBuffer, _PaintLegend);
        canvas.drawText(name, _RectFBuffer.right + 10, _RectFBuffer.bottom, _PaintLegend);
    }

    public void onDataChanged(Lines lines) {
        _lines = lines;
    }

    private float getAnimateY(float src) {
        return lineChart.get_MainPlotRect().bottom - (lineChart.get_MainPlotRect().bottom - src) * _LAnimator.get_hitValueY();
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/AdvancedActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;
import com.linheimx.app.plus.LineChartAdvanced;

import java.util.ArrayList;
import java.util.List;

public class AdvancedActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_advanced);

        getSupportActionBar().setTitle("折线图：双光标");

        LineChartAdvanced lineChartAdvanced = (LineChartAdvanced) findViewById(R.id.linechart);

        setChartData(lineChartAdvanced.get_lineChart());
    }


    private void setChartData(LineChart lineChart) {

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X1:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y1:" + Math.round(value * 100) / 100f;//保留两位小数
            }
        });

        HighLight highLight2 = lineChart.get_HighLight2();
        highLight2.setHighLightColor(Color.GREEN);
        highLight2.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight2.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X2:" + value;
            }
        });
        highLight2.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y2:" + Math.round(value * 100) / 100f;//保留两位小数
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
        xAxis.set_unit("s");

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("m");

        // 数据
        Line line = new Line();
        line.setDrawCircle(false);//不画圆圈
        line.setLineColor(Color.BLUE);
        List<Entry> list = new ArrayList<>();
        for (int i = 0; i < 300; i++) {
            list.add(new Entry(i, (float) Math.random()));
        }
        line.setEntries(list);

        Lines lines = new Lines();
        lines.addLine(line);

        lineChart.setLines(lines);
    }

}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/ScrollLoadActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.linheimx.app.library.adapter.DefaultValueAdapter;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.listener.IDragListener;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;

import java.util.ArrayList;
import java.util.List;

public class ScrollLoadActivity extends AppCompatActivity {

    LineChart _lineChart;
    ProgressDialog _dialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scroll_load);

        getSupportActionBar().setTitle("滑动加载");

        _lineChart = (LineChart) findViewById(R.id.chart);


        _dialog = new ProgressDialog(this);
        _dialog.setTitle("loading...");

        setChartData(_lineChart);
    }


    private void setChartData(LineChart lineChart) {

//        _lineChart.setDragable(true);
//        _lineChart.setScaleable(false);


        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y:" + value;
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
        xAxis.set_unit("单位：s");
        xAxis.set_ValueAdapter(new DefaultValueAdapter(1));

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("单位：m");
        yAxis.set_ValueAdapter(new DefaultValueAdapter(3));// 默认精度到小数点后2位,现在修改为3位精度

        // 数据
        final Line line = new Line();
        List<Entry> list = new ArrayList<>();
        list.add(new Entry(1, 5));
        list.add(new Entry(2, 4));
        list.add(new Entry(3, 2));
        list.add(new Entry(4, 3));
        list.add(new Entry(10, 8));
        line.setEntries(list);

        Lines lines = new Lines();
        lines.addLine(line);


        lineChart.setLines(lines);

        _lineChart.set_dragListener(new IDragListener() {
            @Override
            public void onDrag(final double xMin, final double xMax) {

                // 右边添加更多的数据
                if (xMax > line.getmXMax()) {
                    _dialog.show();
                    _lineChart.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            line.addEntry(new Entry(xMax + 1, 1));
                            line.addEntry(new Entry(xMax + 2, 5));
                            _lineChart.notifyDataChanged();
                            _lineChart.invalidate();
                            _dialog.dismiss();
                        }
                    }, 1000);
                }

                // 左边添加更多的数据
                if (xMin < line.getmXMin()) {
                    _dialog.show();
                    _lineChart.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            line.addEntryInHead(new Entry(xMin - 1, 1));
                            line.addEntryInHead(new Entry(xMin - 2, 5));
                            _lineChart.notifyDataChanged();
                            _lineChart.invalidate();
                            _dialog.dismiss();
                        }
                    }, 1000);
                }
            }
        });
    }


}


<|start_filename|>library/src/main/java/com/linheimx/app/library/charts/LineChart.java<|end_filename|>
package com.linheimx.app.library.charts;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.UiThread;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.linheimx.app.library.R;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.animate.LAnimator;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.listener.IDragListener;
import com.linheimx.app.library.manager.MappingManager;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;
import com.linheimx.app.library.render.GodRender;
import com.linheimx.app.library.render.HighLightRender;
import com.linheimx.app.library.render.LineRender;
import com.linheimx.app.library.render.NoDataRender;
import com.linheimx.app.library.render.XAxisRender;
import com.linheimx.app.library.render.YAxisRender;
import com.linheimx.app.library.touch.GodTouchListener;
import com.linheimx.app.library.touch.TouchListener;
import com.linheimx.app.library.utils.LogUtil;
import com.linheimx.app.library.utils.RectD;
import com.linheimx.app.library.utils.SingleD_XY;
import com.linheimx.app.library.utils.Utils;

import java.util.List;

/**
 * Created by lijian on 2016/11/13.
 */

public class LineChart extends Chart {

    MappingManager _MappingManager;

    Lines _lines;

    ////////////////////////////  listener  ///////////////////////////
    IDragListener _dragListener;

    ////////////////////////// function //////////////////////////
    boolean isHighLightEnabled = true;
    boolean isTouchEnabled = true;
    boolean isDragable = true;
    boolean isScaleable = true;
    ChartMode _ChartMode;
    CursorMode _CursorMode = CursorMode.cursor1;// 默认使用光标1

    ///////////////////////////////// parts ////////////////////////////////
    XAxis _XAxis;
    YAxis _YAxis;
    HighLight _HighLight1;// 光标1
    HighLight _HighLight2;// 光标2

    //////////////////////////////////  render  /////////////////////////////
    NoDataRender _NoDataRender;
    XAxisRender _XAxisRender;
    YAxisRender _YAxisRender;
    LineRender _LineRender;
    HighLightRender _HighLightRender1;// 光标1
    HighLightRender _HighLightRender2;// 光标2
    GodRender _GodRender;


    ////////////////////////////// touch  /////////////////////////////
    TouchListener _TouchListener;
    GodTouchListener _GodTouchListener;

    //////////////////////////// 区域 ///////////////////////////
    RectF _MainPlotRect;// 主要的绘图区域

    float _paddingLeft = 40;
    float _paddingRight = 5;
    float _paddingTop = 17;
    float _paddingBottom = 15;

    RectF _GodRect;//

    //////////////////////////////  animator  ////////////////////////////
    LAnimator _LAnimator;


    public LineChart(Context context) {
        super(context);
    }

    public LineChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public LineChart(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void init(Context context, AttributeSet attributeSet) {
        super.init(context, attributeSet);

        TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.LineChart);
        boolean isGodMode = typedArray.getBoolean(R.styleable.LineChart_god_mode, false);
        _ChartMode = isGodMode ? ChartMode.God : ChartMode.Normal;
        typedArray.recycle();

        // animator
        _LAnimator = new LAnimator(this);

        // init v
        _MainPlotRect = new RectF();
        _MappingManager = new MappingManager(_MainPlotRect);
        _GodRect = new RectF();

        // models
        _XAxis = new XAxis();
        _YAxis = new YAxis();
        _HighLight1 = new HighLight();
        _HighLight2 = new HighLight();

        // render
        _NoDataRender = new NoDataRender(_MainPlotRect, _MappingManager);
        _XAxisRender = new XAxisRender(_MainPlotRect, _MappingManager, _XAxis);
        _YAxisRender = new YAxisRender(_MainPlotRect, _MappingManager, _YAxis);
        _LineRender = new LineRender(_MainPlotRect, _MappingManager, _lines, this);
        _HighLightRender1 = new HighLightRender(this, HighLightRender.H1, _MainPlotRect, _MappingManager, _HighLight1);
        _HighLightRender2 = new HighLightRender(this, HighLightRender.H2, _MainPlotRect, _MappingManager, _HighLight2);

        _GodRender = new GodRender(_MainPlotRect, _MappingManager, _GodRect);

        // touch listener
        _TouchListener = new TouchListener(this);
        _GodTouchListener = new GodTouchListener(this);

        // other
        _paddingLeft = Utils.dp2px(_paddingLeft);
        _paddingRight = Utils.dp2px(_paddingRight);
        _paddingTop = Utils.dp2px(_paddingTop);
        _paddingBottom = Utils.dp2px(_paddingBottom);
    }


    @Override
    public void computeScroll() {
        super.computeScroll();

        if (_ChartMode == ChartMode.Normal) {
            _TouchListener.computeScroll();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        if (_lines == null) {
            return false;
        }
        if (!isTouchEnabled) {
            return false;
        }

        if (_ChartMode == ChartMode.Normal) {
            return _TouchListener.onTouch(this, event);
        } else if (_ChartMode == ChartMode.God) {
            return _GodTouchListener.onTouch(this, event);
        }

        return false;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 1. render no data
        if (_lines == null || _lines.getLines() == null || _lines.getLines().size() == 0) {
            _NoDataRender.render(canvas);
            return;
        }

        // 计算轴线上的数值
        Line line = _lines.getLines().get(0);
        double xmin = getVisiableMinX();
        double xmax = getVisiableMaxX();
        double ymin = getVisiableMinY();
        double ymax = getVisiableMaxY();
        _XAxis.calValues(xmin, xmax, line, xmin, xmax);
        _YAxis.calValues(ymin, ymax, line, xmin, xmax);

        // render grid line
        _XAxisRender.renderGridline(canvas);
        _YAxisRender.renderGridline(canvas);

        // render line
        _LineRender.render(canvas);
        // render high light
        _HighLightRender1.render(canvas);// 光标1
        _HighLightRender2.render(canvas);// 光标2

        // render god
        if (_ChartMode == ChartMode.God) {
            _GodRender.render(canvas);
        }

        // render warn line
        _XAxisRender.renderWarnLine(canvas);
        _YAxisRender.renderWarnLine(canvas);

        // render Axis
        _XAxisRender.renderAxisLine(canvas);
        _YAxisRender.renderAxisLine(canvas);

        // render labels
        _XAxisRender.renderLabels(canvas);
        _YAxisRender.renderLabels(canvas);

        // render unit
        _XAxisRender.renderUnit(canvas);
        _YAxisRender.renderUnit(canvas);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        _LineRender.onChartSizeChanged(w, h);
        notifyDataChanged();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();

        _lines = null;
    }

    /**
     * 通知数据改变
     */
    public void notifyDataChanged() {

        limitMainPlotArea();

        if (_lines == null) {
            return;
        }
        _lines.calMinMax();

        prepareMap();

        // 2. onDataChanged
        _LineRender.onDataChanged(_lines);
    }

    /**
     * 限制 主绘图区域的边界
     */
    private void limitMainPlotArea() {

        _MainPlotRect.setEmpty();
        _MainPlotRect.right += _MainPlotRect.left + getWidth();
        _MainPlotRect.bottom += _MainPlotRect.top + getHeight();

        // 0. padding
        offsetPadding();
        // 1. 计算label,unit的宽高
        offsetArea();

        if (_ChartMode == ChartMode.God) {
            _GodRect.set(_MainPlotRect);
            _GodRect.right = _GodRect.right / 3;

            // 设置预览窗口
            _GodTouchListener.changeViewPort(0, 0);
        }
    }

    private void offsetPadding() {

        // 考虑图例
        if (_lines != null) {
            int h = 0;
            for (Line line : _lines.getLines()) {
                if (line.getLegendHeight() > h) {
                    h = line.getLegendHeight();
                }
            }

            if (h > 0) {
                _paddingTop = h;
            }
        }

        _MainPlotRect.left += _paddingLeft;
        _MainPlotRect.top += _paddingTop;
        _MainPlotRect.right -= _paddingRight;
        _MainPlotRect.bottom -= _paddingBottom;
    }

    private void offsetArea() {

        _YAxisRender.paint_label();
        _YAxisRender.paint_unit();
        Paint paintLabel = _YAxisRender.get_PaintLabel();
        Paint paintUnit = _YAxisRender.get_PaintUnit();

        /*******************************  取一堆label中的head middle tail 中的最大值  ***********************************/
        float labelDimen = _YAxis.getLabelDimen();

        if (_lines != null && _lines.getLines().size() > 0) {
            Line line = _lines.getLines().get(0);

            if (line.getEntries().size() > 0) {
                List<Entry> entryList = line.getEntries();

                Entry head = entryList.get(0);
                Entry tail = entryList.get(entryList.size() - 1);
                Entry middle = entryList.get((0 + entryList.size() - 1) / 2);

                IValueAdapter yAdapter = _YAxis.get_ValueAdapter();
                String s1 = yAdapter.value2String(head.getY());
                float w1 = Utils.textWidth(paintLabel, s1);
                if (labelDimen < w1) {
                    labelDimen = w1;
                }

                String s2 = yAdapter.value2String(middle.getY());
                float w2 = Utils.textWidth(paintLabel, s2);
                if (labelDimen < w2) {
                    labelDimen = w2;
                }

                String s3 = yAdapter.value2String(tail.getY());
                float w3 = Utils.textWidth(paintLabel, s3);
                if (labelDimen < w3) {
                    labelDimen = w3;
                }
            }

        }

        // 考虑y label和unit
        _MainPlotRect.left += _YAxis.offsetLeft(labelDimen, Utils.textHeight(paintUnit));
        // 考虑x label和unit
        _MainPlotRect.bottom -= _XAxis.offsetBottom(Utils.textHeight(paintLabel), Utils.textHeight(paintUnit));
    }


    /**
     * 准备映射关系
     */
    private void prepareMap() {

        double xMin = _lines.getmXMin();
        double xMax = _lines.getmXMax();
        double yMin = _lines.getmYMin();
        double yMax = _lines.getmYMax();

        _MappingManager.prepareRelation(xMin, xMax, yMin, yMax);
    }

    /**
     * 设置数据源
     *
     * @param lines
     */
    public void setLines(Lines lines) {
        _lines = lines;

        notifyDataChanged();
        postInvalidate();
    }

    public Lines getlines() {
        return _lines;
    }

    /**
     * 清空数据
     */
    public void clearData() {
        _lines = null;
        invalidate();
    }


    private void A______________________________________________() {

    }

    /**
     * Y方向进行动画
     */
    @UiThread
    public void animateY() {
        _LAnimator.animateY(1000);
    }

    /**
     * Y方向进行动画
     */
    @UiThread
    public void animateY(long duration) {
        _LAnimator.animateY(duration);
    }

    /**
     * X方向进行动画
     */
    @UiThread
    public void animateX() {
        _LAnimator.animateX(1000);
    }

    /**
     * X方向进行动画
     */
    @UiThread
    public void animateX(long duration) {
        _LAnimator.animateX(duration);
    }

    /**
     * X,Y方向进行动画
     */
    @UiThread
    public void animateXY() {
        _LAnimator.animateXY(1000);
    }

    /**
     * X,Y方向进行动画
     */
    @UiThread
    public void animateXY(long duration) {
        _LAnimator.animateXY(duration);
    }

    public LAnimator get_LAnimator() {
        return _LAnimator;
    }

    public void set_LAnimator(LAnimator _LAnimator) {
        this._LAnimator = _LAnimator;
    }


    private void B_________________________________________________() {

    }

    private void a______________________________________________() {

    }

    public boolean isCanX_drag() {
        return _TouchListener.isCanX_drag();
    }

    /**
     * 设置x方向是否可拖动
     *
     * @param canX_drag
     */
    public void setCanX_drag(boolean canX_drag) {
        _TouchListener.setCanX_drag(canX_drag);
    }

    public boolean isCanY_drag() {
        return _TouchListener.isCanY_drag();
    }

    /**
     * 设置y方向是否可拖动
     *
     * @param canY_drag
     */
    public void setCanY_drag(boolean canY_drag) {
        _TouchListener.setCanY_drag(canY_drag);
    }

    public boolean isZoom_alone() {
        return _TouchListener.isZoom_alone();
    }

    /**
     * 设置x,y方向是否可以独立缩放
     *
     * @param zoom_independent
     */
    public void setZoom_alone(boolean zoom_independent) {
        _TouchListener.setZoom_alone(zoom_independent);
    }

    public boolean isCanX_zoom() {
        return _TouchListener.isCanX_zoom();
    }

    /**
     * 设置x方向是否可以缩放
     *
     * @param canX_zoom
     */
    public void setCanX_zoom(boolean canX_zoom) {
        _TouchListener.setCanX_zoom(canX_zoom);
    }

    public boolean isCanY_zoom() {
        return _TouchListener.isCanY_zoom();
    }

    /**
     * 设置y方向是否可以缩放
     *
     * @param canY_zoom
     */
    public void setCanY_zoom(boolean canY_zoom) {
        _TouchListener.setCanY_zoom(canY_zoom);
    }

    public boolean isDragable() {
        return isDragable;
    }

    public void setDragable(boolean dragable) {
        isDragable = dragable;
    }

    public boolean isScaleable() {
        return isScaleable;
    }

    public void setScaleable(boolean scaleable) {
        isScaleable = scaleable;
    }

    public IDragListener get_dragListener() {
        return _dragListener;
    }

    public void set_dragListener(IDragListener _dragListener) {
        this._dragListener = _dragListener;
    }

    private void b______________________________________________() {

    }

    public float get_paddingLeft() {
        return _paddingLeft;
    }

    public void set_paddingLeft(float _paddingLeft) {
        this._paddingLeft = _paddingLeft;
    }

    public float get_paddingRight() {
        return _paddingRight;
    }

    public void set_paddingRight(float _paddingRight) {
        this._paddingRight = _paddingRight;
    }

    public float get_paddingTop() {
        return _paddingTop;
    }

    public void set_paddingTop(float _paddingTop) {
        this._paddingTop = _paddingTop;
    }

    public float get_paddingBottom() {
        return _paddingBottom;
    }

    public void set_paddingBottom(float _paddingBottom) {
        this._paddingBottom = _paddingBottom;
    }

    private void c______________________________________________() {

    }

    public double getVisiableMinX() {
        float px = _MainPlotRect.left;
        SingleD_XY xy = _MappingManager.getValueByPx(px, 0);
        return xy.getX();
    }

    public double getVisiableMaxX() {
        float px = _MainPlotRect.right;
        SingleD_XY xy = _MappingManager.getValueByPx(px, 0);
        return xy.getX();
    }

    public double getVisiableMinY() {
        float py = _MainPlotRect.bottom;
        SingleD_XY xy = _MappingManager.getValueByPx(0, py);
        return xy.getY();
    }

    public double getVisiableMaxY() {
        float py = _MainPlotRect.top;
        SingleD_XY xy = _MappingManager.getValueByPx(0, py);
        return xy.getY();
    }

    public RectD get_currentViewPort() {
        return _MappingManager.get_currentViewPort();
    }

    public void set_currentViewPort(RectD currentViewPort) {
        _MappingManager.set_currentViewPort(currentViewPort);
    }

    /**
     * 设置y轴的范围
     *
     * @param yMin
     * @param yMax
     */
    public void setYMax_Min(double yMin, double yMax) {
        if (_lines != null) {
            _lines.setYCustomMaxMin(true);
            _lines.setmYMin(yMin);
            _lines.setmYMax(yMax);
            postInvalidate();
        } else {
            LogUtil.e("setAxisMaxMin: 请在lines设置后，调用此方法！");
        }
    }

    /**
     * 设置轴线的范围
     *
     * @param xMin
     * @param xMax
     */
    public void setXAix_MaxMin(double xMin, double xMax) {
        if (_lines != null) {
            _lines.setXCustomMaxMin(true);
            _lines.setmXMin(xMin);
            _lines.setmXMax(xMax);
            postInvalidate();
        } else {
            LogUtil.e("setAxisMaxMin: 请在lines设置后，调用此方法！");
        }
    }

    private void d______________________________________________() {

    }

    /**
     * 获取映射管家
     *
     * @return
     */
    public MappingManager get_MappingManager() {
        return _MappingManager;
    }


    ////////////////////////////////  便捷的方法  //////////////////////////////////


    public CursorMode get_CursorMode() {
        return _CursorMode;
    }

    /**
     * 设置使用哪一个光标
     * ---------------------
     * 第一个？
     * 第二个？
     *
     * @param _CursorMode
     */
    public void set_CursorMode(CursorMode _CursorMode) {
        this._CursorMode = _CursorMode;
    }

    public void highLight_PixXY(float px, float py) {
        SingleD_XY xy = _MappingManager.getValueByPx(px, py);
        highLight_ValueXY(xy.getX(), xy.getY());
    }

    public void highLight_ValueXY(double x, double y) {

        if (_CursorMode == CursorMode.cursor1) {
            _HighLightRender1.highLight_ValueXY(x, y);
        } else if (_CursorMode == CursorMode.cursor2) {
            _HighLightRender2.highLight_ValueXY(x, y);
        }

        invalidate();
    }

    public void highLightLeft() {

        if (_CursorMode == CursorMode.cursor1) {
            _HighLightRender1.highLightLeft();
        } else if (_CursorMode == CursorMode.cursor2) {
            _HighLightRender2.highLightLeft();
        }

        invalidate();
    }

    public void highLightRight() {

        if (_CursorMode == CursorMode.cursor1) {
            _HighLightRender1.highLightRight();
        } else if (_CursorMode == CursorMode.cursor2) {
            _HighLightRender2.highLightRight();
        }

        invalidate();
    }

    public HighLight get_HighLight1() {
        return _HighLight1;
    }

    public HighLight get_HighLight2() {
        return _HighLight2;
    }

    public HighLightRender get_HighLightRender1() {
        return _HighLightRender1;
    }

    public HighLightRender get_HighLightRender2() {
        return _HighLightRender2;
    }

    public XAxis get_XAxis() {
        return _XAxis;
    }

    public YAxis get_YAxis() {
        return _YAxis;
    }

    public RectF get_GodRect() {
        return _GodRect;
    }

    public void set_GodRect(RectF _GodRect) {
        this._GodRect = _GodRect;
    }

    public RectF get_MainPlotRect() {
        return _MainPlotRect;
    }

    public void set_MainPlotRect(RectF _MainPlotRect) {
        this._MainPlotRect = _MainPlotRect;
    }

    public ChartMode get_ChartMode() {
        return _ChartMode;
    }

    public LineChart set_ChartMode(ChartMode _ChartMode) {
        this._ChartMode = _ChartMode;
        return this;
    }

    LineChart _ob_linechart;

    public void registObserver(LineChart lineChartOb) {
        this._ob_linechart = lineChartOb;

        notifyDataChanged_FromOb(lineChartOb);
    }

    public void notifyDataChanged_FromOb(LineChart lineChartOb) {

        // x,y轴上的单位
        XAxis xAxis = lineChartOb.get_XAxis();
        this.get_XAxis().set_unit(xAxis.get_unit());

        YAxis yAxis = lineChartOb.get_YAxis();
        this.get_YAxis().set_unit(yAxis.get_unit());

        this.setLines(lineChartOb.getlines());
    }

    public void notifyOB_ViewportChanged(RectD _currentViewPort) {
        _ob_linechart.set_CurrentViewPort(_currentViewPort);
        _ob_linechart.invalidate();
    }

    public LineChart set_CurrentViewPort(RectD _currentViewPort) {
        _MappingManager.set_currentViewPort(_currentViewPort);
        return this;
    }


    public enum ChartMode {
        Normal, God
    }

    public enum CursorMode {
        cursor1, cursor2
    }


}


<|start_filename|>library/src/main/java/com/linheimx/app/library/render/XAxisRender.java<|end_filename|>
package com.linheimx.app.library.render;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;

import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.manager.MappingManager;
import com.linheimx.app.library.model.Axis;
import com.linheimx.app.library.model.WarnLine;
import com.linheimx.app.library.utils.SingleF_XY;
import com.linheimx.app.library.utils.Utils;

import java.util.List;

/**
 * Created by lijian on 2016/11/14.
 */

public class XAxisRender extends AxisRender {

    public XAxisRender(RectF _FrameManager, MappingManager _MappingManager, Axis axis) {
        super(_FrameManager, _MappingManager, axis);
    }

    @Override
    public void renderAxisLine(Canvas canvas) {
        super.renderAxisLine(canvas);

        float startX = _rectMain.left;
        float startY = _rectMain.bottom;
        float stopX = _rectMain.right;
        float stopY = _rectMain.bottom;

        canvas.drawLine(startX, startY, stopX, stopY, _PaintAxis);
    }


    @Override
    public void renderGridline(Canvas canvas) {
        super.renderGridline(canvas);

        canvas.save();
        canvas.clipRect(_rectMain);// 限制绘制区域

        double[] values = _Axis.getLabelValues();
        int labelCount = _Axis.getLabelCount();
        float x = 0;

        float top = _rectMain.top;
        float bottom = _rectMain.bottom;

        _PathGrid.reset();

        for (int i = 0; i < labelCount; i++) {
            if (values.length < (i + 1)) {
                break;
            }

            double value = values[i];

            SingleF_XY xy = _MappingManager.getPxByValue(value, 0);
            x = xy.getX();

            _PathGrid.moveTo(x, bottom);
            _PathGrid.lineTo(x, top);
        }

        // grid line
        canvas.drawPath(_PathGrid, _PaintGridline);

        canvas.restore();
    }

    @Override
    public void renderLabels(Canvas canvas) {
        super.renderLabels(canvas);

        double[] values = _Axis.getLabelValues();
        int labelCount = _Axis.getLabelCount();

        IValueAdapter adapter = _Axis.get_ValueAdapter();
        float indicator = _Axis.getLeg();

        float x = 0;

        float bottom = _rectMain.bottom;

        for (int i = 0; i < labelCount; i++) {
            if (values.length < (i + 1)) {
                break;
            }

            double value = values[i];
            String label = adapter.value2String(value);

            SingleF_XY xy = _MappingManager.getPxByValue(value, 0);
            x = xy.getX();

            // check
            if (x < _rectMain.left || x > _rectMain.right) {
                continue;
            }

            if (label == null) {
                continue;
            }

            // indicator
            canvas.drawLine(x, bottom, x, bottom + indicator, _PaintLittle);

            // label
            float labelX = x - Utils.textWidth(_PaintLabel, label) / 2;
            float labelY = bottom + _Axis.getLeg() + _Axis.getLabelDimen();
            canvas.drawText(label, labelX, labelY, _PaintLabel);
        }
    }


    @Override
    public void renderUnit(Canvas canvas) {
        super.renderUnit(canvas);

        String unit = _Axis.get_unit();
        Paint paintUnit = _PaintUnit;

        float bottom = _rectMain.bottom;
        float labelX = _rectMain.centerX() - Utils.textWidth(paintUnit, unit) / 2;
        float labelY = bottom + _Axis.getLeg() + _Axis.getLabelDimen() + _Axis.getUnitDimen();

        canvas.drawText(unit, labelX, labelY, _PaintUnit);
    }


    @Override
    public void renderWarnLine(Canvas canvas) {
        super.renderWarnLine(canvas);

        List<WarnLine> warnLines = _Axis.getListWarnLins();
        if (warnLines == null) {
            return;
        }

        canvas.save();
        canvas.clipRect(_rectMain);

        for (WarnLine warnLine : warnLines) {
            if (warnLine.isEnable()) {
                double value = warnLine.getValue();

                SingleF_XY xy = _MappingManager.getPxByValue(value, 0);
                float x = xy.getX();

                if (x < _rectMain.left || x > _rectMain.right) {
                    continue;
                }

                _PaintWarnText.setColor(warnLine.getWarnColor());
                _PaintWarnText.setStrokeWidth(warnLine.getWarnLineWidth());
                _PaintWarnText.setTextSize(warnLine.getTxtSize());

                _PaintWarnPath.setColor(warnLine.getWarnColor());
                _PaintWarnPath.setStrokeWidth(warnLine.getWarnLineWidth());

                _PathWarn.reset();
                _PathWarn.moveTo(x, _rectMain.bottom);
                _PathWarn.lineTo(x, _rectMain.top);

                canvas.drawPath(_PathWarn, _PaintWarnPath);

                float txtHeight = Utils.textHeight(_PaintWarnText);
                float txtWidth = Utils.textWidth(_PaintWarnText, "" + value);

                canvas.drawText(value + "", x - txtWidth * 1.5f, _rectMain.bottom - txtHeight * 1.5f, _PaintWarnText);
            }
        }

        canvas.restore();
    }

}


<|start_filename|>app/src/main/java/com/linheimx/app/chart_dialog/ChartPreviewDialog.java<|end_filename|>
package com.linheimx.app.chart_dialog;

import android.app.Dialog;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.linheimx.app.lchart.R;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;
import com.linheimx.app.plus.LineChartPlus;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by LJIAN on 2017/3/9.
 */

public class ChartPreviewDialog extends DialogFragment {

    public static ChartPreviewDialog newInstance(String title) {
        ChartPreviewDialog dialog = new ChartPreviewDialog();
        Bundle bundle = new Bundle();
        bundle.putString("title", title);
        dialog.setArguments(bundle);
        return dialog;
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_chart_god, null);

        LineChart lineChart1 = ((LineChartPlus) view.findViewById(R.id.chart1)).get_lineChart();
        LineChart godLineChart = (LineChart) view.findViewById(R.id.chart2);

        godLineChart.registObserver(lineChart1);

        setChartData(lineChart1);

        // 通知 lineChart2 数据改变了（因为lineChart1改变了）
        godLineChart.notifyDataChanged_FromOb(lineChart1);

        return view;
    }


    @Override
    public void onStart() {
        super.onStart();

        // safety check
        if (getDialog() == null)
            return;

        String title = "";
        Bundle bun = getArguments();
        if (bun != null) {
            title = bun.getString("title");
        }

        Dialog dialog = getDialog();
        dialog.setTitle(title);

        int width = ViewGroup.LayoutParams.MATCH_PARENT;
        int height = ViewGroup.LayoutParams.MATCH_PARENT;
        dialog.getWindow().setLayout(width, height);
    }

    private void setChartData(LineChart lineChart) {

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y:" + value;
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
        xAxis.set_unit("s");

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("m");

        Line line = new Line();
        line.setDrawCircle(false);
        List<Entry> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            list.add(new Entry(i, (float) Math.random()));
        }
        line.setEntries(list);

        List<Line> list2 = new ArrayList<>();
        list2.add(line);
        Lines lines = new Lines(list2);

        lineChart.setLines(lines);
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/plus/LineChartPlus.java<|end_filename|>
package com.linheimx.app.plus;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;

import com.linheimx.app.lchart.R;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Lines;

/**
 * 包装一下 lineChart
 *
 * Created by LJIAN on 2017/1/9.
 */

public class LineChartPlus extends FrameLayout {

    LineChart _lineChart;

    public LineChartPlus(Context context) {
        super(context);
        init(context);
    }

    public LineChartPlus(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public LineChartPlus(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }


    private void init(Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.linechart_plus, null);
        addView(view);

        _lineChart = (LineChart) view.findViewById(R.id.linechart);

        ImageButton btnLeft = (ImageButton) view.findViewById(R.id.btnLeft);
        ImageButton btnRight = (ImageButton) view.findViewById(R.id.btnRight);

        btnLeft.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                btnLeft();
            }
        });

        btnRight.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                btnRight();
            }
        });
    }

    public void setLines(Lines lines) {
        _lineChart.setLines(lines);
    }

    public LineChart get_lineChart() {
        return _lineChart;
    }

    public void set_lineChart(LineChart _lineChart) {
        this._lineChart = _lineChart;
    }

    public void btnLeft() {
        _lineChart.highLightLeft();
    }

    public void btnRight() {
        _lineChart.highLightRight();
    }

}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/fragment/ScrollView_Fragment.java<|end_filename|>
package com.linheimx.app.lchart.fragment;

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.linheimx.app.lchart.R;

import java.util.ArrayList;
import java.util.List;


public class ScrollView_Fragment extends Fragment {


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_scroll_view_, container, false);
        return view;
    }

}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/fragment/LineChartFragment.java<|end_filename|>
package com.linheimx.app.lchart.fragment;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.linheimx.app.lchart.R;
import com.linheimx.app.library.adapter.DefaultValueAdapter;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by LJIAN on 2017/3/17.
 */

public class LineChartFragment extends Fragment {


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_line_chart, container, false);
        LineChart lineChart = (LineChart) view.findViewById(R.id.chart);

        setChartData(lineChart);
        return view;
    }


    private void setChartData(LineChart lineChart) {

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y:" + value;
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
        xAxis.set_unit("单位：s");
        xAxis.set_ValueAdapter(new DefaultValueAdapter(1));

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("单位：m");
        yAxis.set_ValueAdapter(new DefaultValueAdapter(3));// 默认精度到小数点后2位,现在修改为3位精度

        // 数据
        Line line = new Line();
        List<Entry> list = new ArrayList<>();
        list.add(new Entry(1, 5));
        list.add(new Entry(2, 4));
        list.add(new Entry(3, 2));
        list.add(new Entry(4, 3));
        list.add(new Entry(10, 8));
        line.setEntries(list);

        Lines lines = new Lines();
        lines.addLine(line);


        lineChart.setLines(lines);
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/fragment/ViewPager_Fragment.java<|end_filename|>
package com.linheimx.app.lchart.fragment;

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.linheimx.app.lchart.R;

import java.util.ArrayList;
import java.util.List;


public class ViewPager_Fragment extends Fragment {


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_view_pager_, container, false);

        TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab);
        ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewpager);

        viewPager.setOffscreenPageLimit(2);
        viewPager.setAdapter(new Adapter(getChildFragmentManager()));
        tabLayout.setupWithViewPager(viewPager);

        return view;
    }


    class Adapter extends FragmentStatePagerAdapter {

        List<Fragment> list;

        public Adapter(FragmentManager fm) {
            super(fm);

            list = new ArrayList<>();
            list.add(new LineChartFragment());
            list.add(new LineChartFragment());
            list.add(new LineChartFragment());
        }

        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Fragment getItem(int position) {
            return list.get(position);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return "chart " + position;
        }
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/LineChartActivity.java<|end_filename|>
package com.linheimx.app.lchart;


import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.SeekBar;

import com.linheimx.app.library.adapter.DefaultValueAdapter;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.Axis;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class LineChartActivity extends AppCompatActivity {

    LineChart _lineChart;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_line_chart);

        getSupportActionBar().setTitle("折线图：基本");

        _lineChart = (LineChart) findViewById(R.id.chart);
        SeekBar sb1 = (SeekBar) findViewById(R.id.sb_entry_more);
        CheckBox cb = (CheckBox) findViewById(R.id.cb_high);
        CheckBox cb_fill = (CheckBox) findViewById(R.id.cb_fill);

//        _lineChart.setCanX_drag(true);// x 方向可以拖拽
//        _lineChart.setCanY_drag(false);// y 方向不可拖拽
//        _lineChart.setCanX_zoom(true);// x 方向可以缩放
//        _lineChart.setCanY_zoom(false);// y 方向不可用缩放
//        _lineChart.setZoom_alone(true);// 设置在 x，y方向上是否要独立缩放


        setChartData(_lineChart);

        sb1.setProgress(5);
        sb1.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                Lines lines = _lineChart.getlines();
                Line line = lines.getLines().get(0);

                line.setEntries(generateLineData(progress));
                _lineChart.notifyDataChanged();
                _lineChart.invalidate();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                HighLight highLight = _lineChart.get_HighLight1();
                highLight.setEnable(isChecked);// 启用高亮显示  默认为启用状态
                _lineChart.invalidate();
            }
        });

        cb_fill.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                Lines lines = _lineChart.getlines();
                if (lines != null && lines.getLines().size() > 0) {
                    Line line = lines.getLines().get(0);
                    line.setFilled(isChecked);
                    _lineChart.invalidate();
                }
            }
        });
    }


    private void setChartData(LineChart lineChart) {

        lineChart.get_MappingManager().setCurrent2Fat(true);
        lineChart.get_MappingManager().setFatFactor(1.1f);//设置 可见视图与原始数据视图的比例
//        lineChart.setCanY_zoom(false);//设置只能y方向是否能缩放！

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y:" + value;
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
        xAxis.setCalWay(Axis.CalWay.every); // 轴线上label的计算方式
        xAxis.set_unit("单位：s");
        xAxis.set_ValueAdapter(new DefaultValueAdapter(1));

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("单位：m");
        yAxis.setCalWay(Axis.CalWay.every);
//        yAxis.set_enableUnit(false);
        yAxis.set_ValueAdapter(new DefaultValueAdapter(2));// 默认精度到小数点后2位,现在修改为3位精度

        // 数据
        Line line = new Line();
        line.setLineColor(Color.RED);
        List<Entry> list = new ArrayList<>();
//        list.add(new Entry(1, 5));
//        list.add(new Entry(2, 4));
//        list.add(new Entry(3, 2));
//        list.add(new Entry(4, 3));
//        list.add(new Entry(10, 8));

        list.add(new Entry(0, 0));
        list.add(new Entry(4, 0));
        list.add(new Entry(4, 1));
        list.add(new Entry(8, 1));
        list.add(new Entry(8, 2));
        list.add(new Entry(12, 2));
        list.add(new Entry(12, 3));
        list.add(new Entry(16, 3));
        list.add(new Entry(16, 2));
        list.add(new Entry(20, 2));
        list.add(new Entry(20, 1));
        list.add(new Entry(24, 1));

        line.setEntries(list);

        Lines lines = new Lines();
        lines.addLine(line);

        lineChart.setLines(lines);

        //        lineChart.setMaxMin(2,20,1,10);//手动设置，x和y方向上的数据范围
    }


    private List<Entry> generateLineData(int dataCount) {

        List<Entry> list = new ArrayList<>();

        Random random = new Random();
        for (int i = 0; i < dataCount; i++) {
            double x = i;
            double y = random.nextDouble() * 100;
            list.add(new Entry(x, y));
        }

        return list;
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/plus/LineChartAdvanced.java<|end_filename|>
package com.linheimx.app.plus;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.Spinner;

import com.linheimx.app.lchart.R;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Lines;

import java.util.ArrayList;
import java.util.List;

/**
 * 包装一下 lineChart
 * <p>
 * Created by LJIAN on 2017/1/9.
 */

public class LineChartAdvanced extends FrameLayout {

    LineChart _lineChart;

    public LineChartAdvanced(Context context) {
        super(context);
        init(context);
    }

    public LineChartAdvanced(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public LineChartAdvanced(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }


    private void init(Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.linechart_advanced, null);
        addView(view);

        _lineChart = (LineChart) view.findViewById(R.id.linechart);

        final List<String> curList = new ArrayList<>();
        curList.add("光标1");
        curList.add("光标2");

        Spinner spinner = (Spinner) view.findViewById(R.id.sp_cursor);
        spinner.setAdapter(new ArrayAdapter<String>(this.getContext(), android.R.layout.simple_list_item_1, curList));
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String s = curList.get(position);
                if (s.equals("光标1")) {
                    _lineChart.set_CursorMode(LineChart.CursorMode.cursor1);
                } else if (s.equals("光标2")) {
                    _lineChart.set_CursorMode(LineChart.CursorMode.cursor2);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });


        ImageButton btnLeft = (ImageButton) view.findViewById(R.id.btnLeft);
        ImageButton btnRight = (ImageButton) view.findViewById(R.id.btnRight);

        btnLeft.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                btnLeft();
            }
        });
        btnRight.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                btnRight();
            }
        });
    }

    public void setLines(Lines lines) {
        _lineChart.setLines(lines);
    }

    public LineChart get_lineChart() {
        return _lineChart;
    }

    public void set_lineChart(LineChart _lineChart) {
        this._lineChart = _lineChart;
    }

    public void btnLeft() {
        _lineChart.highLightLeft();
    }

    public void btnRight() {
        _lineChart.highLightRight();
    }

}


<|start_filename|>library/src/main/java/com/linheimx/app/library/model/Axis.java<|end_filename|>
package com.linheimx.app.library.model;

import android.graphics.Color;

import com.linheimx.app.library.adapter.DefaultValueAdapter;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.utils.Utils;

import java.util.List;

/**
 * 轴线相关
 * -----------------------
 * 区域事先约定，优于计算！
 * <p>
 * Created by lijian on 2016/12/5.
 */

public abstract class Axis {

    public static final float D_AXIS_WIDTH = 2;// d 代表default
    public static final float D_LEG_WIDTH = 5;
    public static final float D_LABEL_TXT = 7;
    public static final float D_UNIT_TXT = 12;

    public static final int D_LABEL_COUNT = 6;// 建议label的数量


    //////////////////////////  label 相关  /////////////////////////
    double[] labelValues = new double[]{};
    int labelCount = 6;
    int _labelCountAdvice = D_LABEL_COUNT;
    float labelDimen;
    int labelColor = Color.BLUE;
    float labelTextSize;
    CalWay calWay = CalWay.perfect;

    ///////////////////////////////  unit 相关  ////////////////////////////
    boolean _enableUnit = true;
    String _unit = "";
    float unitDimen;
    float unitTxtSize;
    int unitColor = Color.RED;

    /////////////////////////////////  轴线相关  //////////////////////////////////
    int axisColor = Color.BLACK;
    float axisWidth;
    float leg;// 轴线上的小腿（多出来的小不点：叫他小腿吧)

    /////////////////////////////////  预警线相关  ////////////////////////////////
    List<WarnLine> listWarnLins;


    boolean enable = true;// axis is enable?
    IValueAdapter _ValueAdapter;

    public Axis() {

        axisWidth = Utils.dp2px(D_AXIS_WIDTH);
        labelTextSize = Utils.dp2px(D_LABEL_TXT);
        leg = Utils.dp2px(D_LEG_WIDTH);
        unitTxtSize = Utils.dp2px(D_UNIT_TXT);

        // value adapter
        _ValueAdapter = new DefaultValueAdapter(2);
    }

    /**
     * 计算与存储：可见区域内的每一步的数值
     * -----------------------------
     * 注意：可见区域！
     */
    public void calValues(double min, double max, Line line, double x_min, double x_max) {

        double range;
        range = max - min;

        if (Math.abs(max - min) == 0) {
            return;
        }

        if (calWay == CalWay.perfect) {
            // 漂亮：展现的更合理

            double rawInterval = range / (_labelCountAdvice - 1);
            // 1.以最大数值为量程
            double interval = Utils.roundNumber2One(rawInterval);//314->300
            // 2. 量程>5，则以10为单位
            double intervalMagnitude = Math.pow(10, (int) Math.log10(interval));//100
            int intervalSigDigit = (int) (interval / intervalMagnitude);
            if (intervalSigDigit > 5) {
                interval = Math.floor(10 * intervalMagnitude);// 以10位单位 //
            }

            double first = Math.floor(min / interval) * interval;//有几个interval
            double last = Math.ceil(max / interval) * interval;

            double f;
            int n = 0;
            if (interval != 0.0) {
                for (f = first; f <= last; f += interval) {
                    ++n;
                }
            }
            labelCount = n;

            if (labelValues.length < labelCount) {
                labelValues = new double[labelCount];
            }

            f = first;
            for (int i = 0; i < n; f += interval, ++i) {

                if (f == 0.0) // Fix for negative zero case (Where value == -0.0, and 0.0 == -0.0)
                    f = 0.0;

                labelValues[i] = (float) f;
            }

//            //--------------------------> 修复第一个和最后一个不显示问题 <----------------------
//            // 第一个
//            if (first < min) {
//                labelValues[0] = min;
//            }
//            // 第二个
//            if (n > 1 && labelValues[n - 1] > max) {
//                labelValues[n - 1] = max;
//            }

        } else if (calWay == CalWay.justAvg) {
            // 平均：达到共产主义
            labelCount = _labelCountAdvice;

            if (labelValues.length < labelCount) {
                labelValues = new double[labelCount];
            }

            double v = min;
            double interval = range / (labelCount - 1);

            labelValues[0] = min;
            for (int i = 1; i < labelCount - 1; i++) {
                v = v + interval;
                labelValues[i] = v;
            }
            labelValues[labelCount - 1] = max;
        } else if (calWay == CalWay.every) {
            // 每个：将可视范围内，这条线上的每个数据在x轴上的label都绘制出来

            if (this instanceof XAxis) {
                if (line != null && line.getEntries().size() != 0) {
                    int minIndex = Line.getEntryIndex(line.getEntries(), min, Line.Rounding.DOWN);
                    int maxIndex = Line.getEntryIndex(line.getEntries(), max, Line.Rounding.UP);

                    labelCount = (maxIndex - minIndex) + 1;
                    if (labelValues.length < labelCount) {
                        labelValues = new double[labelCount];
                    }

                    int count = 0;
                    for (int i = minIndex; i <= maxIndex; i++) {
                        labelValues[count++] = line.getEntries().get(i).getX();
                    }
                }
            } else {
                if (line != null && line.getEntries().size() != 0) {
                    int minIndex = Line.getEntryIndex(line.getEntries(), x_min, Line.Rounding.DOWN);
                    int maxIndex = Line.getEntryIndex(line.getEntries(), x_max, Line.Rounding.UP);

                    labelCount = (maxIndex - minIndex) + 1;
                    if (labelValues.length < labelCount) {
                        labelValues = new double[labelCount];
                    }

                    int count = 0;
                    for (int i = minIndex; i <= maxIndex; i++) {
                        double y = line.getEntries().get(i).getY();

                        boolean exist = false;
                        for (int j = 0; j < labelValues.length; j++) {
                            if (labelValues[j] == y) {
                                exist = true;
                                break;
                            }
                        }

                        if (!exist)
                            labelValues[count++] = y;
                    }
                }
            }
        }
    }

    /**
     * 轴线左边 label和indicator的距离
     *
     * @return
     */
    public float offsetLeft(float labelWidth, float unitHeight) {
        labelDimen = labelWidth;
        unitDimen = unitHeight;

        float sum = labelDimen;
        if (_enableUnit) {
            sum += unitDimen;
        }
        sum += leg;
        return sum;
    }

    /**
     * 轴线底部 label和indicator的距离
     *
     * @return
     */
    public float offsetBottom(float labelHeight, float unitHeight) {
        labelDimen = labelHeight;
        unitDimen = unitHeight;

        float sum;
        sum = labelDimen;
        if (_enableUnit) {
            sum += unitDimen;
        }
        sum += leg;
        return sum;
    }


    public float getLabelDimen() {
        return labelDimen;
    }

    public void setLabelDimen(float labelDimen) {
        this.labelDimen = labelDimen;
    }

    public float getUnitDimen() {
        return unitDimen;
    }

    public void setUnitDimen(float unitDimen) {
        this.unitDimen = unitDimen;
    }


    ///////////////////////////////  get set  //////////////////////////////////////


    public IValueAdapter get_ValueAdapter() {
        return _ValueAdapter;
    }

    public void set_ValueAdapter(IValueAdapter _ValueAdapter) {
        this._ValueAdapter = _ValueAdapter;
    }

    public boolean is_enableUnit() {
        return _enableUnit;
    }

    public void set_enableUnit(boolean _enableUnit) {
        this._enableUnit = _enableUnit;
    }

    public int get_labelCountAdvice() {
        return _labelCountAdvice;
    }

    public void set_labelCountAdvice(int _labelCountAdvice) {
        this._labelCountAdvice = _labelCountAdvice;
    }

    public String get_unit() {
        return _unit;
    }

    public void set_unit(String _unit) {
        this._unit = _unit;
    }

    public float getUnitTxtSize() {
        return unitTxtSize;
    }

    public void setUnitTxtSize(float unitTxtSize) {
        this.unitTxtSize = unitTxtSize;
    }

    public int getUnitColor() {
        return unitColor;
    }

    public void setUnitColor(int unitColor) {
        this.unitColor = unitColor;
    }

    public int getAxisColor() {
        return axisColor;
    }

    public void setAxisColor(int axisColor) {
        this.axisColor = axisColor;
    }

    public float getAxisWidth() {
        return axisWidth;
    }

    public void setAxisWidth(float axisWidth) {
        this.axisWidth = axisWidth;
    }

    public boolean isEnable() {
        return enable;
    }

    public void setEnable(boolean enable) {
        this.enable = enable;
    }

    public float getLeg() {
        return leg;
    }

    public void setLeg(float leg) {
        this.leg = leg;
    }

    public float getLabelTextSize() {
        return labelTextSize;
    }

    public void setLabelTextSize(float labelTextSize) {
        this.labelTextSize = labelTextSize;
    }

    public int getLabelColor() {
        return labelColor;
    }

    public void setLabelColor(int labelColor) {
        this.labelColor = labelColor;
    }

    public int getLabelCount() {
        return labelCount;
    }

    public void setLabelCount(int labelCount) {
        this.labelCount = labelCount;
    }

    public double[] getLabelValues() {
        return labelValues;
    }

    public void setLabelValues(double[] labelValues) {
        this.labelValues = labelValues;
    }

    public List<WarnLine> getListWarnLins() {
        return listWarnLins;
    }

    public void setListWarnLins(List<WarnLine> listWarnLins) {
        this.listWarnLins = listWarnLins;
    }

    public CalWay getCalWay() {
        return calWay;
    }

    /**
     * 轴线上一堆label的计算方式
     *
     * @param calWay
     */
    public void setCalWay(CalWay calWay) {
        this.calWay = calWay;
    }

    /**
     * 轴线上的一堆数据的计算方式
     */
    public enum CalWay {
        /**
         * 漂亮：展现的更合理
         */
        perfect,
        /**
         * 平均：达到共产主义
         */
        justAvg,
        /**
         * 每个：将可视范围内，这条线上的每个数据在x轴上的label都绘制出来
         */
        every
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/PreviewActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import com.linheimx.app.chart_dialog.ChartPreviewDialog;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;

import java.util.ArrayList;
import java.util.List;

public class PreviewActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_god);

        getSupportActionBar().setTitle("折线图：预览模式");

        final LineChart lineChart = (LineChart) findViewById(R.id.chart1);
        final LineChart godLineChart = (LineChart) findViewById(R.id.chart2);

//        lineChart2.set_ChartMode(LineChart.ChartMode.God);//切换成上帝视角  xml已经写了
        godLineChart.registObserver(lineChart);

        setChartData(lineChart);

        // 通知 lineChart2 数据改变了（因为lineChart1改变了）
        godLineChart.notifyDataChanged_FromOb(lineChart);
    }

    private void setChartData(LineChart lineChart) {

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y:" + value;
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
        xAxis.set_unit("s");

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("m");

        Line line = new Line();
        line.setDrawCircle(false);
        List<Entry> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            list.add(new Entry(i, (float) Math.random()));
        }
        line.setEntries(list);

        List<Line> list2 = new ArrayList<>();
        list2.add(line);
        Lines lines = new Lines(list2);

        lineChart.setLines(lines);
    }

    public void btnShowChart(View view) {
        ChartPreviewDialog dialog = ChartPreviewDialog.newInstance("预览模式");
        dialog.setStyle(DialogFragment.STYLE_NORMAL, 0);
        dialog.setCancelable(true);
        dialog.show(getSupportFragmentManager(), null);
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/MainActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void btn1(View v) {
        startActivity(new Intent(MainActivity.this, LineChartActivity.class));
    }

    public void btn2(View v) {
        startActivity(new Intent(MainActivity.this, MultiLineActivity.class));
    }

    public void btn4(View v) {
        startActivity(new Intent(MainActivity.this, PreviewActivity.class));
    }

    public void btn5(View v) {
        startActivity(new Intent(MainActivity.this, WarnLinesActivity.class));
    }

    public void btn6(View v) {
        startActivity(new Intent(MainActivity.this, RealTimeActivity.class));
    }

    public void btn7(View v) {
        startActivity(new Intent(MainActivity.this, TouchProcessActivity.class));
    }

    public void btn8(View v) {
        startActivity(new Intent(MainActivity.this, ScrollLoadActivity.class));
    }

    public void btn9(View v) {
        startActivity(new Intent(MainActivity.this, AnimateActivity.class));
    }

    public void btn10(View v) {
        startActivity(new Intent(MainActivity.this, NullEntityActivity.class));
    }

    public void btn11(View v) {
        startActivity(new Intent(MainActivity.this, AdvancedActivity.class));
    }
}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/TouchProcessActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import com.linheimx.app.lchart.fragment.LineChartFragment;
import com.linheimx.app.lchart.fragment.ScrollView_Fragment;
import com.linheimx.app.lchart.fragment.ViewPager_Fragment;

import java.util.ArrayList;
import java.util.List;

public class TouchProcessActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_touch_process);

        getSupportActionBar().setTitle("滑动冲突的处理");


    }


    public void btn_vp(View view) {

        FragmentManager fm = getSupportFragmentManager();
        fm.beginTransaction()
                .replace(R.id.content, new ViewPager_Fragment())
                .commit();
    }

    public void btn_sv(View view) {

        FragmentManager fm = getSupportFragmentManager();
        fm.beginTransaction()
                .replace(R.id.content, new ScrollView_Fragment())
                .commit();
    }

}


<|start_filename|>app/src/main/java/com/linheimx/app/lchart/NullEntityActivity.java<|end_filename|>
package com.linheimx.app.lchart;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.linheimx.app.library.adapter.DefaultValueAdapter;
import com.linheimx.app.library.adapter.IValueAdapter;
import com.linheimx.app.library.charts.LineChart;
import com.linheimx.app.library.data.Entry;
import com.linheimx.app.library.data.Line;
import com.linheimx.app.library.data.Lines;
import com.linheimx.app.library.model.HighLight;
import com.linheimx.app.library.model.XAxis;
import com.linheimx.app.library.model.YAxis;

import java.util.ArrayList;
import java.util.List;

public class NullEntityActivity extends AppCompatActivity {

    LineChart _lineChart;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_null_entity);

        _lineChart = (LineChart) findViewById(R.id.chart);

        setChartData(_lineChart);
    }


    private void setChartData(LineChart lineChart) {

//        lineChart.get_MappingManager().setFatFactor(1f);//设置 可见视图与原始数据视图的比例
//        lineChart.setCanY_zoom(false);//设置只能y方向是否能缩放！

        // 高亮
        HighLight highLight = lineChart.get_HighLight1();
        highLight.setEnable(true);// 启用高亮显示  默认为启用状态
        highLight.setxValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "X:" + value;
            }
        });
        highLight.setyValueAdapter(new IValueAdapter() {
            @Override
            public String value2String(double value) {
                return "Y:" + value;
            }
        });

        // x,y轴上的单位
        XAxis xAxis = lineChart.get_XAxis();
//        xAxis.setCalWay(Axis.CalWay.every); // 轴线上label的计算方式
        xAxis.set_unit("单位：s");
        xAxis.set_ValueAdapter(new DefaultValueAdapter(1));

        YAxis yAxis = lineChart.get_YAxis();
        yAxis.set_unit("单位：m");
//        yAxis.set_enableUnit(false);
        yAxis.set_ValueAdapter(new DefaultValueAdapter(2));// 默认精度到小数点后2位,现在修改为3位精度

        // 数据
        Line line = new Line();
        line.setLineColor(Color.BLUE);
        List<Entry> list = new ArrayList<>();
        list.add(new Entry(1, 5));
        list.add(new Entry(2, 4));
        list.add(new Entry(3, 2).setNull_Y()); // 这个点是断点
        list.add(new Entry(4, 3));
        list.add(new Entry(10, 8));
        line.setEntries(list);

        Lines lines = new Lines();
        lines.addLine(line);

        lineChart.setLines(lines);
//        lineChart.setMaxMin(2,20,1,10);//手动设置，x和y方向上的数据范围
    }

}
