图形绘制中的PorterDuffXfermode
1、概述
在Android图形渲染中 会使用到图像混合模式
- <span style="font-size:18px;">setXfermode(Xfermode xfermode)</span>
Xfermode有三个子类
AvoidXfermode, PixelXorXfermode,这俩个均已经被淘汰
只剩 【PorterDuffXfermode】,这个模式是由俩个大牛Tomas Proter和Tom Duff名字来命名的,PorterDuffXfermode模式能为android图形渲染做啥呢,先来张经典图片
咋看有点晕,先解释一下
1.PorterDuff.Mode.CLEAR :所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC : 显示上层绘制图片
3.PorterDuff.Mode.DST : 显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER : 正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER : 上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN : 取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN :取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT :取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT : 取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP :取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP : 取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR : 异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN :取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN : 取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY : 取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN : 取两图层全部区域,交集部分变为透明色
后来还新增了俩种模式 ADD和OVERLAY
17.PorterDuff.Mode.ADD 饱和度叠加
18.PorterDuff.Mode.OVERLAY: 直接叠加
2、示例代码、
下面听过俩个例子来熟悉一下使用
首先来定义一个获取屏幕宽和高的工具代码
- <span style="font-size:18px;">public class ScreenMeasureUtil {
- //同时获取宽高
- public static int[] getScreenHW(Activity activity) {
- DisplayMetrics metrics = new DisplayMetrics();
- activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
- int Height = metrics.heightPixels;
- int Width = metrics.widthPixels;
- int HW[] = new int[]{Height, Width};
- }
- }</span>
橡皮擦效果
自定义一个eraser的view,然后在之布局文件中引入这个控件即可 EraserView.Java,注释很详细,这里使用了DST_IN模式(使用dst_out效果一样)
- <span style="font-size:18px;">public class EraserView extends View {
- //屏幕宽高
- private int[] screenSize;
- private int screenH;
- private int screenW;
- //PorterDuff Mode
- private static final PorterDuff.Mode PD_MODE = PorterDuff.Mode.DST_IN;
- private static final int MIN_MOVE_DIS = 5;//最小的移动距离:如果我们手指在屏幕上的移动距离小于此值则不会绘制
- private float preTouchX, preTouchY;
- //绘图
- private Canvas mCanvas; //画布
- private Paint mPaint;//画笔
- private Path mPath;//路径
- //前后背景
- private Bitmap fgBitmap, bgBitmap;
- public EraserView(Context context, AttributeSet attrs) {
- super(context, attrs);
- screenSize = ScreenMeasureUtil.getScreenHW((Activity) context);
- screenH = screenSize[0];
- screenW = screenSize[1];
- initViews(context);
- }
- private void initViews(Context context) {
- //实例化路径对象
- mPath = new Path();
- //实例化画笔开启抗锯齿和抗抖动
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
- //画笔风格为描边
- mPaint.setStyle(Paint.Style.STROKE);
- //笔触类型为圆角
- mPaint.setStrokeJoin(Paint.Join.ROUND);
- //设置描边
- mPaint.setStrokeCap(Paint.Cap.ROUND);
- //设置描边宽度
- mPaint.setStrokeWidth(20);
- //设置混合模式
- mPaint.setXfermode(new PorterDuffXfermode(PD_MODE));
- //此处采用的是DST_IN模式必须要将画笔透明度设置为0
- mPaint.setARGB(128, 255, 0, 0);
- //前景图片的bitmap
- fgBitmap = Bitmap.createBitmap(screenW, screenH, Bitmap.Config.ARGB_8888);
- //填充进画布
- mCanvas = new Canvas(fgBitmap);
- //绘制画布背景颜色为灰色
- mCanvas.drawColor(0xffacacac);
- //获取底面背景图片
- bgBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.bg_splash);
- //缩放bitmap至屏幕大小
- bgBitmap = Bitmap.createScaledBitmap(bgBitmap, screenW, screenH, true);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- //绘制背景
- canvas.drawBitmap(bgBitmap, 0, 0, null);
- //绘制前景
- canvas.drawBitmap(fgBitmap, 0, 0, null);
- mCanvas.drawPath(mPath, mPaint);
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- float x = event.getX();
- float y = event.getY();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mPath.reset();
- mPath.moveTo(x, y);
- preTouchX = x;
- preTouchY = y;
- break;
- case MotionEvent.ACTION_MOVE:
- float dx = Math.abs(x - preTouchX);
- float dy = Math.abs(y - preTouchY);
- if (dx >= MIN_MOVE_DIS || dy >= MIN_MOVE_DIS) {
- mPath.quadTo(preTouchX, preTouchY, (x + preTouchX) / 2, (y + preTouchY) / 2);
- preTouchX = x;
- preTouchY = y;
- }
- break;
- }
- //重绘视图
- invalidate();
- return true;
- }
- }
- </span>
转载:http://blog.****.net/xsf50717/article/details/49822179