カスタム折れ線グラフ、アリの富を模倣

9346 ワード

  //       ,      ,  mWidth、mBaseHeight。
    protected final float DEF_WIDTH = 650;
    protected final float DEF_HIGHT = 400;

    //       ,  onMeasure     。
    protected int mBaseWidth;
    protected int mBaseHeight;
    private Paint mInnerXPaint;
    private Paint mLoadingPaint;
    private Paint mXYPaint;
    private Paint mLinePaint;
    private Paint dotPaint;
    //    padding,    
    //x、y          
    protected float mXYTextSize = 25;
    //             
    protected float mLeftTxtPadding = 64;
    //            
    protected float mBottomTxtPadding = 40;

    protected float mBasePaddingTop = 200;
    protected float mBasePaddingBottom = 200;
    protected float mBasePaddingLeft = 150;
    protected float mBasePaddingRight = 50;
    private ArrayList mPoints;
    private float mPerX;
    private float mPerY;

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

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

    public ChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        if (widthSpecMode == AT_MOST && heightSpecMode == AT_MOST) {
            setMeasuredDimension((int) DEF_WIDTH, (int) DEF_HIGHT);
        } else if (widthSpecMode == AT_MOST) {
            setMeasuredDimension((int) DEF_WIDTH, heightSpecSize);
        } else if (heightSpecMode == AT_MOST) {
            setMeasuredDimension(widthSpecSize, (int) DEF_HIGHT);
        } else {
            setMeasuredDimension(widthSpecSize, heightSpecSize);
        }
        mBaseWidth = getMeasuredWidth();
        mBaseHeight = getMeasuredHeight();
    }

    /**
     *          
     */
    private void init() {
        //       
        mLoadingPaint = new Paint();
        mLoadingPaint.setColor(getContext().getResources().getColor(R.color.colorAccent));
        mLoadingPaint.setTextSize(14);
        mLoadingPaint.setAntiAlias(true);
        //   x  
        mInnerXPaint = new Paint();
        mInnerXPaint.setColor(Color.LTGRAY);
        mInnerXPaint.setStrokeWidth(1);
        mInnerXPaint.setStyle(Paint.Style.STROKE);
        mInnerXPaint.setAntiAlias(true);
        //x y    
        mXYPaint = new Paint();
        mXYPaint.setColor(Color.GRAY);
        mXYPaint.setTextSize(25);
        mXYPaint.setAntiAlias(true);
        //  
        mLinePaint = new Paint();
        mLinePaint.setColor(Color.RED);
        mLinePaint.setStyle(Paint.Style.STROKE);
        mLinePaint.setAntiAlias(true);
        mLinePaint.setTextSize(11);
        //     
        dotPaint = new Paint();
        dotPaint.setColor(Color.BLUE);
        dotPaint.setStrokeWidth(1);
        dotPaint.setAntiAlias(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //   X    
        drawInnerXPaint(canvas);
        //  xy   
        drawXYPaint(canvas);
        //     
        drawBrokenPaint(canvas);
        //       
        drawDot(canvas);
    }

    /**
     *        
     *
     * @param canvas
     */
    private void drawDot(Canvas canvas) {
        //                 60  
        float buyXDot = mBasePaddingLeft + (4 * mPerX);
        float buyYDot = (mBaseHeight - mBasePaddingTop) - (mPoints.get(4).y * mPerY);
        //        
        dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 1));
        canvas.drawLine(buyXDot, buyYDot, buyXDot, buyYDot - Utils.dip2px(getContext(), 20), dotPaint);  //    
        dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 4));
        canvas.drawCircle(buyXDot, buyYDot, Utils.dip2px(getContext(), 2), dotPaint); //    
        dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 0.5f));
        dotPaint.setStyle(Paint.Style.FILL);
        canvas.drawRect(buyXDot - Utils.dip2px(getContext(), 30), buyYDot - Utils.dip2px(getContext(), 26),
                buyXDot, buyYDot - Utils.dip2px(getContext(), 13), dotPaint);
        dotPaint.setTextSize(Utils.dip2px(getContext(), 11));
        dotPaint.setColor(Color.WHITE);
        canvas.drawText("  ", buyXDot - Utils.dip2px(getContext(), 30 / 2) - dotPaint.measureText("  ") / 2, buyYDot - Utils.dip2px(getContext(), 15), dotPaint);
        float saleXDot = mBasePaddingLeft + (20 * mPerX);
        float saleYDot = (mBaseHeight - mBasePaddingTop) - (mPoints.get(20).y * mPerY);
        //        
        dotPaint.setColor(Color.GREEN);
        dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 1));
        canvas.drawLine(saleXDot, saleYDot, saleXDot, saleYDot - Utils.dip2px(getContext(), 20), dotPaint);  //    
        dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 4));
        canvas.drawCircle(saleXDot, saleYDot, Utils.dip2px(getContext(), 2), dotPaint); //    
        dotPaint.setStrokeWidth(Utils.dip2px(getContext(), 0.5f));
        dotPaint.setStyle(Paint.Style.FILL);
        canvas.drawRect(saleXDot - Utils.dip2px(getContext(), 30), saleYDot - Utils.dip2px(getContext(), 26),
                saleXDot, saleYDot - Utils.dip2px(getContext(), 13), dotPaint);
        dotPaint.setTextSize(Utils.dip2px(getContext(), 11));
        dotPaint.setColor(Color.WHITE);
        canvas.drawText("  ", saleXDot - Utils.dip2px(getContext(), 30 / 2) - dotPaint.measureText("  ") / 2, saleYDot - Utils.dip2px(getContext(), 15), dotPaint);

    }
        private void drawInnerXPaint (Canvas canvas){
            // 5      
            //              
            float perHight = (mBaseHeight - mBasePaddingBottom - mBasePaddingTop) / 4;
            //     
            canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop,
                    mBaseWidth - mBasePaddingRight, mBasePaddingTop, mInnerXPaint);//       

            canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop + perHight * 1,
                    mBaseWidth - mBasePaddingRight, mBasePaddingTop + perHight * 1, mInnerXPaint);//2

            canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop + perHight * 2,
                    mBaseWidth - mBasePaddingRight, mBasePaddingTop + perHight * 2, mInnerXPaint);//3

            canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop + perHight * 3,
                    mBaseWidth - mBasePaddingRight, mBasePaddingTop + perHight * 3, mInnerXPaint);//4

            canvas.drawLine(0 + mBasePaddingLeft, mBaseHeight - mBasePaddingBottom,
                    mBaseWidth - mBasePaddingRight, mBaseHeight - mBasePaddingBottom, mInnerXPaint);//       

        }

        private void drawXYPaint (Canvas canvas){
            //   y     
            //     、     
            Paint.FontMetrics fontMetrics = mXYPaint.getFontMetrics();
            float height = fontMetrics.descent - fontMetrics.ascent;
            //draw min
            float txtWigth = Utils.dip2px(getContext(), 10) + mLeftTxtPadding;

            //        ,               ,    。
            float perYWidth = (mBaseHeight - mBasePaddingBottom - mBasePaddingTop) / 4;
            //       
            for (int i = 0; i < 5; i++) {
                canvas.drawText((20 * i) + "",
                        mBasePaddingLeft - txtWigth,
                        mBaseHeight - mBasePaddingBottom - perYWidth * i + height / 2, mXYPaint);
            }

            //  x     
            //x      
            float hight = mBaseHeight - mBasePaddingBottom + mBottomTxtPadding;

            //  X   
            float space = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight - mXYPaint.measureText("2020-02-02") * 2 - mXYPaint.measureText("2020-02-02") / 2) / 2;  //         
            canvas.drawText("2020-02-02", mBasePaddingLeft - mXYPaint.measureText("2020-02-02") / 2, hight, mXYPaint);
            canvas.drawText("2020-02-04", mBasePaddingLeft + space + mXYPaint.measureText("2020-02-02") / 2, hight, mXYPaint);
            canvas.drawText("2020-02-06", mBaseWidth - mBasePaddingRight - mXYPaint.measureText("2020-02-02"), hight, mXYPaint);
        }

        private void drawBrokenPaint (Canvas canvas){
            mPerX = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight) / mPoints.size();
            mPerY = ((mBaseHeight - mBasePaddingTop - mBasePaddingBottom) / 80);
            Path path = new Path();
            path.moveTo(mBasePaddingLeft, (mBaseHeight - mBasePaddingTop) - (mPoints.get(0).y * mPerY));
            for (int i = 1; i < mPoints.size(); i++) {
                path.lineTo(mBasePaddingLeft + (i * mPerX), (mBaseHeight - mBasePaddingTop) - (mPoints.get(i).y * mPerY));
            }
            canvas.drawPath(path, mLinePaint);

        }

        public void setData (ArrayList < Point > points) {
            this.mPoints = points;
            invalidate();
        }

githubアドレスはhttps://github.com/yybDream/ChartView/tree/master