[Android] 你可能要用到的自定義View——碼表

自定義View——IndicatorView,源碼地址:ttdevs github

0x00 main

進步淘衙、創(chuàng)新都是在不斷變化的需求中誕生的。
-- By ttdevs

這不彤守,新的需求又來了。廢話不多說具垫,先上設計稿:

boohee design

簡單分析上圖包括三部分:最上面的類Progressbar,中間兩個指示盤和最下面的指示盤卦碾。第一個類Progressbar我們項目之前有實現(xiàn)過,但是和這個需求有一些差異洲胖,因此決定重新實現(xiàn)一遍坯沪。另外兩個圓形指示盤本想通過在一張背景圖片上放一張指針圖绿映,控制指針圖的旋轉來實現(xiàn)腐晾,但是考慮到這樣不夠靈活,因此也決定自己來畫赴魁。So,我們接下來實現(xiàn)這三個View颖御。

正式開始之前,先看看我們最終效果圖(當然潘拱,指針是可以動的):

result one
result two

0x01 分析

  • LineIndicator (第一個芦岂,類Progressbar)

    主要包括三部分:左側的提示和內容瘪弓,右側的提示和內容禽最,中間的類Progressbar腺怯。兩側的文字比較容易處理,掌握了文字的基本繪制呛占,畫起來是很容易的。中間的類Progressbar由于打算自己畫晾虑,所以不會直接貼個Progressbar在上面。我的思路是畫一條長的直線作為背景帜篇,中間的指示也是直線,比背景直線粗洪灯,直線的Paint設置 StrokeCapPaint.Cap.ROUNDpaint.setStrokeCap(Paint.Cap.ROUND);,這樣就可以有兩頭半圓的效果逃沿;中間的指示數(shù)字直接畫在粗的指示直線上面即可婴渡。這里可能遇到的問題有下面兩個:

    • StrokeCap 設置 為 Paint.Cap.ROUND時的位置關系

      StrokeCap 設置 為 Paint.Cap.ROUND幻锁,直線兩側的半圓是不算在直線的長度里的。簡單來說哄尔,如果view的長度和我畫的直線長度一致,那么這個直線就是矩形而不是期待的兩側都是半圓的橢圓岭接。

    • 當進度為0或者為100%時的展示

      如果我們背景直線和指示直線起點終點位置一致,那么最終效果就是當進度為0或者100%的時候鸣戴,指示直線是顯示不全的,因此我們需要對這兩個位置進行矯正创千。我的矯正方法比較簡單,在0~x和y~100%進度的時候分別顯示x和y(本以為自己的思路很屌追驴,后來發(fā)現(xiàn)別人也是這么干的)疏之。

  • CircleIndicator (中間的多種顏色環(huán))

    這個View我將其分解為四部分,從上層到下層:中間指針锋爪,刻度環(huán)爸业,顯示的內容,圓環(huán)背景和外層指示文字沃呢。每一部分再做分解:

    • 中間指針

      這個又分解為六個部分:最下層大圓拆挥,兩個圓形半圓薄霜,兩個三角形和上層小圓纸兔。

    • 刻度環(huán)

      由于是圓環(huán),所以必須畫弧線了汉矿。但是這個弧線又有點特殊,兩側帶圓角奈揍,中間圓環(huán)直角,這個沒想到啥好辦法赋续,用了很一般的思路:先用 Paint.Cap.ROUND 畫兩側的弧,然后 Paint.Style.STROKE 畫中間的部分纽乱。

    • 顯示的內容

      這個就比較簡單了,主要在于計算文字的顯示位置鸦列。

    • 圓環(huán)背景和外層文字

      最簡單的一個圓,加一個以圓為路徑畫的文字顽爹。

最后我們畫的順序正好與上面所述順序相反。
  • ProgressIndicator (最下面的兩種顏色環(huán))

    這個相較 CircleIndicator 就簡單了一些镜粤。在畫圓環(huán)的時候诲锹,我們只需要先畫一個灰色背景,然后再畫一個綠色圓弧即可归园。

0x02 實現(xiàn)

View的繪制我們應該都比較熟悉,主要有下面三個過程: onMeasure(測量)庸诱、onLayout(布局)晤揣、onDraw(繪制)朱灿。針對上述三個View:LineIndicator,我們根據實際的內容來計算View的高度盗扒,寬度用戶設定;CircleIndicator和ProgressIndicator的寬度用戶設定侣灶,高度自定計算與寬度相同。onLayout我們不需要池户。最后的根據實際的展示內容來繪制凡怎。

