動(dòng)態(tài)改變SeekBar

燈光SeekBar

這個(gè)頁(yè)面主要功能是RecyclerView展示各個(gè)燈光卡片汗洒,選擇色盤(pán)珠漂,亮度調(diào)節(jié),整體算法聯(lián)動(dòng)控制的效果笼才。

1. 色盤(pán)

首先我們來(lái)講解下這個(gè)色盤(pán)吧漱受。這個(gè)頁(yè)面除了亮度算法,就是顏色的控制啦骡送。
想搞出色盤(pán)昂羡,能夠準(zhǔn)確的計(jì)算出色值絮记,需要搞清楚這幾個(gè)屬性:

  • 色調(diào)H:0-360
    從紅色開(kāi)始按逆時(shí)針?lè)较蛴?jì)算,紅色為0°虐先,綠色為120°怨愤,藍(lán)色為240°。它們的補(bǔ)色是:黃色為60°蛹批,青色為180°撰洗,紫色為300°

  • 飽和度S:0%-100%
    飽和度高,顏色則深而艷腐芍。光譜色的白光成分為0差导,飽和度達(dá)到最高。通常取值范圍為0%~100%猪勇,值越大柿汛,顏色越飽和。

  • 明度V:0%-100%
    明度表示顏色明亮的程度埠对,通常取值范圍為0%(黑)到100%(白)络断。

  • 亮度B:0%-100%
    亮度表示顏色明亮的程度,通常取值范圍為0%(黑)到100%(白)项玛。

  • 色溫T:0%-100%
    色溫表示光譜能量分布的指標(biāo)貌笨,色溫高,光譜能量分布于短波的成分略多襟沮,顏色偏藍(lán)锥惋。色溫低,光譜能量分布于長(zhǎng)波的成分略多开伏,顏色偏黃膀跌。

即便理解了這幾個(gè)屬性,是不是也還是一臉懵逼呀固灵?

日常生活中用到的捅伤,像有的燈具只有亮度可以調(diào)節(jié),有的燈具可以調(diào)節(jié)亮度和冷暖色溫巫玻,有的燈具可以調(diào)節(jié)色調(diào)丛忆,飽和度和亮度,功能再多點(diǎn)的燈仍秤,可以調(diào)節(jié)色調(diào)+飽和度+亮度+色溫熄诡。

對(duì)應(yīng)到UI色盤(pán)上的關(guān)系,或許可以讓你更多的理解這幾個(gè)屬性诗力,更清楚的知道怎么去控制這幾個(gè)值凰浮。

從圖上我們可以看出,色盤(pán)由圓形和長(zhǎng)方形2種,各自對(duì)應(yīng)的關(guān)系我已經(jīng)標(biāo)注的比較清楚了袜茧。
圓形相對(duì)與長(zhǎng)方形來(lái)說(shuō)屿良,它需要根據(jù)弧度來(lái)確定色調(diào)H,根據(jù)點(diǎn)的位置和利用勾股定理來(lái)確定飽和度S惫周。
畫(huà)這個(gè)UI圖對(duì)應(yīng)到各個(gè)HSVBT值還比較簡(jiǎn)單尘惧,可以通過(guò)Color來(lái)計(jì)算和轉(zhuǎn)換,比如HSVToColor递递,colorToHSV喷橙,RGBToHSV等,比較繁瑣的是燈具不同登舞,硬件上的值和各自轉(zhuǎn)換算法不同贰逾,下發(fā)到燈具上的顏色亮度也不同,這個(gè)保密就不做介紹了菠秒。

2. 動(dòng)畫(huà)

從最上面的操作錄屏中疙剑,你可以看到,SeekBar亮度調(diào)節(jié)的時(shí)候還有一些動(dòng)畫(huà)践叠,為了讓用戶有圓潤(rùn)的動(dòng)畫(huà)體驗(yàn)言缤,這里使用了彈性動(dòng)畫(huà)。

彈性動(dòng)畫(huà)這里選擇了interpolator插值器的實(shí)現(xiàn)方式禁灼。

