Android自定義view之天氣折線圖

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

    }

最後貼上這個類的源碼:傳送門

代碼都有詳細的註釋。週五萬歲,,,

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章