上篇文章那个需求,我用了clip path,最后发现不行(主要是安卓的白色=透明),最后还是打算用setXfermode这个方式


先复制下参数的意思

Android setXfermode

这张图片从一定程度上形象地说明了图形混合的作用,两个图形一圆一方通过一定的计算产生不同的组合效果,在API中Android为我们提供了18种(比上图多了两种ADD和OVERLAY)模式: 

  ADD:饱和相加,对图像饱和度进行相加,不常用

  CLEAR:清除图像

  DARKEN:变暗,较深的颜色覆盖较浅的颜色,若两者深浅程度相同则混合

  DST:只显示目标图像

  DST_ATOP:在源图像和目标图像相交的地方绘制【目标图像】,在不相交的地方绘制【源图像】,相交处的效果受到源图像和目标图像alpha的影响

  DST_IN:只在源图像和目标图像相交的地方绘制【目标图像】,绘制效果受到源图像对应地方透明度影响

  DST_OUT:只在源图像和目标图像不相交的地方绘制【目标图像】,在相交的地方根据源图像的alpha进行过滤,源图像完全不透明则完全过滤,完全透明则不过滤

  DST_OVER:将目标图像放在源图像上方

  LIGHTEN:变亮,与DARKEN相反,DARKEN和LIGHTEN生成的图像结果与Android对颜色值深浅的定义有关

  MULTIPLY:正片叠底,源图像素颜色值乘以目标图像素颜色值除以255得到混合后图像像素颜色值

  OVERLAY:叠加

  SCREEN:滤色,色调均和,保留两个图层中较白的部分,较暗的部分被遮盖

  SRC:只显示源图像

  SRC_ATOP:在源图像和目标图像相交的地方绘制【源图像】,在不相交的地方绘制【目标图像】,相交处的效果受到源图像和目标图像alpha的影响

  SRC_IN:只在源图像和目标图像相交的地方绘制【源图像】

  SRC_OUT:只在源图像和目标图像不相交的地方绘制【源图像】,相交的地方根据目标图像的对应地方的alpha进行过滤,目标图像完全不透明则完全过滤,完全透明则不过滤

  SRC_OVER:将源图像放在目标图像上方

  XOR:在源图像和目标图像相交的地方之外绘制它们,在相交的地方受到对应alpha和色值影响,如果完全不透明则相交处完全不绘制


我实现的效果

Android setXfermode

中间终于镂空了


核心代码

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(b, rect, rect, paint);

    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
    paint.setColor(Color.parseColor("#FFFFFF"));

    canvas.drawCircle(x,y,radius,paint);
}

安卓白色=透明的解决方式,我找了白色的图片,绘制。就是上面的b

这里,b就是源图片,circle就是目标图片,XOR就是如果相交了,相交部分不画,另外的只画源文件


最后发现还不行 需要开启硬件加速

setLayerType(View.LAYER_TYPE_SOFTWARE, null);


全部代码

public class MyClip extends View {
    private static final String TAG = "xbh";

    public MyClip(@NonNull Context context) {
        super(context);
    }

    private Bitmap b;

    public MyClip(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        paint = new Paint();

//        setWillNotDraw(false);

        b = ((BitmapDrawable) context.getResources().getDrawable(R.drawable.white)).getBitmap();
    }

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

    public MyClip(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private int width;
    private int height;

    private Rect rect;

    private int x;
    private int y;
    private int radius;

    private Paint paint;

    @SuppressLint("DrawAllocation")
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        width = getWidth();
        height = getHeight();

        rect = new Rect(0, 0, width, height);

        radius = width >> 2;
        x = width >> 1;
        y = 4 * radius / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(b, rect, rect, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
        paint.setColor(Color.parseColor("#FFFFFF"));

        canvas.drawCircle(x,y,radius,paint);
    }
}

相关文章:

  • 2022-01-14
  • 2021-08-01
  • 2021-11-11
  • 2021-06-01
  • 2021-12-27
  • 2021-05-19
猜你喜欢
  • 2021-05-16
  • 2021-04-17
  • 2021-07-01
  • 2021-07-10
  • 2021-11-21
  • 2021-04-16
  • 2022-01-16
相关资源
相似解决方案