绘制带线性颜色变化填充的折线图

最近在项目中遇到一个显示折线图的效果,但此效果与一般的折线图显示有几点特殊的要求:1、折线图里面,需要用特定的颜色填充,并且此颜色右上而下是渐变的;2、此折线图只需要均匀显示10个数据;3、在0,3,6,9这几个点上面,需要把改点代表的数字显示出来。效果图如下:
这里写图片描述

此效果的时候不多解释,肯定需要用到我们的自定义View,通过canvas来绘制曲线,绘制文字,绘制多边形并且用线性变化的颜色填充它,在底部还绘制了一个黑色填充的矩形。
这里先普及一下API:
canvas.drawText(string, x,y,paint); //绘制string文字,x代表的是字符开始的x坐标,y代表的是字符底部的坐标。
canvas.drawLine(startx, starty, endx, endy, paint); //绘制线段,开始的坐标和结束的坐标连接起来就成了一个线段,每根线段连接起来就是折线了。

Path.moveTo(float x,float y);//把绘制点移动到某个地方。

Path.lineTo(float x,float y);//添加多边形的点,绘制多边形的时候就会根据这些点依次绘制,形成我们需要的多边形。

LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, TileMode tile);//线性渐变类的构造参数,x0,y0表示线性变化开始的点;x1,y1表示线性变化结束的点;colors数组表示颜色的变化分布;positions表示颜色的分配比例,它的个数需要和颜色值一一对应,如果是null则直接均匀线性变化;TileMode 表示颜色铺垫的模式,我们一般写的是TileMode.REPEAT。

下面贴出代码:

public class Custom_line extends View{


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

    private static final int BOTTOMY = 100; //底部黑色矩形的高度

    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);
    }

    /**
     * 绘制多边形
     */
    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);
    }


    /**
     * 绘制文字
     * @param canvas
     */
    private void drawText(Canvas canvas){

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

        //计算最后一个文字的宽度
        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);
    }

    /**
     * 绘制底部的黑色矩形
     * @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);
        }
    }

    /**
     * 根据传进来的数据获得应该显示的数据点
     * @return
     */
    private Point[] getPoints(){
        if(data==null){
            return null;
        }

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

        int viewHeight = getHeight()- BOTTOMY;  //因为底部要画一个黑色的矩形,所以需要把这个高度减掉
        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;
    }


}

原码地址:https://code.csdn.net/yus201120/mycustom2/tree/master

猜你喜欢

转载自blog.csdn.net/yus201120/article/details/76690274