Android Xfermode 學習筆記

来源:http://www.cnblogs.com/goagent/archive/2016/03/27/5326438.html
-Advertisement-
Play Games

一、概述 Xfermode全名transfer-mode,其作用是實現兩張圖疊加時的混合效果。 網上流傳的關於Xfermode最出名的圖來源於AndroidSDK的samples中,名叫Xfermodes.java,效果如下: [轉載請保留本文地址:http://www.cnblogs.com/go ...


一、概述

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] 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <style> 5 div 6 { 7 width:100px; 8 height:100px; 9 background:yellow; 10 transition:width 2s; 11 -moz-transition ...
  • 上文《詳解Javascript的繼承實現》介紹了一個通用的繼承庫,基於該庫,可以快速構建帶繼承關係和靜態成員的javascript類,好使用也好理解,額外的好處是,如果所有類都用這種庫來構建,還能使代碼在整體上保持一致的風格,便於其它同事閱讀和理解。在寫完該文之後,這兩天時不時都在思考這個庫可能存在... ...
  • 對於H5來說,canvas可以說是它最有特色的一個地方了,有了它之後我們可以隨意的在網頁上畫各種各樣的圖形,做一些小游戲啊什麼的。canvas這個標簽的用法,在網上也有特別多的教程了,這裡就不作介紹了。今天我們就用canvas來做一個小小的時鐘。完整的代碼在這裡https://github.com/ ...
  • × 目錄 [1]首行縮進 [2]水平對齊 [3]字間隔[4]字母間隔[5]文本轉換 [6]文本修飾 前面的話 CSS文本樣式是相對於內容進行的樣式修飾。由於在層疊關係中,內容要高於背景。所以文本樣式相對而言更加重要。有些人對文本和字體樣式之間的不同不太瞭解,簡單地講,文本是內容,而字體則用於顯示這個 ...
  • 將瀏覽器預設的下拉框樣式清除,然後應用上自己的,再附一張向右對齊小箭頭的圖片即可。 IE8/9並不支持 appearance:none CSS屬性,想要支持的話可能需要非常特殊的方法,參考SF: 我們需要為其添加一個父容器,容器是用來覆蓋小箭頭的,然後為select添加一個向右的小偏移或者寬度大於父 ...
  • 首先我要解釋一下標題的意義,日期的簡潔格式展示,之所以簡介,是因為讓人一目瞭然,不需要思考是什麼時候。 在詳細一點就是我們在微信朋友圈中 所看到的時間格式。 例如:剛剛 -幾分鐘前-幾小時前等等。 今天這裡帶來的是一個簡單的類別。 方便實用。 以及簡單的實際應用。 先看看一看類別是什麼樣子的 .h ...
  • 新手瞭解 有不對的地方指點下 首先, 瞭解下什麼是GIT,GIT是一款開元的分散式版本控制工具, 在世界上的所有分散式版本控制工具中,GIT是最簡單,最流行,同時也是最常用的 相比於其他版本的控制工具而言,GIT也有著自己的特點 舉個例子,GIT與集中式版本控制中的SVN相比來說,區別主要在於以下幾 ...
  • 在現在這個離不開手機的時代,對於手機APP的開發也是一個很大的市場,所以自己也想去探一探手機APP開發,在我們進行Android開發的第一步就是搭建環境,具體怎麼搭建我就不說,這裡記錄一下在搭建環境的過程中遇到的一些問題,來幫助遇到相同問題的童鞋。 1、點擊安卓模擬器就會出現一個錯誤消息:Locat ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...