Android中Xfermode简单用法

首先参考了这篇博文给的灵感:
详解Paint的setXfermode(Xfermode xfermode)
其次呢,在写这篇博文的时候呢也避免不了抱怨啊。网上其他的关于Xfermode介绍的大部分都是google官方文档中属性的含义,都很雷同估计都是翻译过来的。

贴上google官方ApiDemo中Graphics中Xfermode截图:
Android中Xfermode简单用法_第1张图片

纠结了2天终于弄出来的

最令人气愤是你看着其他人博客然后想做google官方属性的出的效果,但是愣是没有做出来效果,我这暴脾气,非要弄出来。于是乎有了这篇博文。

下面会给大家介绍最简单直接的做法,为了方便大伙看明白,简单有效才是王道!!

下面真正是正文了啊:大伙注意了。
对于官方文档的xfermode我们只是看到两个类似层的图片
其实和photoshop中的图层一样;
一个是原始图层,另一个是遮罩层
我把整个View的画布设置为绿色了,为了方便大家观看效果

canvas.drawColor(Color.GREEN);//画布设为绿色

先上效果图吧,嘿嘿苍老师的头像。

Android中Xfermode简单用法_第2张图片

看完正确运行出来的效果,那么给大家看看错误运行出来的效果:
是我的苍老师,也是大家的苍老师
Android中Xfermode简单用法_第3张图片

下面告诉大伙正确的操作:

//将绘制操作保存到新的图层(离屏缓存)
canvas.saveLayer(0,0,300,300, null,Canvas.ALL_SAVE_FLAG);
方法:
public int saveLayer(float left, float top, float right, float bottom, Paint paint, int saveFlags)

大伙不要小看这个方法,我们必须设置将绘制操作保存到新的图层,不然就会出现苍老师头像显示不正常的情况
当然最后还要还原画布

// 还原画布
canvas.restoreToCount(sc);

canvas顾名思义是画布。所有的绘制操作都发生在这张画布上,当然当我们要使用多个图片叠加等的情况我们就要使用“层”了,就如百度地图或是高德地图,他们在地图上面添加新的事物,如线路,兴趣点的时候都是用到了层Layer。
当然Canvas给我们提供了层支持;这些Layer是按照栈结构来管理的,后进先出的顺序显示;
当Layer入栈的时候,那么后续的drawXXXX操作都发生在这个Layer层上面。而Layer退栈时,就会把本层绘制的图像“绘制”到上层或是Canvas上,在复制Layer到Canvas上时,可以指定Layer的透明度(Layer),这是在创建Layer时指定的:
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags)
我们这篇就不说明saveLayerAplha了。大伙可以自己使用

那么说这么多,有人看博文肯定说代码呢,稍等,客官马上就来咯:
当然Xfermode网上很多文章都写了相关属性介绍的含义,当然我做这个的时候是按照官方给出图片做的效果。意思呢,可以意会。如果我说了,大伙又迷糊了。哈哈哈哈,这也是我的风格。

那么我所有的操作都在onDraw()函数体里面写了啊。至于性能方面不是我这篇文章所讨论的。可以不用在onDraw里面new对象操作,可以提高性能啥的。
当然自定义view避免不了,先测量下啦。为了简单直接这样:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width=MeasureSpec.getSize(widthMeasureSpec);
int height=MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width,height);
}

最后贴上onDraw里面的代码,全部在这了:

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.GREEN);//设画布绿色
canvas.translate(20,20);//移动画布
// 原始图片
Bitmap src = BitmapFactory.decodeResource(getResources(), R.mipmap.cangcang);
// 图片的遮罩
Bitmap mask=Bitmap.createBitmap(300, 300, src.getConfig());
Canvas cc=new Canvas(mask);
cc.drawCircle(150,150,150,mPaint);
/*
* 离屏缓存
* Layer层的宽和高要设定好,不然会出现有些部位不再层里面,你的操作是不对这些部位起作用的
*/
int sc = canvas.saveLayer(0,0,300,300, null, Canvas.ALL_SAVE_FLAG);
// 先绘制dis目标图
canvas.drawBitmap(src, 0, 0, mPaint);
// 设置混合模式 (只在源图像和目标图像相交的地方绘制目标图像)
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
// 再绘制src源图
canvas.drawBitmap(mask, 0, 0, mPaint);
// 还原混合模式
mPaint.setXfermode(null);
// 还原画布
canvas.restoreToCount(sc);
}

那么其他的xfermode属性大家可以自己尝试。前提是Layer的宽度和高度大家要控制好,其他都大同小异。

你可能感兴趣的:(Android,android,paint)