用于屏蔽父级并在父级中心创建透明圆的自定义视图

时间:2017-11-24 09:55:55

标签: android android-custom-view surfaceview android-framelayout

我想做一个圆形的suface视图(舷窗效果)。曲面视图位于Frame布局中。我想创建一个自定义视图,我可以在表面视图顶部添加到Frame布局,并屏蔽整个Frame布局以生成舷窗效果,以便表面视图显示为圆形。

我在Web和Stackoverflow上搜索了很多答案但是失败了。 然后我看到this问题,我尝试了这个自定义视图来掩盖框架布局(因此也是faceview),但我没有得到理想的结果。

我想要的是一个自定义视图,它可以获取它的父级的高度和宽度(父级是方形的形状),并在它的中心形成一个透明圆圈,触及边界中间的所有四个边,休息(视图 - 圆圈)该视图将是我可以设置的颜色。

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
}

}

请有人帮助我。提前谢谢。

1 个答案:

答案 0 :(得分:1)

这是一个视图的示例,它将整个视图绘制成粉红色并切割一个居中的圆形孔,使父级可见:


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,它将会删除先前绘制到画布上的所有内容,包括父级图。

可能有更好的解决方案,但这个很容易理解。