Effect:

You can swipe left or right and click on the display box.

In the code

public class LineChartView extends View {
    private static final String TAG = "LineChartView";
    /*动画插值器*/
    DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator();
    //Y轴  每个刻度的间距间距
    private int myInterval;
    //X轴  每个刻度的间距间距
    private int mxInterval;
    //Y轴距离view长度
    private int mLeftInterval;
    //X轴距离view长度
    private int mBottomInterval;
    //X轴距离view顶部长度
    private int mTopInterval;
    //Y轴字体的大小
    private float mYAxisFontSize;
    //View 的宽和高
    private int mWidth, mHeight;
    //线的颜色
    private int mLineColor;
    private int mLineColor2;
    //线条的宽度
    private float mStrokeWidth = 4.0f;
    //X轴的文字
    private ArrayList<String> mXAxis;
    //Y轴的文字
    private ArrayList<String> mYAxis;
    //点 (温度)
    private ArrayList<Integer> mYLine;
    private ArrayList<Integer> mYLine2;

    //纵轴最大值
    private int maxYValue;
    //纵轴分割数量
    private int dividerCount;
    //画坐标线的轴
    private Paint axisPaint;

    //画X轴文字
    private Paint axisTextPaint;
    //连接线条
    private Paint linePaint;
    //小圆点内环
    private Paint innerCirclePaint;
    private Paint innerCirclePaint2;
    //小圆点中间环
    private Paint middleCiclePaint;
    //小圆点外环
    private Paint outterCiclePaint;
    private Paint outterCiclePaint2;
    //折线路径
    private Path mpolylinePath;
    //小圆点内环半径
    private int innerCircleRadius;
    //小圆点中间环半径
    private int middleRadius;
    //小圆点外环半径
    private int outerRadius;
    /*动画刷新的次数*/
    private int mDuration = 10;
    /*当前动画进度值*/
    private int mCurrentTime = 0;
    /*Handler刷新界面产生动画效果*/
    private Handler mHandler = new Handler();

    private Runnable mAnimation = new Runnable() {
        @Override
        public void run() {
            if (mCurrentTime < mDuration) {
                mCurrentTime++;
                LineChartView.this.invalidate();
            }
        }
    };
    private float xInit;
    private boolean isDraw = false;
    private float minXInit;
    private float maxXInit;

    public LineChartView(Context context) {
        this(context, null);
    }