public class SpringScaleInterpolator implements Interpolator {
    //彈性因數(shù)
    private float factor;

    public SpringScaleInterpolator(float factor) {
        this.factor = factor;
    }

    @Override
    public float getInterpolation(float input) {
        return (float) (Math.pow(2, -10 * input) * Math.sin((input - factor / 4) * (2 * Math.PI) / factor) + 1);
    }
}

從代碼上看管挟,可能你不清楚彈性因子和代碼里的數(shù)字各自影響的動(dòng)畫(huà)效果是什么樣的,那么就從這個(gè)網(wǎng)站查看效果吧弄捕。

關(guān)于差值器網(wǎng)站

在這個(gè)網(wǎng)站上可以在線看每種interpolator的效果僻孝,從而調(diào)節(jié)數(shù)字來(lái)選擇所需要的interpolator。

factor的值越小守谓,值來(lái)回變化的次數(shù)越多穿铆,對(duì)應(yīng)到具體的動(dòng)畫(huà)就是:factor值越小,view來(lái)回縮放的次數(shù)越多斋荞,平移到指定位置后在指定位置上下或左右擺動(dòng)的次數(shù)也越多

具體的彈性動(dòng)畫(huà)方面荞雏,還有其他的實(shí)現(xiàn)方式,可自行查看譬猫,這里不做詳細(xì)介紹讯檐。

3. seekbar

從錄屏中可以看一下,SeekBar的特點(diǎn)染服,除了動(dòng)畫(huà)效果外,還有圓角處理+顏色動(dòng)態(tài)變換+透明度+色值漸變叨恨。每一個(gè)HSVBT值的變化柳刮,都需要計(jì)算color,來(lái)改變SeekBar和卡片的顏色,同時(shí)計(jì)算整體亮度秉颗。

  • SeekBar固定進(jìn)度條顏色和圓角

SeekBar的進(jìn)度條和滑塊可以通過(guò)設(shè)置progressDrawable與thumb痢毒,這樣設(shè)置會(huì)是固定的,從錄屏上看我們需要的是動(dòng)態(tài)的更改漸變顏色蚕甥,100%的時(shí)候更改圓角哪替。
我們先從progressDrawable和thumb開(kāi)始吧。

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!--定義seekbar滑動(dòng)條的底色-->
    <item android:id="@android:id/background">
        <shape>
            <solid android:color="#39000000" />
        </shape>
    </item>
<!--定義seekbar滑動(dòng)條第二背景顏色-->
<!--    <item android:id="@android:id/secondaryProgress">-->
<!--        <clip>-->
<!--            <shape>-->
<!--                <corners android:radius="5dp" />-->
<!--                <gradient-->
<!--                    android:startColor="#80ffd300"-->
<!--                    android:centerColor="#80ffb600"-->
<!--                    android:centerY="0.75"-->
<!--                    android:endColor="#a0ffcb00"-->
<!--                    android:angle="270"/>-->
<!--            </shape>-->
<!--        </clip>-->
<!--    </item>-->
    <!--定義seekbar滑動(dòng)條進(jìn)度顏色-->
    <item android:id="@android:id/progress">
        <scale android:scaleWidth="100%" >
            <shape android:shape="rectangle">
                <gradient
                    android:angle="180"
                    android:endColor="@color/transparent"
                    android:startColor="@color/white" />
                <corners android:bottomRightRadius="7dp" android:topRightRadius="7dp"/>
            </shape>
        </scale>
    </item>
</layer-list>

UI圖上沒(méi)有第二背景菇怀,這里就把它添加上并寫(xiě)了注釋凭舶,有個(gè)細(xì)節(jié)的點(diǎn)需要了解下,就是scale與clip的區(qū)別爱沟。
先使用clip對(duì)比看一下UI:

<clip>
    <shape android:shape="rectangle">
        <gradient
              android:angle="180"
              android:endColor="@color/transparent"
              android:startColor="@color/white" />
        <corners android:bottomRightRadius="@dimen/dp_7" android:topRightRadius="@dimen/dp_7"/>
    </shape>
</clip>

展示如下:

使用clip從截圖來(lái)看帅霜,沒(méi)有了圓角。

  • scale能夠?qū)rawable進(jìn)行縮放呼伸,通過(guò)其scaleWidth和scaleHeight屬性身冀,可設(shè)置drawable縮放的比例。
  • 使用clip標(biāo)簽可實(shí)現(xiàn)對(duì)drawable的裁剪括享,用法與scale類似搂根。通過(guò)在代碼中調(diào)用getBackground()獲取Drawable后,通過(guò)setLevel(int level)方法铃辖,可控制裁剪的程度兄墅。

滑塊部分可自定查看文末的參考文檔,在xml里設(shè)置android:thumb="@drawable/seekbar_thumb"

  • SeekBar動(dòng)態(tài)設(shè)置顏色和圓角

我們可以使用getProgressDrawable得到進(jìn)度背景LayerDrawable澳叉,它包含多個(gè)層次隙咸,對(duì)應(yīng)上面layer-list設(shè)置的3個(gè)層次,可以通過(guò)Id獲取各自的Drawable成洗。

//獲取seerbar層次drawable對(duì)象
LayerDrawable layerDrawable = (LayerDrawable) seekBar.getProgressDrawable();
// 有多少個(gè)層次(最多三個(gè))
int layers = layerDrawable.getNumberOfLayers();
Drawable[] drawables = new Drawable[layers];
for (int i = 0; i < layers; i++) {
    switch (layerDrawable.getId(i)) {
        // seekbar背景
        case android.R.id.background:
            drawables[i] = layerDrawable.getDrawable(0);
            break;
        // 拖動(dòng)條第一進(jìn)度
        case android.R.id.progress:
            //動(dòng)態(tài)設(shè)顏色值
            drawables[i] = new PaintDrawable(progressColor);
         drawables[i].setBounds(layerDrawable.getDrawable(0).getBounds());
            break;
        ...
    }
}
seekBar.setProgressDrawable(new LayerDrawable(drawables));
seekBar.invalidate();

由于我的UI只progress顏色在變化五督,可以直接取LayerDrawable的Drawable第1個(gè)Drawable,轉(zhuǎn)變?yōu)镚radientDrawable瓶殃,進(jìn)行設(shè)置漸變顏色和圓角

LayerDrawable layerDrawable = (LayerDrawable) seekBar.getProgressDrawable();
GradientDrawable gradientDrawable = (GradientDrawable)((ScaleDrawable)layerDrawable.getDrawable(1)).getDrawable();
//設(shè)置漸變顏色
int[] gradientColors = {mContext.getResources().getColor(R.color.white), mContext.getResources().getColor(R.color.transparent)};
gradientColors[1] = newColor;
gradientDrawable.setColors(gradientColors);

//設(shè)置圓角
float gradientRadius = mContext.getResources().getDimension((seekBar.getProgress() == 100) ? 0dp : 7dp);
float[] radius = {0f, 0f, gradientRadius, gradientRadius, gradientRadius, gradientRadius, 0f, 0f};
gradientDrawable.setCornerRadii(radius);

seekBar.setProgressDrawable(layerDrawable);
seekBar.invalidate();

這里需要了解下充包,用shape標(biāo)簽定義的xml,最終都是轉(zhuǎn)化為GradientDrawable對(duì)象遥椿,而不是ShapeDrawable, 也不是類型對(duì)應(yīng)的 OvalShape基矮,RoundRectShape等。
GradientDrawable可以動(dòng)態(tài)設(shè)置跟xml文件中android:shape的值一一對(duì)應(yīng)的類型冠场。

從UI上看家浇,seekBar設(shè)置過(guò)顏色的同時(shí),卡片的背景也需要設(shè)置碴裙,這里通過(guò)setColorFilter設(shè)置

Drawable itemBackground = itemBgView.getBackground();
itemBackground.setColorFilter(newColor, PorterDuff.Mode.SRC);

這里也有需要了解的點(diǎn)钢悲,PorterDuff.Mode.SRC点额,不做多介紹,詳細(xì)的可以查看文末參考文檔

