1.关于Xfermode类
从上面看出Xfermode有三个子类:AvoidXfermode,PixelXorXfermode,PoterDuffXfermode。它们分别表示:
AvoidXfermode:在绘图时,要么绘制在最顶层,要么绘制在除最顶层以外的地方。
PixelXorXfermode:这种转换不遵循自左乘的约定,因此这种模式总返回不透明的颜色(alpha=255),由此,对于混合颜色操作是没有用的。
PoterDuffXfermode:可以使用图像合成的任何一条PoterDuff模式。
注意:只有当一个Xfermode被分配给一个Paint时,使用Paint绘制Xfermode才有效。
2.PoterDuffXfemode
关于PoterDuff的所有Mode的效果图如下:
16种模式表示的意思分别是:
PoterDuff.Mode.CLEAR:绘制的图不会提交到画布上
PoterDuff.Mode.SRC:只显示绘制的上层图
PoterDuff.Mode.DST:只显示绘制的下层图
PoterDuff.Mode.SRC_OVER:绘制的上层图和下层图都显示,但上层图会覆盖下层图
PoterDuff.Mode.DST_OVER:绘制的上层图和下层图都显示,但下层图会覆盖上层图
PoterDuff.Mode.SRC_IN:取绘制的图的交集部分,显示上层
PoterDuff.Mode.DST_IN:取绘制的图的交集部分,显示下层
PoterDuff.Mode.SRC_OUT:取绘制的图的非交集部分,显示上层
PoterDuff.Mode.DST_OUT:取绘制的图的非交集部分,显示下层
PoterDuff.Mode.SRC_ATOP:取绘制的图的下层部分,和上层与下层的交集部分
PoterDuff.Mode.DST_ATOP:取绘制的图的上层部分,和下层与上层的交集部分
PoterDuff.Mode.XOR:取绘制的图的上层和下层的非交集部分
PoterDuff.Mode.DARKEN:取绘制的图的全集,上层和下层交集部分加深
PoterDuff.Mode.LIGHTEN:取绘制的图的全集,上层和下层交集部分点亮
PoterDuff.Mode.MULTIPLY:取绘制的图的交集部分并且交集部分颜色加深
PoterDuff.Mode.SCREEN:取绘制的图的全集,上层和下层的交集部分透明
附加:关于图的示例来自于SDK中的Sample,在我电脑上的路劲为:\sdk\samples\android-16\ApiDemos\src\com\example\android\apis\graphics\Xfermode.java
3.运用示例:
3.1 拍照遮罩
先看效果图:
总体为一个FramLayout,遮罩层在相机预览的上面,为了实现这个效果,最核心的就是在画遮罩层的时候,让中间矩形这块区域不可见。那么从上面分析的PoterDuff.Mode中,很明显CLEAR模式下,可以实现上面的效果。
因此,只需要两步,第一步画一个整体的遮罩图(下层图),第二步画一个不显示的矩形图(上层图):
设置画矩形区域的画笔: mRectPaint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR));
在onDraw()方法中,先画下层图: canvas.drawRect(0, 0, mScreenWidth, mScreenHeight, mAreaPaint);,再画上层图:canvas.drawRect(mVisibleRect, mRectPaint);
因此,这样就可以实现上面的显示效果。
3.2 圆形图片
先看效果图:
思路:在PoterDuff.Mode的SRC_IN下,画一个圆形的下层图,再把目标图片画在上面,那么这样最后的结果就是圆形图片(取绘制的图的交集部分,显示上层)。
代码示例:
public static Bitmap getRoundedCornerBitmap(Bitmap srcBitmap) {
int width = srcBitmap.getWidth();
int height = srcBitmap.getHeight();
int radius = 0;
if (width <= height) {
radius = width / 2;
} else {
radius = height / 2;
}
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(Color.WHITE);
Rect rect = new Rect(0, 0, 2 * radius, 2 * radius);
RectF rectF = new RectF(rect);
Bitmap desBitmap = Bitmap.createBitmap(2 * radius, 2 * radius, Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(desBitmap);
//除去抗锯齿
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
canvas.drawARGB(0, 0, 0, 0);
//绘制下层图
canvas.drawRoundRect(rectF, radius, radius, paint);
// 设置PorterDuffXfermode模式,取绘制的图的交集部分,显示上层
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
//绘制上层图
canvas.drawBitmap(srcBitmap, rect, rect, paint);
return desBitmap;
}