一、setXfermode(Xfermode xfermode)
Xfermode国外有大神称之为过渡模式,这种翻译比较贴切但恐怕不易理解,大家也可以直接称之为图像混合模式,因为所谓的“过渡”其实就是图像混合的一种,这个方法跟我们上面讲到的setColorFilter蛮相似的。查看API文档发现其果然有三个子类:AvoidXfermode, PixelXorXfermode和PorterDuffXfermode,这三个子类实现的功能要比setColorFilter的三个子类复杂得多。
二、AvoidXfermode
2.1 关闭硬件加速
这个API因为不支持硬件加速在API 16已经过时了(大家可以在HardwareAccel查看那些方法不支持硬件加速)如果想在高于API 16的机子上进行测试,必须现在应用或手机设置中关闭硬件加速,在应用中我们可以通过在AndroidManifest.xml文件中设置application节点下的android:hardwareAccelerated属性为false来关闭硬件加速:
<application android:allowBackup="true" android:hardwareAccelerated="false" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
注意:如果你在设置中开启了强制硬件加速(强制使用GPU进行绘制),在代码中配置也是没用的。
2.2 构造方法
AvoidXfermode只有一个含参的构造方法:AvoidXfermode(int opColor, int tolerance, AvoidXfermode.Mode mode)
AvoidXfermode有三个参数,第一个opColor表示一个16进制的可以带透明通道的颜色值例如0x12345678;第二个参数tolerance表示容差值,那么什么是容差呢?你可以理解为一个可以标识“精确”或“模糊”的东西,表示当前颜色和opColor的差异程度;最后一个参数表示AvoidXfermode的具体模式,其可选值只有两个:AvoidXfermode.Mode.AVOID或者AvoidXfermode.Mode.TARGET,两者的意思也非常简单,我们先来看
2.3 AvoidXfermode.Mode.TARGET
在该模式下Android会判断画布上的颜色是否会有跟opColor不一样的颜色,opColor可以理解为基准色,仅仅用来做判断。比如我opColor是红色,那么在TARGET模式下就会去判断我们的画布上是否有存在红色(opColor)的地方,如果有,则把该区域“染”上一层我们”画笔的颜色“,否则不“染”色,而tolerance容差值则表示画布上的像素和我们定义的红色之间的差别是多少的时候才去“染”的,比如当前画布有一个像素的色值是(200, 20, 13),而我们的红色值为(255, 0, 0),当tolerance容差值为255时,即便(200, 20, 13)并不等于红色值也会被“染”色,容差值越大“染”色范围越广反之则反。
如果我们想要让图片中白色像素被染上紫色:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 先画一个图片 Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.kale); canvas.drawBitmap(bitmap, 240, 600, mPaint); /* * 当画布中有跟0XFFFFFFFF色不一样的地方时候才“染”色 * 第一个参数颜色是基本色,绘制的时候会判断有没有和基本色相似的颜色(相似程度用容差值表示),有的话就用画笔当前的颜色去绘制那个像素点。 */ AvoidXfermode avoidXfermode = new AvoidXfermode(0XFFFFFFFF, 255, AvoidXfermode.Mode.TARGET); // “染”什么色是由我们自己决定的 mPaint.setARGB(255, 211, 53, 243); // 设置模式 mPaint.setXfermode(avoidXfermode); // 在图片同等位置上,画一个和位图大小一样的矩形 canvas.drawRect(240, 600, 240 + bitmap.getWidth(), 600 + bitmap.getHeight(), mPaint); }
得到下面的效果:
如果提高容差值,那么接近白色的区域也会被染上紫色。
注意:如果你没关闭硬件加速,那么就会得到像下图这样的一个色块。
2.4 AvoidXfermode.Mode.AVOID
则与TARGET恰恰相反,TARGET是我们指定的颜色是否与画布的颜色一样,而AVOID是我们指定的颜色是否与画布不一样,其他的都与TARGET类似
AvoidXfermode(0XFFFFFFFF, 0, AvoidXfermode.Mode.AVOID):
当模式为AVOID容差值为0时,只有当图片中像素颜色值与0XFFFFFFFF完全不一样的地方才会被染色
AvoidXfermode(0XFFFFFFFF, 255, AvoidXfermode.Mode.AVOID):
当容差值为255时,只要与0XFFFFFFFF稍微有点不一样的地方就会被染色
那么这玩意究竟有什么用呢?比如说当我们只想在白色的区域画点东西或者想把白色区域的地方替换为另一张图片的时候就可以采取这种方式!
三、PixelXorXfermode
与AvoidXfermode一样也在API 16过时了,该类也提供了一个含参的构造方法PixelXorXfermode(int opColor),该类的计算实现很简单,从官方给出的计算公式来看就是:op ^ src ^ dst,像素色值的按位异或运算,如果大家感兴趣,可以自己用一个纯色去尝试,并自己计算异或运算的值是否与得出的颜色值一样,这里我就不讲了,Because it was deprecated and useless。
四、PorterDuffXfermode
Xfermode的最后一个子类也是惟一一个没有过时且沿用至今的子类,这个类是否强大,值得我们好好的学习学习。