Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中Xfermode簡單用法

Android中Xfermode簡單用法

編輯:關於Android編程

首先在寫這篇博客的時候,需要說明我是參考了那篇博文給我的靈感:
詳解Paint的setXfermode(Xfermode xfermode)
其次呢,在寫這篇博文的時候呢也避免不了抱怨啊。網上其他的關於Xfermode介紹的大部分都是google官方文檔中屬性的含義,都很雷同估計都是翻譯過來的
title=我想說的是就不能有點原創嗎?

so,我決定寫這篇文章:

一是抒發我心中的糾結; 二是抒發這麼多天下文章一大抄就是沒有自己出的文章; 三是抄就抄吧,也要加入自己的感悟把;
四是記錄一下,以免以後忘記;

另外呢,之前我准備參考源碼來寫這篇文章的,但是我下載之後沒有下載到,android5.1下載的samples裡面沒有找到apidemo,不知道怎麼回事,如果有童鞋知道是怎麼回事的,可以和我說說,並且下載下載android5.1的sdk速度飛速啊,但是5.0之後的sdk基本上無響應,下載不了。

下面進入正題吧:
不免俗套的貼上google官方ApiDemo中Graphics中Xfermode截圖:
這裡寫圖片描述

糾結了2天終於弄出來的

這裡寫圖片描述

最令人氣憤是你看著其他人博客然後想做google官方屬性的出的效果,但是愣是沒有做出來效果,我這暴脾氣,非要弄出來。就是比別人糾結。
title=於是乎有了這篇博文。

有可能是我大腦不行,給出大伙看看其他博文的寫法:
他們都是 XxxView extends ImageView然後寫的,但是關鍵點都沒有介紹出來。我呢下面會給大家介紹最簡單直接的做法,為了方便大伙看明白,簡單有效才是王道!!

首先我聲明啊,不是惡意攻擊和灌水

,只是給大伙對比下,其實我們只需要簡簡單單的怎麼用而不是把全套寫法代碼都貼出來。點到即止,同時也要讓大伙知道怎麼用。

 
此處省略百度一大堆文章,全是代碼根本不知道他們要說的主要思想是什麼……..,不是灌水不是攻擊只是給大伙借鑒

下面真正是正文了啊:大伙注意了。
對於官方文檔的xfermode我們只是看到兩個類似層的圖片
其實和photoshop中的圖層一樣;
一個是原始圖層,另一個是遮罩層
我把整個View的畫布設置為綠色了,為了方便大家觀看效果

canvas.drawColor(Color.GREEN);//畫布設為綠色

先上效果圖吧,嘿嘿蒼老師的頭像。

蒼老師,哈哈

看完正確運行出來的效果,那麼給大家看看錯誤運行出來的效果:
是我的蒼老師,也是大家的蒼老師
蒼老師出錯了

這個是為什麼呢title=
最後參照文章開頭的鏈接給大伙看的必須要設置:

//將繪制操作保存到新的圖層(離屏緩存)
canvas.saveLayer(0,0,300,300, null,Canvas.ALL_SAVE_FLAG);
方法:
public int saveLayer(float left, float top, float right, float bottom, Paint paint, int saveFlags)

大伙不要小看這個方法,我們必須設置將繪制操作保存到新的圖層,不然就會出現蒼老師頭像顯示不正常的情況
當然最後還要還原畫布

// 還原畫布
canvas.restoreToCount(sc);

canvas顧名思義是畫布。所有的繪制操作都發生在這張畫布上,當然當我們要使用多個圖片疊加等的情況我們就要使用“層”了,就如百度地圖或是高德地圖,他們在地圖上面添加新的事物,如線路,興趣點的時候都是用到了層Layer。
當然Canvas給我們提供了層支持;這些Layer是按照棧結構來管理的,後進先出的順序顯示;
當Layer入棧的時候,那麼後續的drawXXXX操作都發生在這個Layer層上面。而Layer退棧時,就會把本層繪制的圖像“繪制”到上層或是Canvas上,在復制Layer到Canvas上時,可以指定Layer的透明度(Layer),這是在創建Layer時指定的:
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags)
我們這篇就不說明saveLayerAplha了。大伙可以自己使用

那麼說這麼多,有人看博文肯定說代碼呢,稍等,客官馬上就來咯:
當然Xfermode網上很多文章都寫了相關屬性介紹的含義,當然我做這個的時候是按照官方給出圖片做的效果。意思呢,可以意會。如果我說了,大伙又迷糊了。哈哈哈哈,這也是我的風格。

那麼我所有的操作都在onDraw()函數體裡面寫了啊。至於性能方面不是我這篇文章所討論的。可以不用在onDraw裡面new對象操作,可以提高性能啥的。
當然自定義view避免不了,先測量下啦。為了簡單直接這樣:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width=MeasureSpec.getSize(widthMeasureSpec);
int height=MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width,height);
}

最後貼上onDraw裡面的代碼,全部在這了:

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.GREEN);//設畫布綠色
canvas.translate(20,20);//移動畫布
// 原始圖片
Bitmap src = BitmapFactory.decodeResource(getResources(), R.mipmap.cangcang);
// 圖片的遮罩
Bitmap mask=Bitmap.createBitmap(300, 300, src.getConfig());
Canvas cc=new Canvas(mask);
cc.drawCircle(150,150,150,mPaint);
/*
* 離屏緩存
* Layer層的寬和高要設定好,不然會出現有些部位不再層裡面,你的操作是不對這些部位起作用的
*/
int sc = canvas.saveLayer(0,0,300,300, null, Canvas.ALL_SAVE_FLAG);
// 先繪制dis目標圖
canvas.drawBitmap(src, 0, 0, mPaint);
// 設置混合模式 (只在源圖像和目標圖像相交的地方繪制目標圖像)
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
// 再繪制src源圖
canvas.drawBitmap(mask, 0, 0, mPaint);
// 還原混合模式
mPaint.setXfermode(null);
// 還原畫布
canvas.restoreToCount(sc);
}

那麼其他的xfermode屬性大家可以自己嘗試。前提是Layer的寬度和高度大家要控制好,其他都大同小異。

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