【问题标题】:Custom view to mask a parent and make transparent circle at center of parent自定义视图以掩盖父级并在父级中心制作透明圆圈
【发布时间】:2017-11-24 09:55:54
【问题描述】:

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

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

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

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
}

}

如果有人可以帮助我,请。提前致谢。

【问题讨论】:

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


【解决方案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,它将删除之前绘制到画布上的所有内容,包括父视图。

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

【讨论】:

  • 您能解释一下mInternalCanvas的用途吗?
  • mInternalCanvas 用于绘制到临时位图。如果你在给onDraw的画布上使用mCutPaint,你会剪掉在视图之前绘制的所有东西,所以你也会在父级上剪一个洞,导致一个黑色圆圈而不是一个切穿给父母。但是,如果您首先在自己的 Canvas 上绘制,则可以安全地切开整个内容,然后将结果绘制到 onDraw 提供的 Canvas 上。我希望这可以清除它,否则您可以尝试将绘制命令应用于原始画布并亲自查看会发生什么:)
  • 知道了!再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-10
  • 2012-03-26
  • 2017-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多