Paint画笔特效之PorterDuffXfermode

来源:互联网 发布:淘宝商品下面的优惠券 编辑:程序博客网 时间:2024/05/21 11:13

一、为什么只说PorterDuffXfermode?

1.提到Xfermode,现在查看API文档会发现它有三个子AvoidXfermode,PPixelXorXfermode,PorterDuffXfermode.

前两个子类在API16的时候已经过期了,现在去查看Api最新文档,你会发现只有PorterDufferXfermode一个子类.

画笔Paint的setXfermode(Xfermode xfermode)方法设置的是两个图像重叠时候的混合显示模式,参数中只有一个PorterDufferXfermode还一直被使用至今.所以我们只说PorterDuffXfermode.

二、图形混合模式 PorterDuffXfermode类

该类有且只有一个含参的构造方法PorterDuffXfermode(PorterDuff.Mode mode),这个PorterDuff.Mode就表示一种混合模式,而PorterDuffXfermode表示这种图形混合模式的显示.

这些模式显示用下面这张比较俗套的图可以体现


在API中Android为我们提供了18种(比上图多了两种ADD和OVERLAY)模式;

需要说一下上图中先画的是黄色圆形,后画是蓝色矩形,产生的混合效果,下面我们使用代码演示一下。

三、用代码验证PorterDuffXfermode类所有情形

废话不多说,直接上代码了

public class PorterDuffXfermodeView extends View {    private PorterDuffXfermode mXfermode;//定义图像间的混合显示模式    private static PorterDuff.Mode sMode = PorterDuff.Mode.SRC_OVER;// //定义PorterDuff.MODE常量    private int mScreenWidth;//屏幕的宽度    private int mScreenHeight;//屏幕的高度    private int mWidth;//绘制一个Bitmap的宽度    private int mHeight;//绘制一个Bitmap的高度    private Bitmap srcBitmap;//后画的Bitmap    private Bitmap dstBitmap;//先画的Bitmap    public PorterDuffXfermodeView(Context context) {        this(context, null);    }    public PorterDuffXfermodeView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public PorterDuffXfermodeView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics outMetrics = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics(outMetrics);        mScreenHeight = outMetrics.heightPixels;        mScreenWidth = outMetrics.widthPixels;        mHeight = mWidth = mScreenWidth / 3;        //创建一个PorterDuffermode对象        mXfermode = new PorterDuffXfermode(sMode);        srcBitmap = makeSrc(mWidth, mHeight);        dstBitmap = makeDst(mWidth, mHeight);    }    //绘制一个矩形    private Bitmap makeSrc(int w, int h) {        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);        Canvas srcCanvas = new Canvas(bm);        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);        p.setColor(0xFF63A9FE);        srcCanvas.drawRect(w / 3, h / 3, w * 4 / 5, h * 4 / 5, p);        return bm;    }    //绘制一个圆形    private Bitmap makeDst(int w, int h) {        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);        Canvas dstCanvas = new Canvas(bm);        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);        p.setColor(0xFFFECF41);        dstCanvas.drawOval(new RectF(w / 10, h / 10, w * 2 / 3, h * 2 / 3), p);        return bm;    }    @Override    protected void onDraw(Canvas canvas) {        Paint paint = new Paint();        paint.setStyle(Paint.Style.FILL);        canvas.drawBitmap(dstBitmap, 0, 0, paint);//先画的图形DST        canvas.drawBitmap(srcBitmap, mHeight, 0, paint);//后画的图形SRC                //在另一个图层上演示DST和SRC图形混合后的效果        int sc = canvas.saveLayer(0, 0, mScreenWidth, mHeight, null, Canvas.ALL_SAVE_FLAG);        canvas.drawBitmap(dstBitmap, mHeight * 2, 0, paint);//绘制        //设置Paint的Xfermode        paint.setXfermode(mXfermode);        canvas.drawBitmap(srcBitmap, mHeight * 2, 0, paint);        // 还原画布        canvas.restoreToCount(sc);    }}

注意上面onDraw()方法中有涉及三个Canvas 这里为什么使用saveLayer之后才会有效果,我也没搞明白。。。知道的可以回复一下,,下面是我的理解

saveLayer方法相当于创建了一个透明的图层,在它上面进行图像的融合,正好可以!但必须是图层相同宽高的部分。

我们改变代码中的sMode变量验证所有的混合模式,上面代码显示绘制第一个要显示的黄色图形,然后绘制要显示的蓝色图形,最后在另一个图层上展示他们的混合模式,

运行之后的效果图(按照那张模式图来展示):

1.PorterDuff.Mode.Clear


2.PorterDuff.Mode.Src


3.PorterDuff.Mode.Dst


4.PorterDuff.Mode.SrcOver


5.PorterDuff.Mode.DstOver


6.PorterDuff.Mode.SrcIn


7.PorterDuff.Mode.DstIn


8.PorterDuff.Mode.SrcOut


9.PorterDuff.Mode.DstOut


10.PorterDuff.Mode.SrcATop


11.PorterDuff.Mode.DstATop


12.PorterDuff.Mode.Xor


13.PorterDuff.Mode.Darken


14.PorterDuff.Mode.Lighten


15.PorterDuff.Mode.Multiply


16.PorterDuff.Mode.Screen


17.PorterDuff.Mode.ADD


18.PorterDuff.Mode.OVERLY


最后两种模式换了一个模拟器测试,不相信的,可以自己动手测试看看效果信!




0 0
原创粉丝点击