1、概述
在android图形渲染中 会使用到图像混合模式
<span style="font-size:18px;">setXfermode(Xfermode xfermode)</span>
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>