編輯:關於android開發
一、概述
Xfermode全名transfer-mode,其作用是實現兩張圖疊加時的混合效果。
網上流傳的關於Xfermode最出名的圖來源於AndroidSDK的samples中,名叫Xfermodes.java,效果如下:

[轉載請保留本文地址:http://www.cnblogs.com/goagent/p/5326438.html]
二、體驗
提煉出Xfermodes.java中的核心代碼,自己寫了個簡單粗暴的demo試試水:
1 public class ImageViewXfermode extends ImageView {
2 public ImageViewXfermode(Context context) {
3 super(context);
4 init();
5 }
6
7 public ImageViewXfermode(Context context, AttributeSet attrs) {
8 super(context, attrs);
9 init();
10 }
11
12 public ImageViewXfermode(Context context, AttributeSet attrs, int defStyle) {
13 super(context, attrs, defStyle);
14 init();
15 }
16
17 private void init() {
18 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
19 setLayerType(View.LAYER_TYPE_SOFTWARE, null);
20 }
21 }
22
23 @Override
24 protected void onDraw(Canvas canvas) {
25 int defaultWidth = dip2px(85); //xml裡view的寬度是85dp
26 int defaultdHeight = dip2px(85); //xml裡view的高度是85dp
27
28 if (canvas.getHeight() == defaultWidth && canvas.getHeight() == defaultdHeight) {
29 //拿到黃色圓形的bitmap
30 Bitmap bitcircle = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
31 Canvas canvascicle = new Canvas(bitcircle);
32 Paint paintcicle = new Paint(Paint.ANTI_ALIAS_FLAG);
33 paintcicle.setColor(0xFFFFCC44);
34 canvascicle.drawCircle(dip2px(30), dip2px(30), dip2px(25), paintcicle);
35
36 //拿到藍色矩形的bitmap
37 Bitmap bitrect = Bitmap.createBitmap(defaultWidth, defaultdHeight, Config.ARGB_8888);
38 Canvas canvasrect = new Canvas(bitrect);
39 Paint paintrect = new Paint(Paint.ANTI_ALIAS_FLAG);
40 paintrect.setColor(0xFF66AAFF);
41 canvasrect.drawRect(dip2px(30), dip2px(30), dip2px(80), dip2px(80), paintrect);
42
43 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
44 Xfermode xfermode = new PorterDuffXfermode(Mode.LIGHTEN);
45
46 //采用saveLayer,讓後續canvas的繪制在自動創建的bitmap上
47 int cnt = canvas.saveLayer(0, 0, defaultWidth, defaultdHeight, null, Canvas.ALL_SAVE_FLAG);
48 //先畫圓形,圓形是dest
49 canvas.drawBitmap(bitcircle, 0, 0, paint);
50 paint.setXfermode(xfermode);
51 //後畫矩形,矩形是src
52 canvas.drawBitmap(bitrect, 0, 0, paint);
53 paint.setXfermode(null);
54 canvas.restoreToCount(cnt);
55 } else {
56 super.onDraw(canvas);
57 }
58 }
59
60 private int dip2px(float dip) {
61 float scale = getResources().getDisplayMetrics().density;
62 return (int)(dip * scale + 0.5f);
63 }
64 }
效果如下:

介紹一下幾個關鍵點:
1、關於src和dest
先繪制到canvas上的是dest,後繪制的是src
2、關於硬件加速
在sdkversion>=11時,需要關閉硬件加速(第19行),否則 Mode.CLEAR 、 Mode.DARKEN 、 Mode.LIGHTEN 三種模式下繪制效果不正常
3、saveLayer的作用
Canvas.saveLayer在Canvas.save的基礎上,額外自動分配了一個bitmap,使得saveLayer之後的所有繪制都在這個新分配的bitmap上完成。
如果把saveLayer去掉呢?效果就是藍色矩形跟黃色圓形和灰色背景都進行了 Mode.LIGHTEN 操作:

