开头我们来看 ProterDuff 这个词 。
好神奇的单词,完全不知道什么意思对不对(有木有),上网一搜原来是关于2D图像组合的一种理论。
这是豆瓣上的解释:http://www.douban.com/note/143111853/
那么我们为什么要组合2D图形呢?我们先来看一组图:
这是桌面应用程序在触摸和拖动图标时候的状态,图1中的白色围绕着bitmap的边缘,图2也是。找到桌面源码中的HolographicOutlineHelper.java查看,原来是用到了ProterDuff.Mode组合出来的图形。当然还有大量的计算。下面介绍一下ProterDuff是如何来组合图形的
这是官网文档
枚举类
public static final enum
PorterDuff.Mode
extends Enum< PorterDuff.Mode>
java.lang.Object | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
↳ | java.lang.Enum |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
↳ | 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