自定义控件

高级UI<第十六篇>:Xfermode 详解

2019-11-28  本文已影响0人  NoBugException

文章参考了各个击破搞明白PorterDuff.Mode这篇文章,所以本人只演示效果:

案例中涉及到图层,了解图层的使用请看高级UI<第十七篇>:Canvas图层的概念(saveLayer)

代码

public class PorterDuffXfermodeView extends View {

    private Paint mPaint;
    private Xfermode mXfermode;
    private PorterDuff.Mode xfermodemode = PorterDuff.Mode.CLEAR;    //混合模式常量
    private int measureWidth;//父布局宽度
    private int measureHeight;//父布局高度
    private int OFFSET = 100;//偏移量

    public PorterDuffXfermodeView(Context context) {
    super(context);
    init();
    }

    public PorterDuffXfermodeView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init();

    }

    public PorterDuffXfermodeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public PorterDuffXfermodeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    init();
    }

    /**
     * 初始化数据
     */
    private void init(){
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
    //生成混合模式对象
    mXfermode = new PorterDuffXfermode(xfermodemode);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    measureWidth = MeasureSpec.getSize(widthMeasureSpec);
    measureHeight = MeasureSpec.getSize(heightMeasureSpec);

    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.parseColor("#cc99ff"));
    int saveCount1 = canvas.saveLayer(OFFSET,OFFSET,measureWidth - OFFSET,measureHeight - OFFSET,mPaint, Canvas.ALL_SAVE_FLAG);
    mPaint.setColor(Color.YELLOW);
    canvas.drawCircle(300, 300, 100, mPaint);
    canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.dst),null, new RectF(100, 100, 500, 500), mPaint);
    mPaint.setXfermode(mXfermode);
    canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.src), null, new RectF(100, 100, 500, 500), mPaint);
    mPaint.setXfermode(null);
    canvas.restoreToCount(saveCount1);

    }
}

混合模式的代码已经注释,效果如下


图片.png
Sa:全称为Source alpha,表示源图的Alpha通道;
Sc:全称为Source color,表示源图的颜色;
Da:全称为Destination alpha,表示目标图的Alpha通道;
Dc:全称为Destination color,表示目标图的颜色.
(1)混合模式之CLEAR

将注释打开, 常量设置如下:

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.CLEAR;    //混合模式常量

效果如下


图片.png

现象:
清除源图的所有alpha和颜色值;

(2)混合模式之SRC

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.SRC;    //混合模式常量

效果如下


图片.png

现象:
只绘制源图的alpha和颜色值

(3)混合模式之DST

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.DST;    //混合模式常量

效果如下


图片.png

现象:
只绘制目标图

(4)混合模式之SRC_OVER

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.SRC_OVER;    //混合模式常量

效果如下


图片.png

现象:

在目标图像的顶部绘制源图像。

(5)混合模式之DST_OVER

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.DST_OVER;    //混合模式常量

效果如下


图片.png

现象:

在源图像的顶部绘制目标图像

(6)混合模式之SRC_IN

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.SRC_IN;    //混合模式常量

效果如下


图片.png

现象:
只在源图像和目标图像相交的地方绘制源图像

(7)混合模式之DST_IN

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.DST_IN;    //混合模式常量

效果如下


图片.png

现象:
只在源图像和目标图像相交的地方绘制目标图像

(8)混合模式之SRC_OUT

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.SRC_OUT;    //混合模式常量

效果如下


图片.png

现象:
只在源图像和目标图像不相交的地方绘制源图像

(9)混合模式之DST_OUT

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.DST_OUT;    //混合模式常量

效果如下


图片.png

现象:
只在源图像和目标图像不相交的地方绘制目标图像

(10)混合模式之SRC_ATOP

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.SRC_ATOP;    //混合模式常量

效果如下


图片.png

现象:
在源图像和目标图像相交的地方绘制源图像,在不相交的地方绘制目标图像

(11)混合模式之DST_ATOP

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.DST_ATOP;    //混合模式常量

效果如下


图片.png

现象:
在源图像和目标图像相交的地方绘制目标图像,在不相交的地方绘制源图像

(12)混合模式之XOR

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.XOR;    //混合模式常量

效果如下


图片.png

现象:
在源图像和目标图像重叠之外的任何地方绘制他们,而在不重叠的地方不绘制任何内容

(13)混合模式之MULTIPLY

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.MULTIPLY;    //混合模式常量

效果如下


图片.png

现象:
将每个位置的两个像素相乘,除以255,然后使用该值创建一个新的像素进行显示。结果颜色=顶部颜色*底部颜色/255

(14)混合模式之ADD

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.ADD;    //混合模式常量

效果如下


图片.png

现象:饱和度相加

(15)混合模式之SCREEN

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.SCREEN;    //混合模式常量

效果如下


图片.png

现象:
反转每个颜色,执行相同的操作(将他们相乘并除以255),然后再次反转。结果颜色=255-(((255-顶部颜色)*(255-底部颜色))/255)

(16)混合模式之LIGHTEN

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.LIGHTEN;    //混合模式常量

效果如下

图片.png

现象:
获得每个位置上两幅图像中最亮的像素并显示

(17)混合模式之DARKEN

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.DARKEN;    //混合模式常量

效果如下


图片.png

现象:
获得每个位置上两幅图像中最暗的像素并显示

(18)混合模式之OVERLAY

常量设置如下

private PorterDuff.Mode xfermodemode = PorterDuff.Mode.OVERLAY ;    //混合模式常量

效果如下


图片.png

现象:

叠加。

[本章完...]

上一篇下一篇

猜你喜欢

热点阅读