另外校焦,由于CircleIndicator和ProgressIndicator和相似度高统倒,很多代碼可以拿來重用,因此檐薯,我寫了一個基類來完成公共的部分注暗,特殊部分每個 子類自己完成。最后再子類地onDraw方法中按照順序調用即可赚楚。

由于主要是計算各種坐標位置,代碼還是不少的宠页,這里就不貼代碼寇仓。最后的實現(xiàn)請移步我的 github。三個View的代碼已經整理完LineIndicator遍烦,其它的兩個還需要點時間(2016-06-19)。

0x03 知識點

  • 自定義View的思路

    • 創(chuàng)建類服猪,繼承自View或者ViewGroup或者其它ViewGroup
    • 定義View的可配置參數(shù)拐云,如果你需要的話
    • 實現(xiàn)View的具體邏輯

    這個太粗略了近她,各位可以參考具體源碼。

  • 文字位置的計算

    如果你沒有自己畫過文字粘捎,那你肯定不可能一下子明白文字的畫法,或多或少的出現(xiàn)偏移捅暴。這里直接給大家推薦一篇講的非常詳細的文章:http://blog.csdn.net/aigestudio/article/details/41447349

  • 位置、半徑蓬痒、弧長等的計算

    這里會涉及到簡單的三角函數(shù)和圓的周長弧度的計算漆羔,可能要說的就是三角函數(shù)的參數(shù)是弧度制度。

  • ObjectAnimator

    /**
     * 設置內容的顏色值(非resource的id)
     *
     * @param contentColor 內容的顏色值
     * @param unitColor    單位的顏色值
     */
    public void setContentColor(int contentColor, int unitColor) {
        mContentColor = contentColor;
        mUnitColor = unitColor;
    }
    
    /**
     * 設置進度
     *
     * @param indicator 進度值
     */
    public void setIndicator(float indicator) {
        if (indicator <= mStartIndicator) {
            mIndicator = mStartIndicator;
        } else if (indicator > mEndIndicator) {
            mIndicator = mEndIndicator;
        } else {
            mIndicator = indicator;
        }
        postInvalidate();
    }
    
    /**
     * 獲取進度
     *
     * @return 當前進度值
     */
    public float getIndicator() {
        return mStartIndicator;
    }
    
    public void animateIndicator(float indicator) {
        Interpolator interpolator = new AnticipateOvershootInterpolator(1.8f);
        ObjectAnimator animation = ObjectAnimator.ofFloat(this, "indicator", indicator);
        animation.setDuration(2000);
        animation.setInterpolator(interpolator);
        animation.start();
    }
    
  • 處理屏幕的旋轉

    由于時間比較緊亲轨,這個我還沒做。主要在View的以下兩個方法中實現(xiàn):

    
    @Override
    protected Parcelable onSaveInstanceState() {
        return super.onSaveInstanceState();
    }
    
    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(state);
    }
    
    

最后歡迎各位吐槽并提供更好的建議~~

Create by ttdevs
Create by ttdevs
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末惦蚊,一起剝皮案震驚了整個濱河市讯嫂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欧芽,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件憎妙,死亡現(xiàn)場離奇詭異曲楚,居然都是意外死亡,警方通過查閱死者的電腦和手機龙誊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讯柔,“玉大人抡蛙,你說我怎么就攤上這事魂迄。” “怎么了捣炬?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵湿酸,是天一觀的道長婿屹。 經常有香客問我推溃,道長,這世上最難降的妖魔是什么铁坎? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任硬萍,我火速辦了婚禮扩所,結果婚禮上朴乖,老公的妹妹穿的比我還像新娘。我一直安慰自己买羞,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布魁兼。 她就那樣靜靜地躺著漠嵌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪儒鹿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天约炎,我揣著相機與錄音,去河邊找鬼圾浅。 笑死,一個胖子當著我的面吹牛喷鸽,可吹牛的內容都是我干的。 我是一名探鬼主播做祝,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼鸡岗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了轩性?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤捌刮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后绅作,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡俄认,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年洪乍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壳澳。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖萎津,靈堂內的尸體忽然破棺而出抹镊,到底是詐尸還是另有隱情锉屈,我是刑警寧澤垮耳,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布遂黍,位于F島的核電站俊嗽,受9級特大地震影響,放射性物質發(fā)生泄漏绍豁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一唬党、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧驶拱,春花似錦、人聲如沸蓝纲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锹漱。三九已至,卻和暖如春哥牍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嗅辣。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留愿题,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓潘酗,卻偏偏與公主長得像外永,于是被迫代替她去往敵國和親崎脉。 傳聞我的和親對象是個殘疾皇子伯顶,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容