Drawing Fold Chart with Linear Color Change Filling

Recently in the project encountered a display of polyline map effect, but this effect and general polyline map display has several special requirements: 1, polyline map inside, need to be filled with a specific color, and this color is gradient from top to bottom right; 2, this polyline map only needs to display 10 data evenly; 3, in 0, 3, 6, 9 points above, need to change the point of digital display. Come out. The results are as follows:

This effect is not explained much, we definitely need to use our custom View, draw curves through canvas, draw text, draw polygons and fill it with linearly varying colors, and draw a black filled rectangle at the bottom.
Let's first popularize API:
canvas.drawText(string, x, y, paint); // Draw string text, X represents the X coordinates at the beginning of the character, Y represents the coordinates at the bottom of the character.
canvas.drawLine(startx, starty, endx, endy, paint); // Draw line segments, the starting coordinates and the ending coordinates are connected to form a line segment, each line segment is connected to a broken line.

Path.moveTo (float x, float y); // Move the drawing point somewhere.

Path.lineTo (float x, float y); // Add points to the polygon, and draw the polygon according to these points in turn, forming the polygon we need.

Linear Gradient (float x0, float y0, float x1, float y1, int [] colors, float [] positions, Tile Mode tile); //linear gradient class construction parameters, x0, Y0 represents the starting point of linear change; x1, Y1 represents the end point of linear change; colors array represents the change distribution of color; positions represent the allocation ratio of color, and its number needs to correspond to the color value one by one. If it is null, it changes linearly and uniformly; TileMode represents the pattern of color matting, which we usually write TileMode.REPEAT.

The code is pasted below:

public class Custom_line extends View{


    Point[] points;
    ArrayList<Integer> data;
    int maxdata; 
    Paint paint;

    private static final int BOTTOMY = 100; //Height of the Black Rectangle at the Bottom

    private static final String TAG = "Custom_line";

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

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

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

        paint = new Paint();
        paint.setColor(Color.rgb(00, 0x55, 0xff));
        paint.setStyle(Style.FILL);

    }

    public void setDatas(ArrayList<Integer> data,int linemaxdata){
        this.data = data;
        this.maxdata = linemaxdata;
        invalidate();
    }

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

    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        points = getPoints();
        if(points==null){
            return;
        }

        drawPolygon(canvas);
        drawLine(canvas);
        drawRect(canvas);
        drawText(canvas);
    }

    /**
     * draw a polygon
     */
    private void drawPolygon(Canvas canvas){
        Path jianbianpath = new Path();
        jianbianpath.moveTo(0, getHeight() - BOTTOMY);

        for(int i=0; i<points.length; i++){
            jianbianpath.lineTo(points[i].x, points[i].y);
        }

        int minY ;
        minY = points[0].y;
        for(int i=1;i<points.length;i++){
            if(points[i].y<minY){
                minY = points[i].y;
            }
        }
        Shader jianbianshader = new LinearGradient(getWidth()/2, minY,getWidth()/2, getHeight()-BOTTOMY,
                new int [] {Color.rgb(34, 67, 172),Color.rgb(18, 19, 20)}, null, TileMode.REPEAT);
        paint.setShader(jianbianshader);
        jianbianpath.lineTo(points[points.length-1].x, getHeight()-BOTTOMY);
        jianbianpath.close();
        canvas.drawPath(jianbianpath, paint);
    }


    /**
     * Drawing Text
     * @param canvas
     */
    private void drawText(Canvas canvas){

        Paint textpaint = new Paint();
        textpaint.setColor(Color.WHITE);
        textpaint.setTextSize(40);

        //Calculate the width of the last word
        Rect bounds = new Rect();
        String dataend = String.valueOf(data.get(9));
        textpaint.getTextBounds(dataend, 0, dataend.length(), bounds);

        canvas.drawText(data.get(0)+"", points[0].x, points[0].y -16, textpaint);
        canvas.drawText(data.get(3)+"", points[3].x -20, points[3].y -16, textpaint);
        canvas.drawText(data.get(6)+"", points[6].x-20, points[6].y -16, textpaint);
        canvas.drawText(data.get(9)+"", points[9].x - bounds.width()-1, points[9].y -16, textpaint);
    }

    /**
     * Draw a black rectangle at the bottom
     * @param canvas
     */
    private void drawRect(Canvas canvas){

        Rect rect = new Rect(0, getHeight() - BOTTOMY-1, getWidth(),getHeight());
        Paint rectpaint = new Paint();
        rectpaint.setColor(Color.rgb(18, 19, 20));
        canvas.drawRect(rect, rectpaint);
    }

    /**
     * 
     * @param canvas
     */
    private void drawLine(Canvas canvas)
    {
        Point startp = new Point();
        Point endp = new Point();
        Paint linepaint = new Paint();
        linepaint.setColor(Color.rgb(41, 88, 172));
        for (int i = 0; i < points.length - 1; i++)
        {
            startp = points[i];
            endp = points[i + 1];
            canvas.drawLine(startp.x, startp.y, endp.x, endp.y, linepaint);
        }
    }

    /**
     * Get the data points that should be displayed based on the incoming data
     * @return
     */
    private Point[] getPoints(){
        if(data==null){
            return null;
        }

        int count = data.size();
        Point[] temppoints = new Point[count];

        int viewHeight = getHeight()- BOTTOMY;  //Because a black rectangle is drawn at the bottom, you need to subtract the height.
        int viewWidth = getWidth();

        for(int i=0 ; i<count ; i++){
            int y =  (int) (viewHeight*(1- ((data.get(i)*1.0f)/maxdata)));
            int x = (int) (((viewWidth*1.0f)/(count-1))*i);
            Log.i(TAG, "x:"+x);
            Point mpoint = new Point(x, y);
            temppoints[i] = mpoint;
        }
        return temppoints;
    }


}

Original address: https://code.csdn.net/yus201120/mycustom2/tree/master

Added by wobbit on Sat, 08 Jun 2019 02:19:02 +0300