PorterDuffColorFilter 在項目中的基本使用
有時候標題欄會浮在內容之上,而內容會有顏色的變化,這時候就要求標題欄能夠變化透明度,標題欄中的圖片能夠變化顏色。看下效果,如下圖:
video.mp4_1488200822.gif
描述
當界面往下劃的時候,我們需要做的是
- 將標題欄是從全透明往全不透明轉變
- 將標題欄中的圖片從白色往主題色轉變
當界面往上時,就反過來轉變界面。
編寫步驟
我們的demo的布局是標題欄在recyclerView的上方,布局如下
我們只需要3個步驟:
- 監聽recyclerView的滑動
- 滑動時計算出位移的百分比
- 根據百分比來操作標題欄背景和圖片
準備工作
在Activity的onCreate里初始化下視圖,獲取view對象,獲取標題欄的背景圖,圖片的drawble對象等
public class MainActivity extends AppCompatActivity {
Drawable headBg ;
Drawable iv1Drawable ;
Drawable iv2Drawable ;
RecyclerView rv;
RelativeLayout rlHead;
private int scrollY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 初始化工作
*/
rv = (RecyclerView) findViewById(R.id.rv);
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(new SimpleAdapter());
rlHead = (RelativeLayout) findViewById(R.id.rl_head);
headBg = rlHead.getBackground().mutate();//獲取head的背景drawable
iv1Drawable = ((ImageView)findViewById(R.id.iv1)).getDrawable().mutate();//獲取圖片的drawable
iv2Drawable = ((ImageView)findViewById(R.id.iv2)).getDrawable().mutate();//獲取圖片的drawable
}
}
重點說明下mutate這個方法。一開始我修改標題欄的透明度時沒有調用mutate方法,導致所有界面的標題欄都透明度都改變了。
Drawable mutate ()
Make this drawable mutable. This operation cannot be reversed. A mutable drawable is guaranteed to not share its state with any other drawable. This is especially useful when you need to modify properties of drawables loaded from resources. By default, all drawables instances loaded from the same resource share a common state; if you modify the state of one instance, all the other instances will receive the same modification. Calling this method on a mutable Drawable will have no effect.
大意就是使當前這個drawable變為易變的,一個易變的drawable被授權不去與其他的drawable共享狀態。從資源載入的所有drawble都是共享一個狀態實例,只要有一個修改了,其他的使用到該drawable的實例也會被修改。調用了這個方法后我們對drawable的修改就不會影響到其他實例了。
監聽recyclerView的滑動
然后對RecyclerView設置滑動監聽
//給recyclerView一個滾動監聽
rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
//我們這里是豎向滑動,只需要關注dy即可
//dy是每次滑動事件觸發后,跟上次y位置的差值
}
});
計算位移百分比
/**
* @param dy
* @return 0~1 ,滑動距離越大,值越大
*/
private float calcFraction(int dy){
//這里的300是圖片的高度,圖片滾完后就是100%
float imgHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 300, getResources().getDisplayMetrics());
float toolbarHeight = rlHead.getHeight();
float maxHeight = imgHeight - toolbarHeight; //圖片從頭到尾移動的距離
scrollY += dy; //dy是這次移動的距離,每次移動的距離加起來就是總移動的距離,dy是有正有負的.scrollY是Activiy的成員對象
if (scrollY >= maxHeight) {
return 1.0f;
} else if (scrollY <= 0) {
return 0f;
} else {
return scrollY/maxHeight;
}
}
根據百分比來操作標題欄背景和圖片
private void setUI(float fraction){
//背景只需要設置透明度,255是全不透明
headBg.setAlpha((int) (fraction*255)); //這個headBg是標題欄
//This evaluator can be used to perform type interpolation between integer values that represent ARGB colors.
//這個求值器用來執行計算用整形表示的顏色的差值
ArgbEvaluator argbEvaluator = new ArgbEvaluator();
int startColor = ActivityCompat.getColor(MainActivity.this,R.color.colorPrimary);
int endColor = Color.WHITE;
//根據fraction計算出開始和結束中間的色值
int calcColor = (int) argbEvaluator.evaluate(fraction, startColor, endColor);
ColorFilter colorFilter = new PorterDuffColorFilter(calcColor, PorterDuff.Mode.SRC_IN);
//應用顏色過濾器
iv1Drawable.setColorFilter(colorFilter);
iv2Drawable.setColorFilter(colorFilter);
}
argbEvaluator是用來計算開始顏色和結束顏色的中間顏色的
ColorFilter是對Drawable設置一個色彩過濾器。這是一個抽象類不能直接使用,他有三個子類:ColorMatrixColorFilter, LightingColorFilter, PorterDuffColorFilter 。我們先看下描述
-
ColorMatrixColorFilter 一個通過4*5的顏色矩陣來改變顏色的顏色過濾器
A color filter that transforms colors through a 4x5 color matrix. This filter can be used to change the saturation of pixels, convert from YUV to RGB, etc.
-
LightingColorFilter 一個可以模擬簡單的燈光效果的顏色過濾器
A color filter that can be used to simulate simple lighting effects. A LightingColorFilter is defined by two parameters, one used to multiply the source color (called colorMultiply) and one used to add to the source color (called colorAdd). The alpha channel is left untouched by this color filter. Given a source color RGB, the resulting R'G'B' color is computed thusly:
-
PorterDuffColorFilter 一個可以使用單個顏色和指定Porter-Duff模式來對源像素進行染色顏色過濾器
A color filter that can be used to tint the source pixels using a single color and a specific Porter-Duff composite mode.
我們就是需要根據位移百分比來對drawable進行顏色變化,就選用PorterDuffColorFilter(為啥說的這么簡單?因為ColorMatrixColorFilter,LightingColorFilter我看的有點懵逼)
Porter-Duff模式
說明文檔 ,這個沒啥好的中文翻譯,我看到一句:Porter-Duff 操作是 1 組 12 項用于描述數字圖像合成的基本手法。用人話講就是:2張圖要放在一張畫板上,這兩張圖需要融合在一起,融合的方法有12個,他們統稱Porter-Duff。具體的融合方法請仔細看下圖
20150416143342583.jpg
我們需要保持原來圖片的形狀,而切換圖片的顏色,選擇PorterDuff.Mode.SRC_IN就可以了,如果理解不了,自己按照圖片多跑幾個模式就知道了。
最后將colorFilter應用到對應的drawable上.圖片顏色的變換就完成啦
來自:http://www.jianshu.com/p/b974a2c88cd9