從圖上可以形象地說(shuō)明了運(yùn)用PorterDuff.Mode進(jìn)行圖像合成的作用莺琳,兩個(gè)圖形一圓一方通過(guò)一定的計(jì)算產(chǎn)生了不同的合成效果还棱,我們?cè)趯?shí)際工作中需要做圖片處理時(shí)可以參考這張圖的示意快速地選擇合適的Mode。

4. 緩存問(wèn)題

單個(gè)使用SeekBar是沒(méi)問(wèn)題的惭等,放在了RecyclerView里珍手,動(dòng)態(tài)的設(shè)置顏色發(fā)現(xiàn)是有問(wèn)題的,他們相互影響顯示同一個(gè)顏色辞做,最終翻看源碼琳要,發(fā)現(xiàn)是Drawable資源緩存的問(wèn)題。詳細(xì)的源碼可以查看ResourcesImpl里loadDrawable部分凭豪。
避免這個(gè)問(wèn)題焙蹭,可以通過(guò)setProgressDrawable設(shè)置SeekBar的LayerDrawable。

int progressDrawableRes = R.drawable.seekbar_progress_drawable;
LayerDrawable layerDrawable = (LayerDrawable)ContextCompat.getDrawable(mContext, progressDrawableRes).getConstantState().newDrawable().mutate();
seekBar.setProgressDrawable(layerDrawable);

5. notifyDataSetChanged問(wèn)題

這里有個(gè)問(wèn)題需要注意嫂伞,從最上面的錄屏看孔厉,滑動(dòng)每一個(gè)SeekBar,動(dòng)畫(huà)執(zhí)行的同時(shí)都需要?jiǎng)討B(tài)的更新數(shù)據(jù)帖努,實(shí)時(shí)的更新整體亮度撰豺,notifyDataSetChanged的時(shí)機(jī)需要跟動(dòng)畫(huà)結(jié)合,因?yàn)镽ecyclerView的緩存機(jī)制拼余,可能動(dòng)畫(huà)執(zhí)行一半污桦,SeekBar對(duì)象就變了。

就這樣吧匙监,算是總結(jié)記錄下最近搞的UI部分吧凡橱。

參考文檔:
Android drawable資源分析
動(dòng)態(tài)改變SeekBar進(jìn)度條顏色與滑塊顏色
GradientDrawable(shape標(biāo)簽定義) 靜態(tài)使用和動(dòng)態(tài)使用(圓角,漸變實(shí)現(xiàn))
各個(gè)擊破搞明白PorterDuff.Mode

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末亭姥,一起剝皮案震驚了整個(gè)濱河市稼钩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌达罗,老刑警劉巖坝撑,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異粮揉,居然都是意外死亡巡李,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)扶认,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)侨拦,“玉大人,你說(shuō)我怎么就攤上這事蝠引⊙舻” “怎么了蛀柴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵螃概,是天一觀的道長(zhǎng)矫夯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)吊洼,這世上最難降的妖魔是什么训貌? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮冒窍,結(jié)果婚禮上递沪,老公的妹妹穿的比我還像新娘。我一直安慰自己综液,他們只是感情好款慨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著谬莹,像睡著了一般檩奠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上附帽,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天埠戳,我揣著相機(jī)與錄音,去河邊找鬼蕉扮。 笑死整胃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的喳钟。 我是一名探鬼主播屁使,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奔则!你這毒婦竟也來(lái)了蛮寂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤应狱,失蹤者是張志新(化名)和其女友劉穎共郭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體疾呻,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡除嘹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了岸蜗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尉咕。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖璃岳,靈堂內(nèi)的尸體忽然破棺而出年缎,到底是詐尸還是另有隱情悔捶,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布单芜,位于F島的核電站蜕该,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏洲鸠。R本人自食惡果不足惜堂淡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望扒腕。 院中可真熱鬧绢淀,春花似錦、人聲如沸瘾腰。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蹋盆。三九已至费薄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怪嫌,已是汗流浹背义锥。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岩灭,地道東北人拌倍。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像噪径,于是被迫代替她去往敵國(guó)和親柱恤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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