自定义折线图

来源:互联网 发布:什么是bim软件 编辑:程序博客网 时间:2024/06/05 23:56

继续来一片简单的自定义View,折线图的自定义。
这里写图片描述
每天来一篇,进步无极限。愚公移山也要由易到难的,这次就没写xml文件的自定义属性:

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

然后还是重写onMeasure方法:

int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        if (MeasureSpec.EXACTLY == widthMode) {            width = widthSize;        } else {            throw new IllegalArgumentException("width is exactly mode!");        }        if (MeasureSpec.EXACTLY == heightMode) {            height = heightSize;        } else {            throw new IllegalArgumentException("height is exactly mode!");        }        setMeasuredDimension(width, height);

由于想省点事,就直接用EXACTLY ,没有去管atmost,无关紧要,
关键在ondraw方法里面比较费事:

@Override    protected void onDraw(Canvas canvas) {        Paint mPaint = new Paint();        mPaint.setTextSize(textFontSize);        mPaint.setColor(Color.RED);        /**         * 画Y轴         */        int[] pointY = new int[textY.length];//保存y轴文字的坐标        //计算每个刻度的间距        int discY = (int) ((height - textFontSize * textY.length) / textY.length);        //测量文字的高度        Paint.FontMetrics fm = mPaint.getFontMetrics();        int yheight = (int) Math.ceil(fm.descent - fm.ascent);        for (int i = 0; i < textY.length; i++) {            canvas.drawText(textY[i], 0, discY * i + yheight, mPaint);            pointY[i] = discY * i + yheight;        }        /**         * 画X轴         */        int[] pointX = new int[textX.length];//保存y轴文字的坐标        int offset = 50;        //计算每个刻度的距离        int discX = (int) ((width - textFontSize * textX.length) / textX.length);        for (int i = 0; i < textX.length; i++) {            canvas.drawText(textX[i], i * discX + textFontSize + offset, height - yheight - offset, mPaint);            pointX[i] = (int) (i * discX + textFontSize + offset);        }        /**         * 画点         */        mPaint.setColor(Color.DKGRAY);        mPaint.setAntiAlias(true);        mPaint.setStyle(Paint.Style.FILL);        int radious = 10;        Paint linePaint = new Paint();        linePaint.setColor(Color.DKGRAY);        linePaint.setAntiAlias(true);        linePaint.setStrokeWidth(5);        for (int i = 0; i < textX.length; i++) {            if (mapParams == null) {                throw new IllegalArgumentException("map 不能为空");            }            canvas.drawCircle(pointX[i], pointY[mapParams.get(i)], radious, mPaint);            if (i > 0) {                canvas.drawLine(pointX[i - 1], pointY[mapParams.get(i - 1)], pointX[i], pointY[mapParams.get(i)], linePaint);            }        }    }

首先画Y轴,在画Y轴的时候定义了一个数组来保存对应的坐标:

  /**         * 画Y轴         */        int[] pointY = new int[textY.length];//保存y轴文字的坐标        //计算每个刻度的间距        int discY = (int) ((height - textFontSize * textY.length) / textY.length);        //测量文字的高度        Paint.FontMetrics fm = mPaint.getFontMetrics();        int yheight = (int) Math.ceil(fm.descent - fm.ascent);        for (int i = 0; i < textY.length; i++) {            canvas.drawText(textY[i], 0, discY * i + yheight, mPaint);            pointY[i] = discY * i + yheight;        }

然后同样画X轴的时候,也要定义一个数组来保存X轴的坐标,

/**         * 画X轴         */        int[] pointX = new int[textX.length];//保存y轴文字的坐标        int offset = 50;        //计算每个刻度的距离        int discX = (int) ((width - textFontSize * textX.length) / textX.length);        for (int i = 0; i < textX.length; i++) {            canvas.drawText(textX[i], i * discX + textFontSize + offset, height - yheight - offset, mPaint);            pointX[i] = (int) (i * discX + textFontSize + offset);        }

下面就是画点,首先在MainActivity里面定义了一个Map来保存要画的点,通过在View设置的方法把Map传进来。

/**     * 设置Y轴的数据     *     * @param textY     */    public void setTextY(String[] textY) {        this.textY = textY;    }    /**     * 设置X轴的数据     *     * @param textX     */    public void setTextX(String[] textX) {        this.textX = textX;    }    /**     * 设置Map     *     * @param mapParams     */    public void setMapParams(Map<Integer, Integer> mapParams) {        this.mapParams = mapParams;    }

然后就开始画点和画折线:

 /**         * 画点         */        mPaint.setColor(Color.DKGRAY);        mPaint.setAntiAlias(true);        mPaint.setStyle(Paint.Style.FILL);        int radious = 10;        Paint linePaint = new Paint();        linePaint.setColor(Color.DKGRAY);        linePaint.setAntiAlias(true);        linePaint.setStrokeWidth(5);        for (int i = 0; i < textX.length; i++) {            if (mapParams == null) {                throw new IllegalArgumentException("map 不能为空");            }            canvas.drawCircle(pointX[i], pointY[mapParams.get(i)], radious, mPaint);            if (i > 0) {                canvas.drawLine(pointX[i - 1], pointY[mapParams.get(i - 1)], pointX[i], pointY[mapParams.get(i)], linePaint);            }        }

最后在MainActivity里面设置下数据就ok了:

  private String[] textY = {"50k", "40k", "30k", "20K", "10k"};    private String[] textX = {"1", "2", "3", "4", "5", "6", "7"};    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        DefineLineView lineView = (DefineLineView) findViewById(R.id.lineView);        lineView.setTextY(textY);        lineView.setTextX(textX);        Map<Integer, Integer> map = new HashMap<>();        for (int i = 0; i < textX.length; i++) {            map.put(i, (int) (Math.random() * 5));        }        lineView.setMapParams(map);    }

