Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android Xfermode 學習筆記,androidxfermode

Android Xfermode 學習筆記,androidxfermode

編輯:關於android開發

Android Xfermode 學習筆記,androidxfermode


一、概述

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] 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved