Android background tint顏色渲染

該篇文章主要是講Android顏色渲染,首先先來看看PorterDuff,對繪圖非常重要。
PorterDuff的由來:
相信大多數人看到這個ProterDuff單詞很奇怪了吧,這腫麼個意思呢,然後就用有道啊,金山啊開始翻譯,但是翻譯軟件給出的結果肯定還是 ProterDuff或者”未找到”.
這是神馬情況呢?因爲ProterDuff是兩個人名的組合: Tomas Proter和 Tom Duff. 他們是最早在SIGGRAPH上提出圖形混合概念的大神級人物.有興趣的童靴們可以自己查下並深入瞭解,在此不再做過多描述.
利用ProterBuff.Mode我們可以完成任意2D圖像測操作, 比如塗鴉畫板應用中的橡皮擦效果,繪製各種自定義的進度,等等很強大的效果,下面請看效果:
這裏寫圖片描述
從上面我們可以看到PorterDuff.Mode爲枚舉類,一共有16個枚舉值:
1.PorterDuff.Mode.CLEAR
所繪製不會提交到畫布上。
2.PorterDuff.Mode.SRC
顯示上層繪製圖片
3.PorterDuff.Mode.DST
顯示下層繪製圖片
4.PorterDuff.Mode.SRC_OVER
正常繪製顯示,上下層繪製疊蓋。
5.PorterDuff.Mode.DST_OVER
上下層都顯示。下層居上顯示。
6.PorterDuff.Mode.SRC_IN
取兩層繪製交集。顯示上層。
7.PorterDuff.Mode.DST_IN
取兩層繪製交集。顯示下層。
8.PorterDuff.Mode.SRC_OUT
取上層繪製非交集部分。
9.PorterDuff.Mode.DST_OUT
取下層繪製非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下層非交集部分與上層交集部分
11.PorterDuff.Mode.DST_ATOP
取上層非交集部分與下層交集部分
12.PorterDuff.Mode.XOR
異或:去除兩圖層交集部分
13.PorterDuff.Mode.DARKEN
取兩圖層全部區域,交集部分顏色加深
14.PorterDuff.Mode.LIGHTEN
取兩圖層全部,點亮交集部分顏色
15.PorterDuff.Mode.MULTIPLY
取兩圖層交集部分疊加後顏色
16.PorterDuff.Mode.SCREEN
取兩圖層全部區域,交集部分變爲透明色

還有另外兩個
17.PorterDuff.Mode.ADD
18.PorterDuff.Mode.OVERLAY

那什麼是Tint呢?
我們可以通過xml中的屬性android:backgroundTint和android:backgroundTintMode來設置,android:backgroundTintMode這個屬性傳的值就是剛剛上面那些PorterDuff.Mode中的值,效果的話上面的圖也展示了。android:backgroundTint的話就是傳color的值。

那麼android:background和android:backgroundTint有什麼區別呢?
如果設置了android:background,那麼控件的背景顏色就會直接修改。
如果設置了android:backgroundTint,那麼就會將設置的顏色和原來的背景進行一個疊加的過程,至於如何疊加,就是上面的mode。
看一個例子:

<Button
    android:id="@+id/button_1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/button_states"
    android:text="text" />
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item 
        android:state_pressed="true" 
        android:drawable="@drawable/button_pressed" />
    <item 
        android:state_pressed="false" 
        android:drawable="@drawable/button_normal" />
</selector>

這是button正常顯示的樣子:
這裏寫圖片描述
爲button設置tint:

Button b = (Button)findViewById(R.id.button_1);
int tint = Color.parseColor("cyan");
b .getBackground().setColorFilter(tint, Mode.DARKEN);

這裏寫圖片描述
看到了麼,效果是疊加,而不是直接覆蓋。使用tint可以保留原來的陰影波紋等效果。

還有個方法是setBackgroundTintList(ColorStateList)和setBackgroundTintMode(PorterDuff.Mode)方法。
如果控件沒有背景,設置backgroundTint無效。

Button b = (Button) findViewById(R.id.button_1);
b.setText(modes[i - 1]);
int[] colors = new int[]{0xfff8513f, 0xffe43d2b};
int[][] states = new int[2][];
states[0] = new int[]{android.R.attr.state_pressed};
states[1] = new int[]{android.R.attr.state_enabled};
b.setBackgroundTintList(new ColorStateList(states, colors));
b.setBackgroundTintMode(mode[i - 1]);

效果與上面類似,但是多了狀態變換的顏色變換。

但是如果控件狀態轉換的時候,顏色不換,則可以採用

b .getBackground().setColorFilter(tint, Mode.DARKEN);

因爲這個API在21版本上纔有,對於低版本調用的話,可以調用以下方法:

ViewCompat.setBackgroundTintList(b, new ColorStateList(states, colors));
ViewCompat.setBackgroundTintMode(b, Mode.DARKEN);

但是現在普通的button,去調用setBackgroundTint和setBackgroundTintMode無效,沒有什麼效果。解決這種問題,可以通過使用android.support.v7.widget.AppCompatButton,然後調用setSupportBackgroundTintList以及setSupportBackgroundTintMode方法。

發佈了110 篇原創文章 · 獲贊 28 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章