贴一下Xml文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    >    <com.example.shuiai.defineline.DefineLineView        android:id="@+id/lineView"        android:layout_width="match_parent"        android:layout_height="300dp" /></LinearLayout>

贴下View的完整代码:

public class DefineLineView extends View {    /**     * view的宽     */    private int width;    /**     * View的高     */    private int height;    /**     * 存放Y轴文字的数组     */    private String[] textY;    /**     * 存放X轴文字的数组     */    private String[] textX;    /**     * 文字大小     */    private float textFontSize = 40;    /**     * 设置Map     *     * @param context     */    private Map<Integer, Integer> mapParams;    public DefineLineView(Context context) {        super(context);    }    public DefineLineView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public DefineLineView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @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);        if (MeasureSpec.EXACTLY == widthMode) {            width = widthSize;        } else {            throw new IllegalArgumentException("width is exactly mode!");        }        if (MeasureSpec.EXACTLY == heightMode) {            height = heightSize;        } else {            throw new IllegalArgumentException("height is exactly mode!");        }        setMeasuredDimension(width, height);    }    @Override    protected void onDraw(Canvas canvas) {        Paint mPaint = new Paint();        mPaint.setTextSize(textFontSize);        mPaint.setColor(Color.RED);        /**         * 画Y轴         */        int[] pointY = new int[textY.length];//保存y轴文字的坐标        //计算每个刻度的间距        int discY = (int) ((height - textFontSize * textY.length) / textY.length);        //测量文字的高度        Paint.FontMetrics fm = mPaint.getFontMetrics();        int yheight = (int) Math.ceil(fm.descent - fm.ascent);        for (int i = 0; i < textY.length; i++) {            canvas.drawText(textY[i], 0, discY * i + yheight, mPaint);            pointY[i] = discY * i + yheight;        }        /**         * 画X轴         */        int[] pointX = new int[textX.length];//保存y轴文字的坐标        int offset = 50;        //计算每个刻度的距离        int discX = (int) ((width - textFontSize * textX.length) / textX.length);        for (int i = 0; i < textX.length; i++) {            canvas.drawText(textX[i], i * discX + textFontSize + offset, height - yheight - offset, mPaint);            pointX[i] = (int) (i * discX + textFontSize + offset);        }        /**         * 画点         */        mPaint.setColor(Color.DKGRAY);        mPaint.setAntiAlias(true);        mPaint.setStyle(Paint.Style.FILL);        int radious = 10;        Paint linePaint = new Paint();        linePaint.setColor(Color.DKGRAY);        linePaint.setAntiAlias(true);        linePaint.setStrokeWidth(5);        for (int i = 0; i < textX.length; i++) {            if (mapParams == null) {                throw new IllegalArgumentException("map 不能为空");            }            canvas.drawCircle(pointX[i], pointY[mapParams.get(i)], radious, mPaint);            if (i > 0) {                canvas.drawLine(pointX[i - 1], pointY[mapParams.get(i - 1)], pointX[i], pointY[mapParams.get(i)], linePaint);            }        }    }    /**     * 设置Y轴的数据     *     * @param textY     */    public void setTextY(String[] textY) {        this.textY = textY;    }    /**     * 设置X轴的数据     *     * @param textX     */    public void setTextX(String[] textX) {        this.textX = textX;    }    /**     * 设置Map     *     * @param mapParams     */    public void setMapParams(Map<Integer, Integer> mapParams) {        this.mapParams = mapParams;    }}

有木有很简单,很简单。

0 0
原创粉丝点击