自定义视图以屏蔽父级并在父级中心制作透明圆圈

Custom view to mask a parent and make transparent circle at center of parent

我想做一个圆形表面视图(舷窗效果)。表面视图位于框架布局内。我想制作一个自定义视图,我可以将其添加到表面视图顶部的框架布局并遮盖整个框架布局以产生舷窗效果,以便表面视图显示为圆形。

我在 Web 和 Whosebug 上搜索了很多答案但都失败了。 然后我看到了 问题,我尝试使用这个自定义视图来屏蔽框架布局(以及表面视图),但我没有得到想要的结果。

我想要的是一个自定义视图,它可以采用其父级(父级为正方形)的高度和宽度,并在其中心制作一个透明圆,接触边界中间的所有四个边,休息(视图 -圆圈)将是我可以设置的颜色。

public class FocusView extends View {

private Paint mTransparentPaint;
private Paint mSemiBlackPaint;
private Path mPath = new Path();

public static float radius , xCor , yCor;

public FocusView(Context context) {
    super(context);
    initPaints();
}

public FocusView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initPaints();
}

public FocusView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initPaints();
}

private void initPaints() {
    mTransparentPaint = new Paint();
    mTransparentPaint.setColor(Color.GREEN);
    mTransparentPaint.setStrokeWidth(10);

    mSemiBlackPaint = new Paint();
    mSemiBlackPaint.setColor(Color.TRANSPARENT);
    mSemiBlackPaint.setStrokeWidth(10);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    mPath.reset();

    mPath.addCircle(xCor,yCor,radius, Path.Direction.CW);
    mPath.setFillType(Path.FillType.INVERSE_EVEN_ODD);

    canvas.drawCircle(xCor,yCor,radius, mTransparentPaint);

    canvas.drawPath(mPath, mSemiBlackPaint);
    canvas.clipPath(mPath);
    canvas.drawColor(Color.parseColor("#FFFFFF"));        //A6000000
}

}

如果有人能帮助我,请帮忙。提前致谢。

这是将整个视图涂成粉红色并切出一个居中的圆孔使父级可见的视图示例:


public class FocusView extends View {

    private Paint mCutPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Bitmap mBitmap;
    private Canvas mInternalCanvas;

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

    public FocusView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FocusView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        mCutPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        if (mInternalCanvas != null) {
            mInternalCanvas.setBitmap(null);
            mInternalCanvas = null;
        }

        if (mBitmap != null) {
            mBitmap.recycle();
            mBitmap = null;
        }

        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mInternalCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mInternalCanvas == null || mBitmap == null) {
            return;
        }

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

        // make the radius as large as possible within the view bounds
        final int radius = Math.min(width, height) / 2;

        mInternalCanvas.drawColor(0xFFFF00FF);
        mInternalCanvas.drawCircle(width / 2, height / 2, radius, mCutPaint);

        canvas.drawBitmap(mBitmap, 0, 0, null);
    }
}

首先绘制到内部 Bitmap 的原因是,如果您将 PorterDuff.Mode.CLEAR 应用于原始 Canvas,它将删除之前绘制到 [=20] 的所有内容=],包括父视图。

可能有更好的解决方案,但这个很简单易懂。