Android视图/布局屏蔽

时间:2014-04-25 19:51:13

标签: android relativelayout mask

我有一个应用程序要求整个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);

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

1 个答案:

答案 0 :(得分:2)

框架中没有直接的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);
}

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