    public LineChartView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LineChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }


    public LineChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initAttr(context, attrs, defStyleAttr);
        init(context);
    }

    @SuppressLint("NonConstantResourceId")
    private void initAttr(Context context, AttributeSet attrs, int defStyleAttr) {
        /**
         * 获得我们所定义的自定义样式属性
         */
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.LineChartView, defStyleAttr, 0);
        int n = a.getIndexCount();
        float tap = 16;
        for (int i = 0; i < n; i++) {
            int index = a.getIndex(i);
            switch (index) {
                // 折线颜色
                case R.styleable.LineChartView_lineColor:
                    mLineColor = a.getColor(index, Color.BLACK);
                    break;
                case R.styleable.LineChartView_lineColor2:
                    mLineColor2 = a.getColor(index, Color.BLACK);
                    break;
                // X轴每个刻度的间距间距
                case R.styleable.LineChartView_dividerCount:
                    dividerCount = a.getInt(index, 1) + 1;
                    break;
                // X轴每个刻度的间距间距
                case R.styleable.LineChartView_xInterval:
                    mxInterval = a.getDimensionPixelSize(index, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, tap, getResources().getDisplayMetrics()));
                    break;
                // Y轴距离view长度
                case R.styleable.LineChartView_leftInterval:
                    mLeftInterval = a.getDimensionPixelSize(index, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, tap, getResources().getDisplayMetrics()));
                    break;
                // X轴距离view底部的高度
                case R.styleable.LineChartView_bottomInterval:
                    mBottomInterval = a.getDimensionPixelSize(index, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, tap, getResources().getDisplayMetrics()));
                    break;
                // X轴距离view顶部长度
                case R.styleable.LineChartView_topInterval:
                    mTopInterval = a.getDimensionPixelSize(index, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, tap, getResources().getDisplayMetrics()));
                    break;
                // Y轴字体的大小
                case R.styleable.LineChartView_yAxisFontSize:
                    // 默认设置为16sp,TypeValue也可以把sp转化为px
                    mYAxisFontSize = a.getDimensionPixelSize(index, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, tap, getResources().getDisplayMetrics()));
                    break;
            }

        }
        a.recycle();
    }

    private void init(Context context) {
        // 画坐标线的轴
        axisPaint = new Paint();
        axisPaint.setTextSize(mYAxisFontSize);
        axisPaint.setColor(Color.WHITE);

        // 画X轴文字
        axisTextPaint = new Paint();
        axisTextPaint.setTextSize(mYAxisFontSize);
        axisTextPaint.setColor(Color.WHITE);

        // 连接线条
        linePaint = new Paint();
        linePaint.setColor(mLineColor);
        linePaint.setAntiAlias(true);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeWidth(mStrokeWidth);

        // 小圆点内环
        innerCirclePaint = new Paint();
        innerCirclePaint.setStyle(Paint.Style.FILL);
        innerCirclePaint.setAntiAlias(true);
        innerCirclePaint.setColor(mLineColor);
        innerCirclePaint.setStrokeWidth(dip2px(2));
        // 小圆点2内环
        innerCirclePaint2 = new Paint();
        innerCirclePaint2.setStyle(Paint.Style.FILL);
        innerCirclePaint2.setAntiAlias(true);
        innerCirclePaint2.setColor(mLineColor2);
        innerCirclePaint2.setStrokeWidth(dip2px(2));
        // 小圆点中间环
        middleCiclePaint = new Paint();
        middleCiclePaint.setStyle(Paint.Style.STROKE);
        middleCiclePaint.setAntiAlias(true);
        middleCiclePaint.setColor(Color.TRANSPARENT);
        middleCiclePaint.setStrokeWidth(dip2px(2));

        // 小圆点外环
        outterCiclePaint = new Paint();
        outterCiclePaint.setStyle(Paint.Style.STROKE);
        outterCiclePaint.setAntiAlias(true);
        outterCiclePaint.setColor(mLineColor);
        outterCiclePaint.setStrokeWidth(dip2px(1));
        // 小圆点2外环
        outterCiclePaint2 = new Paint();
        outterCiclePaint2.setStyle(Paint.Style.STROKE);
        outterCiclePaint2.setAntiAlias(true);
        outterCiclePaint2.setColor(mLineColor2);
        outterCiclePaint2.setStrokeWidth(dip2px(1));

        // 折线路径
        mpolylinePath = new Path();

        //小圆点内环半径
        innerCircleRadius = dip2px(3);
        //小圆点中间环半径
        middleRadius = dip2px(4);
        //小圆点外环半径
        outerRadius = dip2px(6);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        if (changed) {
            myInterval = (getHeight() - mBottomInterval - mTopInterval) / dividerCount;//Y轴刻度间距
            xInit = mLeftInterval;
            minXInit = - mxInterval * (mXAxis.size() - getScreenWidth(getContext())/mxInterval - 1);            maxXInit = mLeftInterval;
        }
        super.onLayout(changed, left, top, right, bottom);
    }

    public int getScreenWidth(Context context){
        WindowManager ma = (WindowManager) context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        Display display = ma.getDefaultDisplay();
        return display.getWidth();

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        Log.d(TAG, "widthSize:" + widthSize + ",heightSize:" + heightSize);
        mHeight = heightSize;
        if (mXAxis == null) {
            Log.d(TAG, "mWidth:" + mWidth + ",mHeight:" + mHeight + "mXAxis:" + mXAxis);
            return;
        }
        //总宽度通过数组长度计算
        mWidth = mxInterval * (mXAxis.size() - 1) + mLeftInterval * 2;
        setMeasuredDimension(mWidth, mHeight);
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        if (isDraw) {
            if (mXAxis.size() == 0 || mYLine.size() == 0 || mYLine2.size() == 0) {
                Log.e(TAG, "数据异常");
                return;
            }
            int layerId = canvas.saveLayer(0, 0, mWidth, mHeight, null, Canvas.ALL_SAVE_FLAG);
            /*计算当前动画进度对应的数值*/
            float animCurrentValue = mDecelerateInterpolator.getInterpolation(1.0f * mCurrentTime / mDuration);
            drawXLine(canvas);
            drawBrokenLine(canvas, animCurrentValue);
            drawBrokenPoint(canvas, animCurrentValue);
            drawBrokenPoint2(canvas, animCurrentValue);
            drawFloatBox(canvas);
            drawYLine(canvas);
            // 将左侧折线超出x轴坐标的部分截取掉
            linePaint.setStyle(Paint.Style.FILL);
            linePaint.setColor(Color.TRANSPARENT);
            linePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            RectF rectF = new RectF(0, 0, mLeftInterval - dip2px(1), mHeight);
            canvas.drawRect(rectF, linePaint);
            linePaint.setXfermode(null);
            drawYText(canvas);
            mHandler.postDelayed(mAnimation, 50);
            canvas.restoreToCount(layerId);
        }
    }

    private void drawYText(Canvas canvas){
        //绘制Y轴文本
        for (int i = 0; i <= dividerCount; i++) {
            if (i <= dividerCount - 1) {
                int y1 = mHeight - mBottomInterval - i * myInterval;
                String text = mYAxis.get(i);
                Rect rect = getTextBounds(text, axisPaint);
                canvas.drawText(text,  mLeftInterval *0.5f- rect.width()*0.5f, y1 + rect.height() / 2, axisPaint);
            }
        }
    }

    private void drawXLine(Canvas canvas){
        // 画横线
        for (int i = 0; i <= dividerCount; i++) {
            if (i <= dividerCount - 1) {
                if (i != 0) {
                    axisPaint.setPathEffect(new DashPathEffect(new float[]{dip2px(4), dip2px(4)}, dip2px(4)));
                    axisPaint.setStrokeWidth(dip2px(1));
                } else {
                    axisPaint.setPathEffect(new PathEffect());
                    axisPaint.setStrokeWidth(dip2px(2));
                }
                float endX = (mXAxis.size() - 1) * mxInterval + xInit;
                int y2 = mHeight - mBottomInterval - i * myInterval;
                canvas.drawLine(xInit, y2, endX, y2, axisPaint);
            }
        }
    }

    private void drawYLine(Canvas canvas){
        // x轴的刻度集合
        int[] xPoints = new int[mXAxis.size()];
        axisPaint.setPathEffect(new PathEffect());
        // 画竖线
        for (int i = 0; i < mXAxis.size(); i++) {
            float xTextWidth = axisPaint.measureText(mXAxis.get(i)) / 2; //文字宽度一半
            float xfloat = i * mxInterval + xInit - xTextWidth;
            // 画X轴的文字
            canvas.drawText(mXAxis.get(i), xfloat, mHeight - mBottomInterval + mYAxisFontSize, axisTextPaint);
            xPoints[i] = (int) (xfloat + xTextWidth);
            // 画竖线
            if (i == 0) {
                float xvfloat = i * mxInterval + mLeftInterval;
                axisPaint.setStrokeWidth(dip2px(2));
                canvas.drawLine(xvfloat, mHeight - mBottomInterval, xvfloat,
                        mHeight - mBottomInterval - myInterval * dividerCount, axisPaint);
            } else {
                float xvfloat = i * mxInterval + xInit;
                axisPaint.setStrokeWidth(dip2px(1));
                canvas.drawLine(xvfloat, mHeight - mBottomInterval, xvfloat,
                        (float) (mHeight - mBottomInterval - myInterval * 0.2), axisPaint);
            }
        }

    }

    private void drawBrokenLine(Canvas canvas, float animCurrentValue){
        /**
         * 画折线1轨迹
         */
        int y_line = myInterval * (dividerCount - 1); // 只拿纵轴的dividerCount-1/dividerCount画图
        linePaint.setColor(mLineColor);
        linePaint.setStyle(Paint.Style.STROKE);
//        axisPaint.setColor(mLineColor); // 设置坐标值的颜色
        for (int i = 0; i < mYLine.size(); i++) {
            float h = mHeight - (mBottomInterval + y_line * mYLine.get(i) / maxYValue) * animCurrentValue;
//            float textWidth = axisPaint.measureText(String.valueOf(mYAxis.get(i))) / 2; //文字宽度一半
            if (i == 0) {
                mpolylinePath.moveTo(xInit, h);
//                canvas.drawText(mYAxis.get(i) + "", mLeftInterval - textWidth, h - mYAxisFontSize, axisPaint);
            } else {
                mpolylinePath.lineTo(xInit + i * mxInterval * animCurrentValue, h);
//                canvas.drawText(mYAxis.get(i) + "", mLeftInterval + i * mxInterval - textWidth, h - mYAxisFontSize, axisPaint);
            }
        }
        canvas.drawPath(mpolylinePath, linePaint);
        mpolylinePath.reset();
        linePaint.setColor(mLineColor2);
        /**
         * 画折线2轨迹
         */
        for (int i = 0; i < mYLine2.size(); i++) {
            float h = mHeight - (mBottomInterval + y_line * mYLine2.get(i) / maxYValue) * animCurrentValue;
//            float textWidth = axisPaint.measureText(String.valueOf(mYAxis2.get(i))) / 2; //文字宽度一半
            if (i == 0) {
                mpolylinePath.moveTo(xInit, h);
//                canvas.drawText(mYAxis2.get(i) + "", mLeftInterval - textWidth, h - mYAxisFontSize, axisPaint);
            } else {
                mpolylinePath.lineTo(xInit + i * mxInterval * animCurrentValue, h);
//                canvas.drawText(mYAxis2.get(i) + "", mLeftInterval + i * mxInterval - textWidth, h - mYAxisFontSize, axisPaint);
            }
        }
        canvas.drawPath(mpolylinePath, linePaint);
        mpolylinePath.reset();
    }

    /**
     * 画小圆圈1
     */
    private void drawBrokenPoint(Canvas canvas,float animCurrentValue){
        int y_line = myInterval * (dividerCount - 1);
        for (int i = 1; i < mYLine.size(); i++) {
            float y = mHeight - (mBottomInterval + y_line * mYLine.get(i) / maxYValue) * animCurrentValue;
            float x = xInit + i * mxInterval * animCurrentValue;
            if (i == selectIndex - 1) {
                outterCiclePaint.setColor(mLineColor);
            }else {
                outterCiclePaint.setColor(Color.TRANSPARENT);
            }
            canvas.drawCircle(x, y, innerCircleRadius, innerCirclePaint);
            canvas.drawCircle(x, y, middleRadius, middleCiclePaint);
            canvas.drawCircle(x, y, outerRadius, outterCiclePaint);
        }
    }
    /**
     * 画小圆圈2
     */
    private void drawBrokenPoint2(Canvas canvas,float animCurrentValue){
        int y_line = myInterval * (dividerCount - 1);
        for (int i = 1; i < mYLine2.size(); i++) {
            float y = mHeight - (mBottomInterval + y_line * mYLine2.get(i) / maxYValue) * animCurrentValue;
            float x = xInit + i * mxInterval * animCurrentValue;
            if (i == selectIndex2 - 1) {
                outterCiclePaint2.setColor(mLineColor2);
//                drawFloatTextBox(canvas, x, y - dp7, mYLine2.get(i),mLineColor2);
            }else {
                outterCiclePaint2.setColor(Color.TRANSPARENT);
            }
            canvas.drawCircle(x, y, innerCircleRadius, innerCirclePaint2);
            canvas.drawCircle(x, y, middleRadius, middleCiclePaint);
            canvas.drawCircle(x, y, outerRadius, outterCiclePaint2);
        }
    }
    /**
     * 画点击节点弹出框
     */
    private void drawFloatBox(Canvas canvas){
        float dp7 = dip2px(7);
        int y_line = myInterval * (dividerCount - 1);
        if(selectIndex != -1){
            for (int i = 1; i < mYLine.size(); i++) {
                if (i == selectIndex - 1) {
                    float y = mHeight - (mBottomInterval + y_line * mYLine.get(i) / maxYValue);
                    float x = xInit + i * mxInterval;
                    drawFloatTextBox(canvas, x, y, mYLine.get(i), mLineColor);
                }
            }
        }
        if(selectIndex2 != -1){
            for (int i = 1; i < mYLine2.size(); i++) {
                if (i == selectIndex2 - 1) {
                    float y = mHeight - (mBottomInterval + y_line * mYLine2.get(i) / maxYValue);
                    float x = xInit + i * mxInterval;
                    drawFloatTextBox(canvas, x, y, mYLine2.get(i), mLineColor2);
                }
            }
        }
    }

    private int selectIndex = -1;//点击的点对应的X轴的第几个点,默认1
    private int selectIndex2 = -1;//点击的点对应的X轴的第几个点,默认1

    private void clickAction(MotionEvent event) {
        int dp8 = dip2px(8);
        float eventX = event.getX();
        float eventY = event.getY();
        int y_line = myInterval * (dividerCount - 1);
        for (int i = 0; i < mYLine.size(); i++) {
            //节点
            float x = xInit + mxInterval * i;
            float y = mHeight - (mBottomInterval + y_line * mYLine.get(i) / maxYValue);
            if (eventX >= x - dp8 && eventX <= x + dp8 && eventY >= y - dp8 && eventY <= y + dp8 && selectIndex != i+1) {//每个节点周围8dp都是可点击区域
                selectIndex = i+1;
                selectIndex2 = -1;
                invalidate();
                return;
            }
            float y2 = mHeight - (mBottomInterval + y_line * mYLine2.get(i) / maxYValue);
            if (eventX >= x - dp8 && eventX <= x + dp8 && eventY >= y2 - dp8 && eventY <= y2 + dp8 && selectIndex2 != i+1) {//每个节点周围8dp都是可点击区域
                selectIndex2 = i+1;
                selectIndex = -1;
                invalidate();
                return;
            }
        }
    }

    private void drawFloatTextBox(Canvas canvas, float x, float y, int text,int color) {
        int dp6 = dip2px(6);
        int dp7 = dip2px(7);
        int dp18 = dip2px(50);
        int dp14 = sp2px(14);
        Path path = new Path();
        if(y - dp6 - dp18 > 0){
            y -= dp7;
            path.moveTo(x, y);
            path.lineTo(x - dp6, y - dp6);
            path.lineTo(x - dp18, y - dp6);
            path.lineTo(x - dp18, y - dp6 - dp18);
            path.lineTo(x + dp18, y - dp6 - dp18);
            path.lineTo(x + dp18, y - dp6);
            path.lineTo(x + dp6, y - dp6);
            path.lineTo(x, y);
        }else {
            y += dp7;
            path.moveTo(x, y);
            path.lineTo(x + dp6, y + dp6);
            path.lineTo(x + dp18, y + dp6);
            path.lineTo(x + dp18, y + dp6 + dp18);
            path.lineTo(x - dp18, y + dp6 + dp18);
            path.lineTo(x - dp18, y + dp6);
            path.lineTo(x - dp6, y + dp6);
            path.lineTo(x, y);
        }

        linePaint.setStyle(Paint.Style.FILL);
        linePaint.setColor(Color.parseColor("#DDFFFF"));
        canvas.drawPath(path, linePaint);

        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setColor(color);
        canvas.drawPath(path, linePaint);

        linePaint.setColor(Color.BLACK);
        linePaint.setTextSize(dp14);

        Rect rect = getTextBounds(text + "", linePaint);
        if(y - dp6 - dp18 > 0){
            canvas.drawText(text + "", x - rect.width() / 2, y - dp6 - (dp18 - rect.height()) / 2, linePaint);
        }else {
            canvas.drawText(text + "", x - rect.width() / 2, y + dp6 + (dp18 + rect.height()) / 2, linePaint);
        }

    }

    private float startX;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        this.getParent().requestDisallowInterceptTouchEvent(true);//当该view获得点击事件,就请求父控件不拦截事件
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                break;
            case MotionEvent.ACTION_MOVE:
                if (mxInterval * mXAxis.size() > mWidth - mLeftInterval) {//当期的宽度不足以呈现全部数据
                    float dis = event.getX() - startX;
                    startX = event.getX();
                    //以Y轴所在的maxXInit为最大值位置
                    if (xInit + dis < minXInit) {
                        //minXInit 为可滑到最左端的负值。
                        xInit = minXInit;
                    } else if (xInit + dis > maxXInit) {
                        xInit = maxXInit;
                    } else {
                        xInit = xInit + dis;
                    }
                    invalidate();
                }
                break;
            case MotionEvent.ACTION_UP:
                clickAction(event);
                this.getParent().requestDisallowInterceptTouchEvent(false);
                break;
            case MotionEvent.ACTION_CANCEL:
                this.getParent().requestDisallowInterceptTouchEvent(false);
                break;
        }
        return true;
    }


    /**
     * 获取丈量文本的矩形
     *
     * @param text
     * @param paint
     * @return
     */
    private Rect getTextBounds(String text, Paint paint) {
        Rect rect = new Rect();
        paint.getTextBounds(text, 0, text.length(), rect);
        return rect;
    }

    /**
     * 设置Y轴文字
     *
     * @param yItem
     */
    public LineChartView setLineItem(ArrayList<Integer> yItem, ArrayList<Integer> yItem2) {
        mYLine = yItem;
        mYLine2 = yItem2;
        return this;
    }

    public void startDraw(){
        isDraw = true;
        invalidate();
    }

    /**
     * 设置X轴文字
     *
     * @param xItem
     */
    public LineChartView setXYItem(ArrayList<String> xItem,ArrayList<String> xItem2) {
        mXAxis = xItem;
        mYAxis = xItem2;
        return this;
    }

    public LineChartView setMaxYValue(int maxYValue) {
        this.maxYValue = maxYValue;
        return this;
    }

    /**
     * dp转化成为px
     *
     * @param dp
     * @return
     */
    private int dip2px(int dp) {
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (dp * density + 0.5f * (dp >= 0 ? 1 : -1));
    }

    /**
     * sp转化为px
     *
     * @param sp
     * @return
     */
    private int sp2px(int sp) {
        float scaledDensity = getContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (scaledDensity * sp + 0.5f * (sp >= 0 ? 1 : -1));
    }
}
Copy the code

Attributes attrs. XML

<declare-styleable name="LineChartView"> <attr name="lineColor" format="color" /><! <attr name="lineColor2" format="color" /><! --> <attr name="dividerCount" format="integer" /><! <attr name="xInterval" format="dimension" /><! <attr name="leftInterval" format="dimension" /><! <attr name="bottomInterval" format="dimension" /><! --> <attr name="topInterval" format="dimension" /><! <attr name="yAxisFontSize" format="dimension" /><! --> </declare-styleable>Copy the code

Layout:

<LinearLayout
        android:orientation="vertical"
        android:layout_marginStart="15dp"
        android:layout_marginEnd="15dp"
        android:paddingEnd="5dp"
        android:paddingStart="0dp"
        android:layout_width="match_parent"
        android:background="@drawable/circle_gradient_stroke_10dp"
        android:layout_height="wrap_content">
            <com.***.view.LineChartView
                android:id="@+id/lineChart"
                android:layout_width="match_parent"
                android:layout_height="200dp"
                linchart:lineColor="@color/colorLine"
                linchart:lineColor2="@color/colorLine2"
                linchart:dividerCount="7"
                linchart:xInterval="50dp"
                linchart:leftInterval="40dp"
                linchart:bottomInterval="20dp"
                linchart:topInterval="20dp"
                linchart:yAxisFontSize="14sp"/>
