Android 雙刻度儀表盤

1、需求

這次要實(shí)現(xiàn)一個(gè)顯示溫濕度的view.開始打算用兩個(gè)儀表盤來顯示.原因是這個(gè)已經(jīng)有很多輪子了(偷懶ing)。后來一想,已經(jīng)有那么多輪子了,還是自己寫一個(gè)吧,順便復(fù)習(xí)一下自定義view的相關(guān)用法。

2、效果

最后實(shí)現(xiàn)的效果就是這個(gè)樣子了。


效果圖

3、實(shí)現(xiàn)前的分析和思路

想要用同一個(gè)控件同事顯示兩個(gè)進(jìn)度值,這里用指針就指向數(shù)值就不太合適了,還是用兩個(gè)嵌套在一起的儀表盤比較好。那么要先做什么,再做什么呢?我從兩個(gè)儀表盤開始,從儀表盤向兩邊輻射去畫圖。

  • 1、畫內(nèi)部溫度的儀表盤;
  • 2、畫溫度里邊的刻度數(shù)值;
  • 3、畫外部濕度的儀表盤;
  • 4、這里要在濕度儀表盤的左右兩邊畫一個(gè)小圓,這樣邊上才不會(huì)是平的;
  • 5、畫儀表盤上的小圓形代表當(dāng)前值
  • 6、畫濕度儀表盤外邊的刻度值
  • 7、畫底部的描述
    思路分析到這里,然后去動(dòng)手一步一步實(shí)現(xiàn)吧。

4、實(shí)現(xiàn)

4.1 提前裝備

這里初始化一些變量,以及畫筆顏色等等

**
     * 控件寬
     */
    private int mWidth;
    /**
     * 控件高
     */
    private int mHeight;
    private String mTempTitle = "溫度(℃)";
    private String mHumTitle = "濕度(%)";
    /**
     * 刻度高 短針
     */
    private int mScaleHeight = dp2px(10);
    /**
     * 刻度高 長(zhǎng)針
     */
    private int mScaleHeight1 = dp2px(15);
    /**
     * 刻度盤/
     */
    private Paint mDialPaint;
    /**
     * 文本畫筆
     */
    private Paint mTitlePaint;
    /**
     * 畫濕度圓環(huán)的畫筆
     */
    private Paint mHumCirclePaint;
    /**
     * 當(dāng)前濕度值的小圓點(diǎn)
     */
    private Paint mHumValueCirclePaint;
    /**
     * 濕度圓環(huán)左邊和右邊的小圓點(diǎn)畫筆
     */
    private Paint mHumLeftCirclePaint;
    private Paint mHumRightCirclePaint;

    /**
     * 當(dāng)前溫度
     */
    private int mTemperature = 15;
    //
    /**
     * 最低溫度
     */
    private int mMinTemp = -30;
    /**
     * 最高溫度
     */
    private int mMaxTemp = 50;
    /**
     * 當(dāng)前濕度
     */
    private int mHumidity = 100;
    /**
     * 最低濕度
     */
    private int mMinHum = 0;
    /**
     * 最高濕度
     */
    private int mMaxHum = 100;
    /**
     * 溫度每份的角度
     */
    private float mAngleOneTem = (float) 270 / (mMaxTemp - mMinTemp);
    /**
     * 濕度每份的角度
     */
    private float mAngleOneHum = (float) 270 / (mMaxHum - mMinHum);

    /**
     * 溫度,刻度的半徑
     */
    private int mTemDialRadius;
    /**
     * 濕度,內(nèi)圈半徑
     */
    private int mHumInSideRadius;
    /**
     * 濕度,圓環(huán)寬度
     */
    private int mHumCriWidth = dp2px(15);

    /**
     * 刻度和文字顏色
     */
    private String mTextColor = "#666666";
    /**
     * 未達(dá)到的溫度
     */
    private String mDialBackGroundColor = "#666666";
    /**
     * 已經(jīng)達(dá)到的溫度
     */
    private String mDialForegroundColor = "#1FC8A2";
    /**
     * 濕度圓環(huán)背景色
     */
    private String mHumCriBackground = "#666666";
    /**
     * 濕度圓環(huán)前景色
     */
    private String mHumCriForeground = "#1FC8A2";
    /**
     * 當(dāng)前濕度的小圓點(diǎn)顏色
     */
    private String mHumCriValue = "#eeeeee";
    /**
     * 當(dāng)前濕度的小圓點(diǎn)的背景色
     */
    private String mHumCriValueBackGround = "#30333333";

    ......


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 控件寬、高
        mWidth = mHeight = Math.min(h, w);
        // 溫度,刻度的半徑
        mTemDialRadius = mWidth / 2 - dp2px(70);
        // 濕度,內(nèi)圈半徑=刻度的內(nèi)圈+最長(zhǎng)刻度+15像素
        mHumInSideRadius = mTemDialRadius + mScaleHeight1 + dp2px(15);
    }

   ......

