Android控件ProgressBar--自定義進(jìn)度條及源碼分析

這里用SeekBar做演示忍弛,SeekBar繼承自ProgressBar,擁有其一切特性,并且其支持拖動以及DPAD左右鍵的進(jìn)退栓拜。一起學(xué)習(xí)吧惠昔!

一、自定義SeekBar進(jìn)度條樣式

原生SeekBar效果如圖


原生SeekBar樣式

1. 自定義SeekBar進(jìn)度條樣式一


效果:顏色隨著進(jìn)度從#00ff00#0000ff漸變
布局文件

<SeekBar
        android:id="@+id/seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxHeight="6dp"
        android:progressDrawable="@drawable/progress_horizontal"
        android:thumb="@drawable/seekbar_thumb" />

progressDrawable用來定義與進(jìn)度有關(guān)的圖片。
res/drawable/progress_horizontal.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!--作為整體背景圖片-->
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="5dp" />
            <solid android:color="#d1d0d0" />
        </shape>
    </item>
    
    <!--@android:id/secondaryProgress   第二進(jìn)度和progress是類似的诫给,有需要可以定義-->
    <!--進(jìn)度狀態(tài)的背景-->
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="5dp" />
                <gradient
                    android:endColor="#0000ff"
                    android:startColor="#00ff00" />
            </shape>
        </clip>
    </item>

</layer-list>

thumb的和普通定義一個圖片一樣啦扬,這里就不貼代碼了扑毡。
progressDrawable工作原理

  • ProgressBar通過progressDrawable屬性拿到背景圖,如果該圖片是普通圖片瞄摊,則進(jìn)度和沒有進(jìn)度看起來是一樣的。如果采用LayerDrawable作為背景圖楔壤,就可控制各個item的顯示部分,從而模擬進(jìn)度递瑰,當(dāng)進(jìn)度為0時@android:id/background該item可以完全看到
  • @android:id/progress的item圖片會隨著進(jìn)度的變化而顯示區(qū)域發(fā)生變化隙畜,例如進(jìn)度為1%禾蚕,該item圖也只會顯示1%狂丝,主要原理是<clip>標(biāo)簽,該標(biāo)簽對應(yīng)ClipDrawable,其可以通過level值控制圖片的顯示部分倍试,ProgressBar內(nèi)部會隨著進(jìn)度變化設(shè)置ClipDrawable的level蛋哭,從而實(shí)現(xiàn)進(jìn)度效果。

2. 自定義SeekBar進(jìn)度條樣式二


效果:進(jìn)度部分漸變保持不變躁愿,隨著進(jìn)度拉長
解決思路就是不斷的更換進(jìn)度部分圖片彤钟,不過簡單是進(jìn)度部分可以是同一張圖片跷叉,只需要動態(tài)改變長度即可。
res/drawable/progress_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:height="6dp"
        android:gravity="center_vertical">
        <shape>
            <corners android:radius="5dp" />
            <solid android:color="#d1d0d0" />
        </shape>
    </item>
    <item
        android:width="0px"
        android:height="6dp"
        android:gravity="center_vertical">
        <shape>
            <corners android:radius="5dp" />
            <gradient
                android:endColor="#0000ff"
                android:startColor="#00ff00" />
        </shape>
    </item>
</layer-list>

不需要加id部分梆砸,將其作為一張普通圖片作為進(jìn)度條背景帖世。
實(shí)現(xiàn)思路:LayerDrawable默認(rèn)最后的item顯示在最上層,那么我們可以將第一個item作為進(jìn)度條的整體顏色俊庇,第二個item作為進(jìn)度部分顏色鸡挠。第二個item寬度為0搬男,也象征著進(jìn)度為0,當(dāng)進(jìn)度條進(jìn)度發(fā)生變化時备埃,我們根據(jù)進(jìn)度相對于整個進(jìn)度條的比例計(jì)算出進(jìn)度部分的寬度褐奴,從而調(diào)整第二個item的寬度實(shí)現(xiàn)上圖效果敦冬。

布局文件保持不變,Java代碼更改如下

seekBar = findViewById(R.id.seekbar);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        progressTV.setText(progress + "%");
        refreshProgressBackground(seekBar, progress);
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
});

private void refreshProgressBackground(SeekBar seekBar, int progress) {
    // 1. 得到LayerDrawable
    LayerDrawable layerDrawable = (LayerDrawable) getResources().getDrawable(R.drawable.seekbar_drawable);
    // seekBar顯示寬度
    int avaliableWidth = seekBar.getWidth() - seekBar.getPaddingLeft() - seekBar.getPaddingRight();
    // 進(jìn)度部分寬度
    int progressWidth = (int) (avaliableWidth * progress / (float) seekBar.getMax());
    // 第二個item堪遂,下標(biāo)為1
    layerDrawable.setLayerWidth(1, progressWidth);
    // 2. 重新設(shè)置ProgressDrawable
    seekBar.setProgressDrawable(layerDrawable);
}

注釋1出之所以不直接通過seekBar獲取LayerDrawable溶褪,是因?yàn)樵谧⑨?出的setProgressDrawable方法內(nèi)會判斷Drawable和SeekBar以前所得到的progressDrawable是否相同践险,相同則不做任何操作,故每次需創(chuàng)建新的對象彭则。

二垫言、SeekBar及ProgressBar實(shí)現(xiàn)原理源碼分析

由于時間問題,該部分后續(xù)更新

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚌成,一起剝皮案震驚了整個濱河市担忧,隨后出現(xiàn)的幾起案子坯癣,更是在濱河造成了極大的恐慌,老刑警劉巖惩猫,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拌阴,居然都是意外死亡奶镶,警方通過查閱死者的電腦和手機(jī)厂镇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酌媒,“玉大人迄靠,你說我怎么就攤上這事。” “怎么了茵臭?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵旦委,是天一觀的道長。 經(jīng)常有香客問我摩钙,道長查辩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮萍倡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘阱佛。我一直安慰自己,他們只是感情好翩蘸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著麦萤,像睡著了一般鹿鳖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上壮莹,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天翅帜,我揣著相機(jī)與錄音,去河邊找鬼命满。 笑死涝滴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胶台。 我是一名探鬼主播歼疮,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼韩脏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起铸磅,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤赡矢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后阅仔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吹散,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年八酒,在試婚紗的時候發(fā)現(xiàn)自己被綠了空民。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡羞迷,死狀恐怖界轩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衔瓮,我是刑警寧澤耸棒,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站报辱,受9級特大地震影響与殃,放射性物質(zhì)發(fā)生泄漏单山。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一幅疼、第九天 我趴在偏房一處隱蔽的房頂上張望米奸。 院中可真熱鬧,春花似錦爽篷、人聲如沸悴晰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铡溪。三九已至,卻和暖如春泪喊,著一層夾襖步出監(jiān)牢的瞬間棕硫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工袒啼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哈扮,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓蚓再,卻偏偏與公主長得像滑肉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子摘仅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容