ProterDuff 使用详解
开头我们来看 ProterDuff 这个词 。
好神奇的单词,完全不知道什么意思对不对(有木有),上网一搜原来是关于2D图像组合的一种理论。
这是豆瓣上的解释:http://www.douban.com/note/143111853/
那么我们为什么要组合2D图形呢?我们先来看一组图:
这是桌面应用程序在触摸和拖动图标时候的状态,图1中的白色围绕着bitmap的边缘,图2也是。找到桌面源码中的HolographicOutlineHelper.java查看,原来是用到了ProterDuff.Mode组合出来的图形。当然还有大量的计算。下面介绍一下ProterDuff是如何来组合图形的
这是官网文档
枚举类
public static final enum
PorterDuff.Mode
java.lang.Object | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
↳ | java.lang.Enum<android.graphics.PorterDuff.Mode> | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
↳ |
android.graphics.PorterDuff.Mode
Summary
|
分别是这些意思:
1.PorterDuff.Mode.CLEAR
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
显示上层绘制图片
3.PorterDuff.Mode.DST
3.PorterDuff.Mode.DST
显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER
4.PorterDuff.Mode.SRC_OVER
正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER
5.PorterDuff.Mode.DST_OVER
上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN
6.PorterDuff.Mode.SRC_IN
取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN
7.PorterDuff.Mode.DST_IN
取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT
8.PorterDuff.Mode.SRC_OUT
取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT
9.PorterDuff.Mode.DST_OUT
取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
10.PorterDuff.Mode.SRC_ATOP
取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP
11.PorterDuff.Mode.DST_ATOP
取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR
12.PorterDuff.Mode.XOR
异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN
13.PorterDuff.Mode.DARKEN
取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN
14.PorterDuff.Mode.LIGHTEN
取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY
15.PorterDuff.Mode.MULTIPLY
取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN
16.PorterDuff.Mode.SCREEN
取两图层全部区域,交集部分变为透明色
然后我们就可以开始怀着一颗好奇心画图了.....
自定义一个View,在View中创建两个Bitmap,分别画方和圆,尺寸可以随便定
Java:
public class DuffView extends View { private Bitmap mSrcB; private Bitmap mDstB; private Shader mBG; // 文档说了是枚举类,共有16个 private static final Xfermode[] sModes = { new PorterDuffXfermode(PorterDuff.Mode.CLEAR), new PorterDuffXfermode(PorterDuff.Mode.SRC), new PorterDuffXfermode(PorterDuff.Mode.DST), new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER), new PorterDuffXfermode(PorterDuff.Mode.DST_OVER), new PorterDuffXfermode(PorterDuff.Mode.SRC_IN), new PorterDuffXfermode(PorterDuff.Mode.DST_IN), new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT), new PorterDuffXfermode(PorterDuff.Mode.DST_OUT), new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP), new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP), new PorterDuffXfermode(PorterDuff.Mode.XOR), new PorterDuffXfermode(PorterDuff.Mode.DARKEN), new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN), new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY), new PorterDuffXfermode(PorterDuff.Mode.SCREEN) }; public DuffView(Context context) { super(context); } public DuffView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public DuffView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } // 初始化 private void init() { mSrcB = makeSrc(400, 400); mDstB = makeDst(400, 400); Bitmap bitmap = Bitmap.createBitmap(new int[] { 0xFFFFFFFF, 0xFFCCCCCC, 0xFFCCCCCC, 0xFFFFFFFF }, 2, 2, Bitmap.Config.RGB_565); mBG = new BitmapShader(bitmap, TileMode.REPEAT, TileMode.REPEAT); Matrix m = new Matrix(); m.setScale(6, 6); mBG.setLocalMatrix(m); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.WHITE); Paint paint = new Paint(); paint.setFilterBitmap(false); canvas.translate(35, 35); paint.setStyle(Style.STROKE); paint.setShader(null); canvas.drawRect(0, 0, 400, 400, paint); // shader paint.setStyle(Style.FILL); paint.setShader(mBG); canvas.drawRect(0, 0, 400, 400, paint); int sc = canvas.saveLayer(0, 0, 400, 400, null, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); canvas.drawBitmap(mDstB, 0, 0, paint); // 组合图形最关键的地方就在这里 // paint.setXfermode(sModes[0]); canvas.drawBitmap(mSrcB, 0, 0, paint); canvas.restoreToCount(sc); } // 画圆 static Bitmap makeDst(int w, int h) { Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setColor(0xFFFFCC44); p.setColor(Color.RED); canvas.drawCircle(w / 2, h / 2, w / 3, p); return bitmap; } // 画方 static Bitmap makeSrc(int w, int h) { Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(bm); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setColor(0xFF66AAFF); c.drawRect(w / 2, h / 2, w - 20, h - 20, p); return bm; } }
这里先运行效果看一下:
然后给画笔加上组合方式,通过setXfermode(arg0)来设置,分别运行16种效果如下:
CLEAR SRC DST SRC_OVER
DST_OVER SRC_IN DST_IN SRC_OUT
DST_OUT SRC_ATOP DST_ATOP XOR
DARKEN LIGHTEN MULTIPLY SCREEN