【问题标题】:Android View/Layout MaskingAndroid 视图/布局遮罩
【发布时间】:2014-04-25 19:51:13
【问题描述】:

我有一个应用程序需要使用自定义图像屏蔽整个 RelativeLayout(现在是扩展它的自定义视图)。布局中有许多视图需要通过触摸来访问,并且是动态的。

我已经使用另一个问题的答案成功地掩盖了区域绘图形状:

@Override
protected void dispatchDraw(Canvas canvas) {
    Path path = new Path();
    int count = canvas.save();

    path.addCircle(400, 200, 300, Path.Direction.CW);

    canvas.clipPath(path);

    super.dispatchDraw(canvas);
    canvas.restoreToCount(count);

}

但是,我需要使用图像源作为我的蒙版源,而不是我可以创作的形状。我已经使用 PorterDuff 工具包来更改位图:

    Bitmap resizedBitmap = Bitmap.createScaledBitmap(mMask, this.getWidth(), this.getHeight(), false);
    Bitmap result = Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.ARGB_8888); //create another bitmap with same height

    Canvas mCanvas = new Canvas(result);
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    mCanvas.drawBitmap(resizedBitmap, 0, 0, paint);
    paint.setXfermode(null);
    onDrawCanvas.drawBitmap(result, 0,0, paint);

这适用于屏蔽图像,但我需要使用剪辑进行屏蔽(我认为)。有没有办法使用不同的 PorterDuff 模式从该图像派生路径?还是有更简单的方法,就像在 iOS 中可以直接使用图像设置 layerMask 一样?提前致谢。

【问题讨论】:

    标签: android android-relativelayout mask


    【解决方案1】:

    框架中没有直接的 API 可让您跟踪实心图像蒙版并生成可用于剪辑的Path。如果您可以以 SVG 的形式访问掩码内容,则可以使用 Romain Guy 在此处描述的路径跟踪技术: http://www.curious-creature.org/2013/12/21/android-recipe-4-path-tracing/

    虽然这不是我最喜欢的技术,但我见过的最佳选择基本上是您已经描述的项目的组合。我们需要创建一个可以渲染视图内容的离屏缓冲区(通过 Canvas+Bitmap),然后使用传输模式技术将结果应用到附加到窗口的 Canvas 上。我没有在调度中使用ViewGroup 尝试过这个,但它应该可以工作。以下(未经测试的)代码将是一个起点:

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (w != oldw || h != oldh) {
            //Create an area to use for content rendering
            mCanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mCanvasBitmap);
            mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        }
    }
    
    @Override
    protected void dispatchDraw(Canvas canvas) {
        //Render contents into our buffer
        super.dispatchDraw(mCanvas);
    
        //Render the mask, clipping with a PorterDuffXfermode
        paint.setXfermode(mXfermode);
        mCanvas.drawBitmap(mMask, 0, 0, paint);
    
        //Clear state and transfer result
        paint.setXfermode(null);
        canvas.drawBitmap(mCanvasBitmap, 0, 0, paint);
    }
    

    这种方法的一个缺点是内存;对于足够大的视图,您必须分配一个与视图容器大小相等的额外块。我们可以通过执行一次并重用缓冲区来最小化这种影响。

    【讨论】:

    • 我尝试了您建议的两种方法。使用 SVG 的路径跟踪有效,但在遮罩曲线上有点不稳定。我最终选择了位图解决方案。谢谢!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 2013-08-25
    • 2017-09-28
    • 1970-01-01
    • 2022-10-23
    • 2019-08-29
    • 2015-06-20
    相关资源
    最近更新 更多