Paint.setXfermode终极解析

Paint.setXfermode终极解析

效果图

关于Paint.setXfermode网上有很多篇文档,但有些未详细说明或讲解有错误,经本人测试,以下是测试结果效果图

这里写图片描述

由于时间关系只能简要说明思路和结果,如无有疑问请阅读代码

  1. 灰色的canvas背景色
  2. 创建一个空白的mDstBitmap并画一个黄色的圆
  3. 创建一个空白的mSrcBitmap并画一个蓝色的矩形(注意这个矩形画在mSrcBitmap中间,mSrcBitmap没有画满是为了观察到组合后差异)

结论

设置意义
CLEAR src无像素+重叠消失
SRC src无像素消失,src完全显示
SRC_OVER src重叠显示,src未重叠显示
SRC_ATOP src重叠显示
SRC_IN src无像素消失,重叠显示src
SRC_OUT src无像素和重叠消失,src未重叠显示
DST dst不变,src无显示
DST_OVER dst不变,src未重叠显示
DST_ATOP src无像素消失,重叠显示dst,显示src
DST_IN src无像素消失,重叠显示dst
DST_OUT 重叠消失,src不显示
XOR 重叠消失,src未重叠显示
DARKEN 重叠颜色加深,src未重叠显示
LIGHTEN 重叠颜色变亮,src未重叠显示
MULTIPLY src无像素消失,重叠加深显示
SCREEN 重叠变亮,src未重叠显示
ADD 重叠变亮,src未重叠显示
OVERLAY 重叠变亮,src未重叠显示

Dome代码

  1. 布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="5dp"
            tools:context="com.feadre.customview.MainActivity">
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                app:set_mode="1"
                app:show_text="CLEAR"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="12"
                app:show_text="XOR"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="13"
                app:show_text="DARKEN"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="14"
                app:show_text="LIGHTEN"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="15"
                app:show_text="MULTIPLY"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="16"
                app:show_text="SCREEN"
                />
    
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="5dp"
            tools:context="com.feadre.customview.MainActivity">
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                app:set_mode="2"
                app:show_text="SRC"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="3"
                app:show_text="SRC_OVER"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="4"
                app:show_text="SRC_ATOP"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="5"
                app:show_text="SRC_IN"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="6"
                app:show_text="SRC_OUT"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="17"
                app:show_text="ADD"
                />
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="5dp"
            tools:context="com.feadre.customview.MainActivity">
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                app:set_mode="7"
                app:show_text="DST"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="8"
                app:show_text="DST_OVER"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="9"
                app:show_text="DST_ATOP"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="10"
                app:show_text="DST_IN"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="11"
                app:show_text="DST_OUT"
                />
    
            <com.feadre.customview.myview.SetXfermodeView
                android:layout_width="85dp"
                android:layout_height="85dp"
                android:layout_marginTop="10dp"
                app:set_mode="18"
                app:show_text="OVERLAY"
                />
        </LinearLayout>
    

  2. 代码

    public class SetXfermodeView extends View {
        public String mText = "没有设置哦";
        private final Paint  mPaint;
        private       Bitmap mSrcBitmap;
        private       Bitmap mDstBitmap;
        private       int    mMode;
        private       Paint  mTitlePaint;
    
        public SetXfermodeView(Context context) {
            this(context, null);
        }
    
        public SetXfermodeView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public SetXfermodeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SetXfermodeView, defStyleAttr, 0);
            String text = array.getString(R.styleable.SetXfermodeView_show_text);
            mMode = array.getInt(R.styleable.SetXfermodeView_set_mode, 0);
            if (!TextUtils.isEmpty(text)) {
                mText = mMode + "   " + text + "  模式";
            }
            mPaint = new Paint();
            mTitlePaint = new Paint();
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            int width = w / 8 * 7;
            int height = h / 8 * 7;
            mSrcBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            mDstBitmap = Bitmap.createBitmap(width-50, height-50, Bitmap.Config.ARGB_8888);
            drawDST();
        }
    
        private void drawTitle(Canvas canvas) {
            mTitlePaint.setColor(Color.RED);
            mTitlePaint.setFakeBoldText(true);
            mTitlePaint.setStyle(Paint.Style.FILL);
            mTitlePaint.setTextSize(30);
            canvas.drawText(mText, 0, getHeight()-10, mTitlePaint);
        }
    
        private void drawDST() {
            Canvas c = new Canvas(mSrcBitmap);
            Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
            p.setColor(0xFFFFCC44);
            c.drawOval(new RectF(10, 10, mSrcBitmap.getWidth(), mSrcBitmap.getHeight()), p);
        }
    
        private void drawSRC() {
            Canvas c = new Canvas(mDstBitmap);
            Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
            p.setColor(0xFF66AAFF);
            c.drawRect(30, 30, mDstBitmap.getWidth()-30, mDstBitmap.getHeight()-30, p);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawColor(Color.GRAY);
            int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
            canvas.drawBitmap(mSrcBitmap, 0, 0, mPaint);
    
            drawSRC();
            switch (mMode) {
                case 1:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
                    break;
                case 2:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
                    break;
                case 3:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
                    break;
                case 4:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
                    break;
                case 5:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
                    break;
                case 6:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
                    break;
                case 7:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST));
                    break;
                case 8:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
                    break;
                case 9:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
                    break;
                case 10:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
                    break;
                case 11:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
                    break;
                case 12:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
                    break;
                case 13:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));
                    break;
                case 14:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN));
                    break;
                case 15:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
                    break;
                case 16:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
                    break;
                case 17:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
                    break;
                case 18:
                    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.OVERLAY));
                    break;
            }
            canvas.drawBitmap(mDstBitmap, 90, 40, mPaint);
            mPaint.setXfermode(null);
            drawTitle(canvas);
            canvas.restoreToCount(layerId);
        }
    }
    

结束语

如果您觉得这篇文章能够帮助到您,请帮忙顶一下,您的鼓励是对我的最大支持!
如需转载请标明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值