高级UI<第十六篇>:Xfermode 详解
文章参考了各个击破搞明白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
- 这里新建了一个图层,分别画了三个图形,假设分别为A(黄)、B(绿)、C(红 )
- 代码中将红色图片设置了混合模式,所以红色图片为源图,黄色图片和绿色图片的并集为目标图
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
现象:
叠加。
[本章完...]