本文主要是介绍关于 Xfermode 正确理解姿势,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
作者: 夏至 欢迎转载,但保留这段申明
http://blog.csdn.net/u011418943/article/details/79310254
首先,先抛出一张 Google 的示例图,这是一张让人尴尬的效果图:
为啥这么说?
因为这张图为了能够显示 PorterDuff 的效果,代码是做了一些效果的,这就导致了一些小伙伴在写 demo 理解的时候,发现跟 Google 的效果不一致,从而产生疑问,是不是我写错了?哪里不一致呢?比如我写了 SRC_IN 这个模式,按照上面的效果,应该是这样的:
而实际上,却是这样的:
咦,为啥是这样的,我进入的姿势不对?
不要急,这里我想说的是,你没有理解错,只是源码做了处理而已。
1、ApiDemo 的代码
先看一下 ApiDemo 的代码, src 和 dst 是一张图片,而玄机就在这里,首先先看 src(即蓝色的图片)的代码:
// create a bitmap with a rect, used for the "src" imagestatic Bitmap makeSrc(int w, int h) {Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas c = new Canvas(bm);Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);p.setColor(0xFF66AAFF);c.drawRect(w/3, h/3, w*19/20, h*19/20, p);return bm;}
可以看到,虽然设置了 宽 和 高,但是实际canvas在画的时候,却没有填满,而留一段空白区域出来。我们在四周加一个边框,看一下效果:
可以看到,这里留了一大段的空白区域,同理,dst 的图片也是如此:
而 SRC_IN 是两者相较的地方绘制,那么上面这两张图绘制的结果,就只能是这样:
真相终于大白了,原来是这厮
嗯,那么,来一段帮助你理解这些模式的代码,去折腾吧:
public class XfermodeView extends View {private static final String TAG = "XfermodeView";private PorterDuffXfermode mPdXfermode; //定义PorterDuffXfermode变量//定义MODE常量,等下直接改这里即可进行测试private static PorterDuff.Mode PD_MODE = PorterDuff.Mode.SRC_IN ;private int mScreenW, mScreenH; //屏幕宽高private int mWidth = 200; //绘制的图片宽高private int nHeight = 200;private Bitmap mSrcBitmap, mDstBitmap; //上层SRC的Bitmap和下层Dst的Bitmapprivate Paint mShowpaint;public XfermodeView(Context context) {this(context, null);}public XfermodeView(Context context, AttributeSet attrs) {super(context, attrs);mShowpaint = new Paint();mShowpaint.setStyle(Paint.Style.STROKE);mShowpaint.setStrokeWidth(2);mScreenW = ScreenUtil.getScreenW(context);mScreenH = ScreenUtil.getScreenH(context);//创建一个PorterDuffXfermode对象mPdXfermode = new PorterDuffXfermode(PD_MODE);//实例化两个BitmapmSrcBitmap = makeSrc(mWidth, nHeight);mDstBitmap = makeDst(mWidth, nHeight);}public XfermodeView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}//定义一个绘制圆形Bitmap的方法,作为dst图private Bitmap makeDst(int w, int h) {Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas c = new Canvas(bm);Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);p.setColor(0xFF26AAD1);c.drawOval(new RectF(0, 0, w * 3 / 4, h * 3 / 4), p);//画四周的边框线mShowpaint.setColor(0xFF26AAD1);c.drawRect(0,0,w,h, mShowpaint);return bm;}//定义一个绘制矩形的Bitmap的方法,作为src图private Bitmap makeSrc(int w, int h) {Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas c = new Canvas(bm);Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);p.setColor(0xFFFFCE43);Log.d(TAG, "zsr --> makeSrc: "+w/3+" "+w*19/20);c.drawRect(w / 3, h / 3, w * 19 / 20, h * 19 / 20, p);//画四周的边框线mShowpaint.setColor(0xFFFFCE43);mShowpaint.setStyle(Paint.Style.STROKE);c.drawRect(0,0,w,h,mShowpaint);return bm;}@Overrideprotected void onDraw(Canvas canvas) {Paint paint = new Paint();paint.setFilterBitmap(false);paint.setStyle(Paint.Style.FILL);//绘制SRC上层的矩形Bitmapcanvas.drawBitmap(mSrcBitmap, (mScreenW / 3 - mWidth) / 2, (mScreenH / 2 - nHeight) / 2, paint);//绘制DST下层的原型Bitmapcanvas.drawBitmap(mDstBitmap, (mScreenW / 3 - mWidth) / 2 + mScreenW / 3, (mScreenH / 2 - nHeight) / 2, paint);//创建一个图层,在图层上演示图形混合后的效果int sc = canvas.saveLayer(0, 0, mScreenW, mScreenH, null, Canvas.ALL_SAVE_FLAG);canvas.drawBitmap(mDstBitmap, (mScreenW / 3 - mWidth) / 2 + mScreenW / 3 * 2,(mScreenH / 2 - nHeight) / 2, paint); //绘制i//设置Paint的Xfermodepaint.setXfermode(mPdXfermode);canvas.drawBitmap(mSrcBitmap, (mScreenW / 3 - mWidth) / 2 + mScreenW / 3 * 2,(mScreenH / 2 - nHeight) / 2, paint);paint.setXfermode(null);// 还原画布canvas.restoreToCount(sc);/*** 画图片的边框,便于理解*/// src lineint srcleft = (mScreenW / 3 - mWidth) / 2 + mScreenW / 3 * 2;int srctop = (mScreenH / 2 - nHeight) / 2;mShowpaint.setColor(0xFFFFCE43);canvas.drawRect(srcleft,srctop,srcleft + mWidth,srctop+ nHeight,mShowpaint);// des line,因为位置一样,加4减4,能看出效果mShowpaint.setColor(0xFF26AAD1);canvas.drawRect(srcleft + 4,srctop + 4,srcleft + mWidth - 4,srctop+ nHeight -4 ,mShowpaint);}
}
这篇关于关于 Xfermode 正确理解姿势的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!