当前位置:   article > 正文

Android Paint之 setXfermode PorterDuffXfermode 讲解_paint.setxfermode

paint.setxfermode

我正在参加 CSDN 2015博客之星评选 感恩分享活动,如果觉得文章还不错,请投个票鼓励下吧:http://vote.blog.csdn.net/blogstar2015/candidate?username=tianjian4592


尊重原创,欢迎转载,转载请注明: FROM  GA_studio   http://blog.csdn.net/tianjian4592


前面关于paint的方法讲解里,讲到 setXfermode 就截止了,原因有两个:

1. 那篇文章已经太长了,我自己都看不下去了;

2. setXfermode 在paint 里占有至关重要的地位;

基于以上两个原因,我们一起来看看这个方法有何妙用。

首先我们还是来看看关于这个方法的说明:

  1. /**
  2. * Set or clear the xfermode object. - 设置或清除xfermode对象;
  3. * Pass null to clear any previous xfermode. - 传递null以清除任何以前的xfermode。
  4. * As a convenience, the parameter passed is also returned. - 为方便起见,也返回传递的参数。
  5. *
  6. * @return xfermode
  7. */
  8. public Xfermode setXfermode(Xfermode xfermode) {
  9. int xfermodeNative = 0;
  10. if (xfermode != null)
  11. xfermodeNative = xfermode.native_instance;
  12. native_setXfermode(mNativePaint, xfermodeNative);
  13. mXfermode = xfermode;
  14. return xfermode;
  15. }

这个方法传进一个 Xfermode 对象,而打开 Xfermode 发现里面没有提供任何可用的构造函数或方法,ctrl +T 看到它有三个子类:




前两个子类 AvoidXfermode 和 PixelXorXfermode 大家可以看到都已经被划上了斜线,下面就简单提及一下,咱们的重点在 PorterDuffXfermode :

1. AvoidXfermode:

  1. /** This xfermode draws, or doesn't draw, based on the destination's
  2. * distance from an op-color.
  3. *
  4. * There are two modes, and each mode interprets a tolerance value.
  5. *
  6. * Avoid: In this mode, drawing is allowed only on destination pixels that
  7. * are different from the op-color.
  8. * Tolerance near 0: avoid any colors even remotely similar to the op-color
  9. * Tolerance near 255: avoid only colors nearly identical to the op-color
  10. * Tolerance near 0: draw only on colors that are nearly identical to the op-color
  11. * Tolerance near 255: draw on any colors even remotely similar to the op-color
  12. */
  13. public AvoidXfermode(int opColor, int tolerance, Mode mode) {
  14. if (tolerance < 0 || tolerance > 255) {
  15. throw new IllegalArgumentException("tolerance must be 0..255");
  16. }
  17. native_instance = nativeCreate(opColor, tolerance, mode.nativeInt);
  18. }

咱们把它上面的说明看下就很清楚了:

xfermode 是否绘制,基于目标色和参数 op-color 的差距;

其中有两种模式,分别为 Avoid 和 TARGET:

Avoid模式:只会在目标像素值和 op-color "不一样" 的地方进行绘制;

Target模式:只会在目标像素值和 op-color "一样" 的地方进行绘制;

上面的"一样" 和 "不一样" 我都打上了引号,并不是指严格意义上的一样,而是只要在可容忍范围内就代表一样,这个可容忍范围,就是容差值(tolerance),0 代表最小容差,即得和 op-color 真正意义上一样才 ok ,255 则代表最大容差,只要有一点相近,则ok;

咱们一起来看个小例子:

先在网上找个图案,用PS去掉周围部分,主体改为纯色;


                                  


当我们使用PS里的魔棒创立选区的时候,发现一次只选取了其中最相近的一部分,这时候可以看到容差为5,但我们的目的是想把图形周围近似的蓝灰色都选中该怎么办呢?容差这时候就起作用了,改大容差,就相当于调大近似度,这个概念和我们里面的容差值是一样的,希望这样说便于理解,我们看下对比图,调到50 一下就可以选中外层所有蓝灰色:


                                               


好,我们现在有了一个纯色的图标,假定我们现在有一个需求,需要在某种操作下将图标变色,类似微信底部的tab图标,未选中时时白色,选中时是绿色,这个时候我们就可以用

AvoidXfermode 进行实现,我们一起看看要怎么做:

1. 给paint 设置要变换的颜色和图层混合模式为 AvoidXfermode;

2. 绘制图标;

3. 再绘制对应色块;

由于是对对应颜色进行替换,所以也就形成了图标变色的效果,一起来看看代码:

  1. public class AvoidXfermodeView extends View {
  2. private Paint mBitmapPaint, mAvoidPaint;
  3. private int mTotalWidth, mTotalHeight;
  4. private Bitmap mBitmap;
  5. private int mBitWidth, mBitHeight;
  6. private Rect mOriginSrcRect, mOriginDestRect;
  7. private Rect mAvoidSrcRect, mAvoidDestRect;
  8. private AvoidXfermode mAvoidXfermode;
  9. public AvoidXfermodeView(Context context) {
  10. super(context);
  11. initPaint();
  12. initBitmap();
  13. // 对蓝色相近的颜色进行替换
  14. mAvoidXfermode = new AvoidXfermode(Color.BLUE, 150, Mode.TARGET);
  15. }
  16. private void initBitmap() {
  17. mBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.bluelogo)).getBitmap();
  18. mBitWidth = mBitmap.getWidth();
  19. mBitHeight = mBitmap.getHeight();
  20. }
  21. private void initPaint() {
  22. mBitmapPaint = new Paint();
  23. // 去锯齿
  24. mBitmapPaint.setAntiAlias(true);
  25. // 防抖动
  26. mBitmapPaint.setDither(true);
  27. // 图像过滤
  28. mBitmapPaint.setFilterBitmap(true);
  29. // 使用上面属性创建一个新paint
  30. mAvoidPaint = new Paint(mBitmapPaint);
  31. // 颜色设置为红色
  32. mAvoidPaint.setColor(Color.RED);
  33. }
  34. @Override
  35. protected void onDraw(Canvas canvas) {
  36. super.onDraw(canvas);
  37. // 绘制原图
  38. canvas.drawBitmap(mBitmap, mOriginSrcRect, mOriginDestRect, mBitmapPaint);
  39. // 绘制用于变色图
  40. canvas.drawBitmap(mBitmap, mAvoidSrcRect, mAvoidDestRect, mAvoidPaint);
  41. // 设置图层混合模式
  42. mAvoidPaint.setXfermode(mAvoidXfermode);
  43. // 绘制色块进行混合,得到最终效果
  44. canvas.drawRect(mAvoidDestRect, mAvoidPaint);
  45. }
  46. @Override
  47. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  48. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  49. }
  50. @Override
  51. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  52. super.onSizeChanged(w, h, oldw, oldh);
  53. mTotalWidth = w;
  54. mTotalHeight = h;
  55. mOriginSrcRect = new Rect(0, 0, mBitWidth, mBitHeight);
  56. // 为了让图水平居中
  57. int left = (mTotalWidth - mBitWidth) / 2;
  58. mOriginDestRect = new Rect(left, 0, left + mBitWidth, mBitHeight);
  59. mAvoidSrc
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/332667
推荐阅读
相关标签
  

闽ICP备14008679号