一个自定义的折线图

公司项目内部需求,轻喷,先上图

这里写图片描述

GqLineChartView的代码

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

import java.util.ArrayList;

/**
 * 作者:Mr.Lee on 2017-7-6 09:46
 * 邮箱:[email protected]
 */

public class GqLineChartView extends View {


    private Paint paint;
    private TextPaint mTextPaint;
    // 上下间隔
    private int verticalSpace = dipToPx(getContext(), 28f);//默认上下间隔 约为55px
    //垂直默认分块数
    private int verticalNum = 5;
    // 左下角Y
    private int mHeigh = verticalSpace * verticalNum+1;//默认高度
    //水平默认分块数
    private int horizontalNum =1;
    // 水平间隔
    private int horizontalSpace;
    //水平padding
    private int horizontalPadding = dipToPx(getContext(), 15f);
    //垂直padding
    private int verticalPadding = dipToPx(getContext(),5);
    //垂直值域高度
    private int valuesHeigh;
    //外yuan半径
    private int mCircleOut=4;
    //内圆半径
    private int mCircleInside=3;

    private int mWidth;//控件宽度
    private int mIndex; //第几个被选中

    private int mHeighView=mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 17f);

    private ArrayList<Float> listX =new ArrayList<>() ;
    private ArrayList<Float> listY =new ArrayList<>() ;
    private ArrayList<Float> mValues = new ArrayList<>(); //值
    private ArrayList<String> mXString = new ArrayList<>(); //值

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

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

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

    public static int dipToPx(Context context, float dip) {
        float density = context.getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
    }

    private void init() {
        paint = new Paint();
        mTextPaint=new TextPaint();
        WindowManager manager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        // 方法1,获取屏幕的默认分辨率
        Display display = manager.getDefaultDisplay(); // getWindowManager().getDefaultDisplay();
        mWidth=display.getWidth()-dipToPx(getContext(),16f)*2;

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(mWidth,mHeighView);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 画数中间横线
        DashPathEffect effects = new DashPathEffect(new float[] { 5, 5, 5, 5 }, 1);
        paint.setColor(Color.parseColor("#ffe2dd"));
        paint.setStrokeWidth(1);
        for (int i = 0; i < verticalNum; i++) {
            float x1 = 0;
            float y = (i + 1) * verticalSpace;
            float x2 = getMeasuredWidth();
            canvas.drawLine(x1, y, x2, y, paint);
        }
        if (mValues.size() <1 || listX.size()<=0 || listY.size()<=0) {
            return;
        }
        // 画数据折线
        paint.setColor(Color.parseColor("#ff3e19"));
        paint.setStrokeWidth(4);
        paint.setStyle(Paint.Style.STROKE);
        Path path = new Path();
        for (int i = 0; i < mValues.size(); i++) {
            if (i == 0) {
                path.moveTo(listX.get(i), listY.get(i));
            } else {
                path.lineTo(listX.get(i), listY.get(i));
            }
        }
        canvas.drawPath(path, paint);
        //画坐标

        mTextPaint.setStrokeWidth(5);
        mTextPaint.setTextSize(dipToPx(getContext(),11));
        mTextPaint.setStyle(Paint.Style.FILL);
        for (int i = 0; i < mXString.size(); i++) {
            if (i == mIndex) {
                if(i==0){
                    mTextPaint.setTextAlign(Paint.Align.LEFT);
                }else if(i==mValues.size()-1){
                    mTextPaint.setTextAlign(Paint.Align.RIGHT);
                }else {
                    mTextPaint.setTextAlign(Paint.Align.CENTER);
                }
                String str=mXString.get(i);
                mTextPaint.setColor(Color.parseColor("#ffffff"));
                Paint linePaint=new Paint();
                linePaint.setColor(Color.parseColor("#ff3e19"));
                linePaint.setStrokeWidth(dipToPx(getContext(), 16f));
                linePaint.setStrokeCap(Paint.Cap.ROUND);
                Rect rect = new Rect();
                paint.getTextBounds(str, 0, str.length(), rect);
                int w = rect.width();
                if(i==0){
                    canvas.drawLine(listX.get(i),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 8f),listX.get(i)+dipToPx(getContext(), w),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 8f), linePaint);
                }else if(i==mValues.size()-1){
                    canvas.drawLine(listX.get(i)-dipToPx(getContext(), w),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 8f),listX.get(i),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 8f), linePaint);
                }else {
                    canvas.drawLine(listX.get(i)-dipToPx(getContext(), w/2),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 8f),listX.get(i)+dipToPx(getContext(), w/2),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 8f), linePaint);
                }
               // canvas.drawLine(listX.get(i)-dipToPx(getContext(), w/2),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 8f),listX.get(i)+dipToPx(getContext(), w/2),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 8f), linePaint);
                canvas.drawText(str,listX.get(i),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 12f), mTextPaint);

            } else {
                mTextPaint.setTextAlign(Paint.Align.CENTER);
                mTextPaint.setColor(Color.parseColor("#000000"));
                canvas.drawText(mXString.get(i),listX.get(i),mHeigh+dipToPx(getContext(), 8f)+dipToPx(getContext(), 12f), mTextPaint);
            }
        }
        // 画被选中的竖线
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.parseColor("#ff8e78"));
        paint.setPathEffect(effects);
        paint.setStrokeWidth(2);
        Path path_vertical = new Path();
        path_vertical.moveTo(listX.get(mIndex),mHeigh+dipToPx(getContext(), 8f));
        path_vertical.lineTo(listX.get(mIndex), verticalSpace*2f);
        canvas.drawPath(path_vertical, paint);

        // 画被选中的竖线头部的圆
        paint.reset();
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(2);
        paint.setColor(Color.parseColor("#ff8e78"));
        canvas.drawCircle(listX.get(mIndex), verticalSpace*2f-dipToPx(getContext(),mCircleInside), dipToPx(getContext(),mCircleInside), paint);

        //画文字
        if(mIndex==0){
            mTextPaint.setTextAlign(Paint.Align.LEFT);
        }else if(mIndex==mValues.size()-1){
            mTextPaint.setTextAlign(Paint.Align.RIGHT);
        }else{
            mTextPaint.setTextAlign(Paint.Align.CENTER);
        }
        mTextPaint.setStrokeWidth(5);
        mTextPaint.setTextSize(dipToPx(getContext(),11));
        mTextPaint.setColor(Color.parseColor("#666666"));
        mTextPaint.setStyle(Paint.Style.FILL);

        canvas.drawText("预计回款金额", listX.get(mIndex),verticalSpace*2f-dipToPx(getContext(),mCircleInside)*2-15, mTextPaint);

        mTextPaint.setTextSize(dipToPx(getContext(),14));
        mTextPaint.setColor(Color.parseColor("#ff3e19"));
        mTextPaint.setFakeBoldText(true);
        canvas.drawText(String.valueOf(mValues.get(mIndex)), listX.get(mIndex),verticalSpace*2f-dipToPx(getContext(),mCircleInside)*2-20-dipToPx(getContext(),11), mTextPaint);

        //画阴影
        Path path_shadow = new Path();
        paint.setColor(Color.parseColor("#10ff3e19"));
        paint.setStyle(Paint.Style.FILL);
        path_shadow.moveTo(listX.get(0)-dipToPx(getContext(),mCircleOut), listY.get(0));

        for (int i = 0; i < mValues.size(); i++) {
            path_shadow.lineTo(listX.get(i), listY.get(i));
        }
        path_shadow.lineTo(listX.get(listX.size()-1)+dipToPx(getContext(),mCircleOut), listY.get(listX.size()-1));
        path_shadow.lineTo(listX.get(listX.size()-1)+dipToPx(getContext(),mCircleOut), mHeigh);
        path_shadow.lineTo(listX.get(0)-dipToPx(getContext(),mCircleOut), mHeigh);
        path_shadow.close();
        canvas.drawPath(path_shadow, paint);

        // 画出转折点圆圈
        paint.setStyle(Paint.Style.FILL);
        for (int i = 0;i <mValues.size(); i++) {

            if(i==mIndex){
                // 画外圆
                paint.setColor(Color.parseColor("#19ff3e19"));
                canvas.drawCircle(listX.get(i), listY.get(i), dipToPx(getContext(),10), paint);
                // 画外圆
                paint.setColor(Color.parseColor("#21ff3e19"));
                canvas.drawCircle(listX.get(i), listY.get(i), dipToPx(getContext(),7), paint);
                // 画外圆
                paint.setColor(Color.WHITE);
                canvas.drawCircle(listX.get(i), listY.get(i), dipToPx(getContext(),mCircleOut), paint);
                // 画中心点为白色
                paint.setColor(Color.parseColor("#ff3e19"));
                canvas.drawCircle(listX.get(i), listY.get(i), dipToPx(getContext(),mCircleInside), paint);

                continue;
            }
            // 画外圆
            paint.setColor(Color.parseColor("#ff3e19"));
            canvas.drawCircle(listX.get(i), listY.get(i), dipToPx(getContext(),mCircleOut), paint);
            // 画中心点为白色
            paint.setColor(Color.WHITE);
            canvas.drawCircle(listX.get(i), listY.get(i), dipToPx(getContext(),mCircleInside), paint);
        }




    }

    /**
     *
     * @param values  传入的值的集合
     * @param index  第几个被选中  从0开始
     */
    public void setValues(ArrayList<Float> values,int index,ArrayList<String> xString) {

        this.mValues=values;
        this.mIndex=index;
        this.mXString=xString;

        if(null==mValues || mValues.size()<0){
            invalidate();
            return;
        }
        listX.clear();
        listY.clear();
        if(mValues.size()!=1){
            horizontalNum=mValues.size()-1;
            horizontalSpace = (mWidth - horizontalPadding * 2) / horizontalNum;
        }else{
            horizontalSpace = (mWidth - horizontalPadding * 2);
        }

        verticalSpace = mHeigh / verticalNum;
        float max = 0;
        for (int i = 0; i < mValues.size(); i++) {
            if (mValues.get(i) > max) {
                max = mValues.get(i);
            }
        }
        valuesHeigh = verticalSpace * 3 - verticalPadding * 2;

        for (int i = 0; i < mValues.size(); i++) {
            listX.add(Float.valueOf(horizontalPadding + i * horizontalSpace));
            if(max==0){
                listY.add((float)( mHeigh - verticalPadding));
                continue;
            }
            listY.add(mHeigh - verticalPadding - (mValues.get(i) / max * valuesHeigh));

        }
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()){
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_DOWN:
                for (int i=0 ;i<mValues.size();i++){
                    if(listX.get(i)-dipToPx(getContext(),20f)<event.getX()&&event.getX()<=listX.get(i)+dipToPx(getContext(),20f)){
                        if(event.getY()>listY.get(i)-dipToPx(getContext(),20f)&&event.getY()<=mHeighView){
                            if(i==mIndex){
                                return true;
                            }
                            setValues(mValues,i,mXString);
                        }
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        //这句话不要修改
        return super.onTouchEvent(event);
    }



}

使用

//布局
  <com.gq.android.views.GqLineChartView
                android:id="@+id/lcv_return"
                android:layout_marginTop="@dimen/px_20"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="16dp"
                android:layout_marginRight="16dp"
                android:layout_marginBottom="@dimen/px_20"
                />
//代码
  lcv.setValues(mValues,0,mXString);

猜你喜欢

转载自blog.csdn.net/u013728021/article/details/78274299