4、如果不saveLayer
有一種變通的方法,在dest對應bitmap的canvas上繪制src對應的bitmap,這樣的目的與saveLayer是一致的,不在當前canvas上直接繪圖:
1 @Override
2 protected void onDraw(Canvas canvas) {
3 int defaultWidth = dip2px(85); //xml裡view的寬度是85dp
4 int defaultdHeight = dip2px(85); //xml裡view的高度是85dp
5
6 if (canvas.getHeight() == defaultWidth && canvas.getHeight() == defaultdHeight) {
7 //拿到黃色圓形的bitmap
8 Bitmap bitcircle = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
9 Canvas canvascicle = new Canvas(bitcircle);
10 Paint paintcicle = new Paint(Paint.ANTI_ALIAS_FLAG);
11 paintcicle.setColor(0xFFFFCC44);
12 canvascicle.drawCircle(dip2px(30), dip2px(30), dip2px(25), paintcicle);
13
14 //拿到藍色矩形的bitmap
15 Bitmap bitrect = Bitmap.createBitmap(defaultWidth, defaultdHeight, Config.ARGB_8888);
16 Canvas canvasrect = new Canvas(bitrect);
17 Paint paintrect = new Paint(Paint.ANTI_ALIAS_FLAG);
18 paintrect.setColor(0xFF66AAFF);
19 canvasrect.drawRect(dip2px(30), dip2px(30), dip2px(80), dip2px(80), paintrect);
20
21 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
22 Xfermode xfermode = new PorterDuffXfermode(Mode.LIGHTEN);
23
24 //設置setXfermode
25 paint.setXfermode(xfermode);
26 //在圓形的canvas上畫矩形,先畫圓形,圓形是dest,後畫矩形,矩形是src
27 canvascicle.drawBitmap(bitrect, 0, 0, paint);
28 paint.setXfermode(null);
29 //將圓形canvas上畫出來的結果繪制到canvas上
30 canvas.drawBitmap(bitcircle, 0.0f, 0.0f, paint);
31 } else {
32 super.onDraw(canvas);
33 }
34 }
[轉載請保留本文地址:http://www.cnblogs.com/goagent/p/5326438.html]
三、更多玩法——圓形ImageView
利用Xfermode的特性也可以做出圓形的ImageView來。先畫原圖,再畫圓形,采用 Mode.DST_IN 即可:
1 @Override
2 protected void onDraw(Canvas canvas) {
3 int defaultWidth = dip2px(85); //xml裡view的寬度是85dp
4 int defaultdHeight = dip2px(85); //xml裡view的高度是85dp
5 Drawable drawable = getDrawable();
6
7 if (canvas.getHeight() == defaultWidth && canvas.getHeight() == defaultdHeight && drawable instanceof BitmapDrawable) {
8 //setBackgroundColor(Color.TRANSPARENT);
9 //拿到原圖的bitmap
10 Bitmap bitimg = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
11 Canvas canvasimg = new Canvas(bitimg);
12 Matrix matrix = new Matrix();
13 matrix.setScale(defaultWidth * 1.0f / drawable.getIntrinsicWidth(), defaultdHeight * 1.0f / drawable.getIntrinsicHeight());
14 Paint paintimg = new Paint(Paint.ANTI_ALIAS_FLAG);
15 canvasimg.drawBitmap(((BitmapDrawable)drawable).getBitmap(), matrix, paintimg);
16
17 //拿到圓形的bitmap
18 Bitmap bitcircle = Bitmap.createBitmap(defaultWidth, defaultdHeight, Config.ARGB_8888);
19 Canvas canvascircle = new Canvas(bitcircle);
20 Paint paintcircle = new Paint(Paint.ANTI_ALIAS_FLAG);
21 paintcircle.setColor(0xFF66AAFF);
22 canvascircle.drawCircle(dip2px(85 / 2.0f), dip2px(85 / 2.0f), dip2px(85 / 2.0f), paintcircle);
23
24 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
25 Xfermode xfermode = new PorterDuffXfermode(Mode.DST_IN);
26
27 //采用saveLayer,讓後續canvas的繪制在自動創建的bitmap上
28 int cnt = canvas.saveLayer(0, 0, defaultWidth, defaultdHeight, null, Canvas.ALL_SAVE_FLAG);
29 //先畫原圖,原圖是dest
30 canvas.drawBitmap(bitimg, 0, 0, paint);
31 paint.setXfermode(xfermode);
32 //後畫圓形,圓形是src
33 canvas.drawBitmap(bitcircle, 0, 0, paint);
34 paint.setXfermode(null);
35 canvas.restoreToCount(cnt);
36 } else {
37 super.onDraw(canvas);
38 }
39 }
[轉載請保留本文地址:http://www.cnblogs.com/goagent/p/5326438.html]
美女的秘密應用項目源碼,秘密項目源碼
美女的秘密應用項目源碼,秘密項目源碼這是一個不錯的Android美女的秘密項目。 源碼下載:http://code.662p.com/list/11_1.html<
Android 手機衛士--自定義組合控件構件布局結構,android構件
Android 手機衛士--自定義組合控件構件布局結構,android構件由於設置中心條目中的布局都很類似,所以可以考慮使用自定義組合控件來簡化實現 本文地址:http
AndroidAnnnotations注入框架使用之第三方框架集成RoboGuice(十三)
AndroidAnnnotations注入框架使用之第三方框架集成RoboGuice(十三) (一).前言: 前面我們已經對於AndroidA
Android多分辨率適配實踐【1】使用字體圖標(內含兩枚神器),android兩枚
Android多分辨率適配實踐【1】使用字體圖標(內含兩枚神器),android兩枚目錄 Android多分辨率適配實踐【0】基礎適配篇(撰寫中)Android多分辨率適