</LinearLayout>
Copy the code

Color parameters:

<color name="colorLine2">#FEFD7B</color>
<color name="colorLine">#6BFEEB</color>
<color name="background_down">#66ADEB</color>
<color name="background_top">#84E5DD</color>
Copy the code

Background Shape: circle_gradient_stroke_10DP.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <gradient
        android:startColor="@color/background_top"
        android:endColor="@color/background_down"
        android:angle="270"
        />
    <corners android:radius="10dp" />
</shape>
Copy the code

Call:

private LineChartView mLineChartView; private void initView() { mLineChartView = (LineChartView) findViewById(R.id.lineChart); / / X String [] xItem = {" 1 ", "2", "3", "4", "5", "6", "7", "eight" and "9", "10", "11", "12", "13", 14 ", "15", "16" and "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30"}; ArrayList<String> xItemArray = new ArrayList<>(Arrays.asList(xItem)); / / y String [] ytItem = {" 0 ", "25 k", "50 k", "75 k", "100 k", "125 k", "150 k", "200 k"}; ArrayList<String> yItemArray = new ArrayList<>(Arrays.asList(ytItem)); int[] yItem = {3, 7, 19, 7, 20, 19, 29, 8, 18, 19, 21, 20, 19, 20, 8, 18, 19, 21, 20, 22, 21, 24, 26, 24, 20, 22, 21, 24, 26, 24}; int[] yItem2 = {9, 2, 9, 17, 2, 14, 24, 8, 19, 12, 24, 2, 4, 14, 8, 13, 9, 25, 11, 24, 15, 13, 28, 21, 1, 13, 25, 21, 22, 12}; ArrayList<Integer> yLineArray = new ArrayList<>(); ArrayList<Integer> yLineArray2 = new ArrayList<>(); for (int value : yItem) { yLineArray.add(value); } for (int value : yItem2) { yLineArray2.add(value); } int yMax = findMax(yItem); mLineChartView.setXYItem(xItemArray, yItemArray) .setLineItem(yLineArray, yLineArray2) .setMaxYValue(yMax) .startDraw();  Private int findMax(int[] array) {int Max = array[0]; private int findMax(int[] array) {int Max = array[0]; for (int i = 0; i < array.length; i++) { if (array[i] > max) max = array[i]; } return max; }Copy the code