Android自定义view之天气折线图

来源:互联网 发布:淘宝买东西有质量问题 编辑:程序博客网 时间:2024/05/22 06:04

Android自定义view之天气折线图

最近公司一个项目需求,需要添加一个折线图,能够显示七天的天气信息。当然这个需求并不是很难,网上也有很多相关的例子,但是为了巩固下自定义view的基础,所以我决定还是自己写一个玩玩。不啰嗦,先上效果图(demo没有美化,比较简陋)
这里写图片描述

看了效果图,是不是感觉比较简单,麻雀虽小,但是五脏俱全,这里面囊括自定义view的核心。
先介绍下自定义view里面的几个核心方法,后面我们都有用到的。
OnMeasure 这个负责测量的,一般我习惯在这里计算自定义view需要的一些值,比如说间距,大小等。
OnDraw 听这个名字就知道是绘制了,也是这个demo的最重要的地方了。


分析

两点确定一条线,这个概念大概我们在读小学的时候老师就应该教过我们吧,所以我们绘制折线的时候也是要依据这个概念了。点是通过XY来确定的,这里X是比较简单确定,因为都是相同的间隔,难点就是Y了。
想要知道Y坐标也是很简单的,在七天温度中,我们可以知道最高温与最低温相差多少,然后也可以知道我们的绘制区域的高度,最后就可以得知一个温度所占的高度。然后用每一个温度去减去最低温,就可以得与最低温相差多少,然后就很轻松的知道这个温度的高度了。

声明需要的值

将一些常用的值写在上面是为了便于以后修改,万一哪天产品经理要你改下颜色什么的,一下就可以搞定了,不用到处去找。

   /**     * view的总高度     */    private  int mViewHeight;    /**     * view的总宽度     */    private int mViewWidth;    /**     * 温度字体大小     */    private int mTempTextSize=22;    /**     * 温度字体颜色     */    private int mTempTextColor=Color.GREEN;    /**     * 线的宽度     */    private int mWeaLineWidth = 3;    /**     * 圆点的半径     */    private int mWeaDotRadius = 5;    /**     * 画圆圈的画笔与画线的笔     */    private Paint mDotPaint;    private Paint mLinePaint;    /**     * 画灰色线的笔与画温度的笔     */    private Paint mGrayLinePaint;    private TextPaint mTempPaint;    /**     * 文字和点的间距     */    private int mTextDotDistance = 20;    /**     * 坐标点文字偏移量     */    private static final int POINT_TEXT_OFFSET = 10;    /**     *  最高温集合中温度差     */    private float mHighsTempest;    /**     *  最低温集合中温度差     */    private int mLowsTempest;    /**     * 最高温数组     */    private List<Integer> mHighs;    /**     * 最低温数组     */    private List<Integer> mLows;    /**     * 与顶部和底部的间距     */    private final int mMarginTopAndrBottom=15;    /**     *每个点的间隔X轴     */    private int mInterval;    /**     * 第一个点的X坐标     */    private float mFristX;    /**     * 折线图高度(单个)     */    private float mLineHeight;    /**     * 灰色线的间隔     */    private int mSpace=200;    //高温线的颜色    private final  static int LINE_COLOR_HIGH=Color.RED;    //低温线的颜色    private final static int LINE_COLOR_LOW=Color.BLUE;

绘制线

因为七个点,所以只要画6条线就OK了.

 private void drawLine(Canvas canvas) {        float highsBaseY=mLineHeight/mHighsTempest;//最高温中每隔一度对应相隔多少y坐标        float lowsBaseY=mLineHeight/mLowsTempest;//最低温中每隔一度对应相隔多少y坐标        float y1,y2=0f;//y1起点y坐标,y2 终点y坐标        float x1,x2=0f;        //绘制高温        for (int i=0;i<mHighs.size()-1;i++){            x1=mFristX+mInterval*i;            x2=mFristX+mInterval*(i+1);            y1=mHighs.get(i)-mHighsLowest;            y1=highsBaseY*y1-(mMarginTopAndrBottom*3);            y1=mLineHeight-y1;            y2=mHighs.get(i+1)-mHighsLowest;            y2=highsBaseY*y2-(mMarginTopAndrBottom*3);            y2=mLineHeight-y2;            canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));            canvas.drawLine(x1,y1,x2,y2,mLinePaint);        }        //绘制低温        mLinePaint.setColor(Color.BLUE);        for (int i=0;i<mLows.size()-1;i++){            x1=mFristX+mInterval*i;            x2=mFristX+mInterval*(i+1);            y1=mLows.get(i)-mLowsLowsest;            y1=lowsBaseY*y1-(mMarginTopAndrBottom*3);            y1=mLineHeight-y1+mSpace;            y2=mLows.get(i+1)-mLowsLowsest;            y2=lowsBaseY*y2-(mMarginTopAndrBottom*3);            y2=mLineHeight-y2+mSpace;            canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));            canvas.drawLine(x1,y1,x2,y2,mLinePaint);        }    }

绘制圆圈

    private void drawDot(Canvas canvas) {        float highsBaseY=mLineHeight/mHighsTempest;//最高温中每隔一度对应相隔多少y坐标        float lowsBaseY=mLineHeight/mLowsTempest;//最低温中每隔一度对应相隔多少y坐标      //  Log.e("smile","highsBaseY "+highsBaseY+"  lowsBaseY"+lowsBaseY);        float y=0f;        float x=0f;        for (int i = 0; i < mHighs.size(); i++) {            y=mHighs.get(i)-mHighsLowest;            x=mFristX+mInterval*i;            y=highsBaseY*y-(mMarginTopAndrBottom*3);            y=mLineHeight-y;            canvas.drawCircle(x,y,mWeaDotRadius,mDotPaint);        }        for (int i = 0; i < mLows.size(); i++) {          //  Log.e("smile","lowset "+mLowsLowsest+"  "+mLows.get(i)+" mlineHeight "+mLineHeight);            y=mLows.get(i)-mLowsLowsest;            y=lowsBaseY*y-(mMarginTopAndrBottom*3);            y=mLineHeight-y+mSpace;            canvas.drawCircle(mFristX+mInterval*i,y,mWeaDotRadius,mDotPaint);        }    }

绘制温度

记住一个是在上面,一个是在下面,

 private void drawTemp(Canvas canvas){        float baseY=mLineHeight/mHighsTempest;//每隔一度对应相隔多少y坐标        float lowsBaseY=mLineHeight/mLowsTempest;//最低温中每隔一度对应相隔多少y坐标        float y=0f;        float x=0f;        for (int i = 0; i < mHighs.size(); i++) {            y=mHighs.get(i)-mHighsLowest;            y=baseY*y-(mMarginTopAndrBottom*3);            y=mLineHeight-y-mTextDotDistance;            x=mFristX+mInterval*i-POINT_TEXT_OFFSET;            canvas.drawText(String.valueOf(mHighs.get(i)),x,y,mTempPaint);        }        for (int i = 0; i < mHighs.size(); i++) {            y=mLows.get(i)-mLowsLowsest;            y=lowsBaseY*y-(mMarginTopAndrBottom*3);            y=mLineHeight-y+mSpace+mTextDotDistance+10;            x=mFristX+mInterval*i-POINT_TEXT_OFFSET;            canvas.drawText(String.valueOf(mLows.get(i)),x,y,mTempPaint);        }    }

最后贴上这个类的源码:传送门

代码都有详细的注释。周五万岁,,,

0 0
原创粉丝点击