Android PorterDuff模式中Source和Destination分别对应什么
问题解答
1. PorterDuff的Destination到底是什么?
PorterDuff混合计算的目标(DST)仅指代当前你正在绘制的Canvas缓冲区内,在执行本次绘制操作前已经存在的像素内容,和其他独立View的绘制内容没有任何关联。
你当前的CustomView独立绘制时,onDraw方法触发时系统传入的Canvas初始状态是仅包含当前CustomView自身的背景(如果没有设置背景就是完全透明的空缓冲区),你没有在调用drawBitmap前向这个Canvas绘制任何内容,所以此时DST就是空的透明缓冲区。
2. 为什么使用DST模式没有内容显示?
PorterDuff.Mode.DST的规则是完全保留DST区域的内容,丢弃本次要绘制的SRC内容。你当前CustomView的Canvas缓冲区初始为空,自然不会有任何内容被渲染出来。
3. 两个独立View能不能直接做PorterDuff混合?
默认不行。Android的每个View默认是独立绘制到窗口的Surface上的,各自的Canvas缓冲区互相隔离,不存在共享的绘制上下文,所以不会自动跨View做混合计算。
4. 实现跨View混合效果的正确方案
有两种常用实现方式:
- 方案1:开启父容器的离屏缓冲
将ImageView和CustomView放在同一个父ViewGroup中,给父ViewGroup设置图层类型为硬件加速离屏层:
开启后整个父容器的所有子View都会按绘制顺序绘制到同一个离屏缓冲区内:先绘制下层ImageView的内容到缓冲区(成为后续绘制的DST),再绘制上层CustomView的内容,此时CustomView设置的PorterDuff规则就能和下层ImageView的内容正常混合。parentViewGroup.setLayerType(View.LAYER_TYPE_HARDWARE, null); - 方案2:合并绘制逻辑到同一个View
直接把ImageView显示的Bitmap传入CustomView,在onDraw里先绘制ImageView的Bitmap,再设置Xfermode绘制你的自定义Bitmap,所有操作都在同一个Canvas内完成,无需处理跨View的问题:@Override protected void onDraw(Canvas canvas) { // 先绘制原图像作为DST canvas.drawBitmap(imageViewBitmap, 0, 0, null); // 设置混合模式 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); // 绘制mask作为SRC canvas.drawBitmap(maskBitmap, 0, 0, paint); // 清除Xfermode避免影响后续绘制 paint.setXfermode(null); }
内容的提问来源于stack exchange,提问作者Nafia Mahjabin
相关产品推荐
相关产品推荐