4.2 要去畫了

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //畫溫度刻度盤和內(nèi)的刻度
        drawTempDial(canvas);
        //畫濕度圓弧
        drawHumArc(canvas);
        //畫左邊和左邊的小圓點(diǎn)
        drwaHumArcLeftAndRight(canvas);
        //當(dāng)前濕度值
        drawHumValueArc(canvas);
        //濕度外邊的刻度
        drawHumText(canvas);
        //畫溫濕度標(biāo)題文字
        drawTemText(canvas);
    }

4.3 畫溫度刻度盤和圈內(nèi)文字

這里去遍歷一次就好了,有些人先遍歷去畫底部的背景,然后又遍歷畫前景,又遍歷一次畫刻度。這就造成了資源的浪費(fèi)。

   /**
     * 畫溫度刻度 和溫度內(nèi)圈文字
     */
    private void drawTempDial(Canvas canvas) {
        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);
        // 順時(shí)針旋轉(zhuǎn)135度
        canvas.rotate(-135);
        for (int i = mMinTemp; i <= mMaxTemp; i++) {
            if (i <= mTemperature) {
                mDialPaint.setColor(Color.parseColor(mDialForegroundColor));
            } else {
                mDialPaint.setColor(Color.parseColor(mDialBackGroundColor));
            }
            if (i % 5 == 0) {
                //從刻度的內(nèi)圈開始,往外畫
                canvas.drawLine(0, -mTemDialRadius, 0, -mTemDialRadius - mScaleHeight1, mDialPaint);
                if (i % 10 == 0) {
                    float tempWidth = mDialPaint.measureText(i + "");
                    canvas.drawText(i + "", 0 - tempWidth / 2, -mTemDialRadius + dp2px(20), mTitlePaint);
                }
            } else {
                canvas.drawLine(0, -mTemDialRadius, 0, -mTemDialRadius - mScaleHeight, mDialPaint);
            }
            canvas.rotate(mAngleOneTem);
        }
        canvas.restore();
    }

4.4 畫外圍濕度,代表當(dāng)前值的小圓點(diǎn)

這里呢,想去畫一個(gè)陰影的背景,半徑比前邊的大一點(diǎn)點(diǎn),然后在畫一個(gè)前邊的小白圓圈。這樣有一點(diǎn)小陰影更漂亮。

    /**
     * 畫當(dāng)前濕度值的小圓點(diǎn)
     */
    private void drawHumValueArc(Canvas canvas) {
        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);
        //旋轉(zhuǎn)到0,再旋轉(zhuǎn)到當(dāng)前濕度值
        canvas.rotate(-135 + mAngleOneHum * mHumidity);
        //畫背景
        mHumValueCirclePaint.setColor(Color.parseColor(mHumCriValueBackGround));
        canvas.drawCircle(0, -mHumInSideRadius, (mHumCriWidth + dp2px(10)) / 2, mHumValueCirclePaint);
        //畫前景
        mHumValueCirclePaint.setColor(Color.parseColor(mHumCriValue));
        canvas.drawCircle(0, -mHumInSideRadius, (mHumCriWidth + dp2px(7)) / 2, mHumValueCirclePaint);
        canvas.restore();
    }

4.5 畫外圍濕度,左邊和右邊的小圓點(diǎn)

先看看沒有小圓點(diǎn)的效果


test

這樣兩邊是平的,沒有突出的效果,比較丑。在兩邊都畫一個(gè)和圓環(huán)寬度一樣寬的小圓圈,就有了突出的效果了。

    /**
     * 左邊右邊分別畫一個(gè)小圓點(diǎn)
     *
     * @param canvas
     */
    private void drwaHumArcLeftAndRight(Canvas canvas) {
        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);
        //旋轉(zhuǎn)到0
        canvas.rotate(-135);
        canvas.drawCircle(0, -mHumInSideRadius, mHumCriWidth / 2, mHumLeftCirclePaint);
        canvas.rotate(270);
        canvas.drawCircle(0, -mHumInSideRadius, mHumCriWidth / 2, mHumRightCirclePaint);
        canvas.restore();
    }

后邊的方法就不一一羅列出來了,可以去看一下源碼。
傳送門

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,656評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評(píng)論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,855評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,254評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,473評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,014評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,833評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,016評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,273評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評(píng)論 1 288
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,730評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,006評(píng)論 2 374