34

所以我尝试了这里的代码:Creating an ImageView with a mask。我使用以下图像作为原始图像和蒙版:

在此处输入图像描述在此处输入图像描述

但是,我得到的结果是这样的:

在此处输入图像描述

请注意,窗口背景不是黑色,而是全息光(在银河系上看起来像非常淡的灰色,而不是完全白色)。第二张图片是我在列表视图中选择项目时得到的结果。

相反,如果我使用相同的算法创建一个新的位图,然后将其传递给图像视图而不是覆盖 onDraw(),它会正确绘制:

Canvas canvas = new Canvas();
Bitmap mainImage = //get original image
Bitmap maskImage = //get mask image
Bitmap result = Bitmap.createBitmap(mainImage.getWidth(), mainImage.getHeight(), Bitmap.Config.ARGB_8888);

canvas.setBitmap(result);
Paint paint = new Paint();
paint.setFilterBitmap(false);

canvas.drawBitmap(mainImage, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(maskImage, 0, 0, paint);
paint.setXfermode(null);

imageView.setImageBitmap(result);

我得到了预期的结果:

在此处输入图像描述

请注意,淡化已正确应用。这在进行选择时更加明显。

那么 ImageView 的 onDraw 方法是如何创建这个黑色背景而不是让窗口背景显示出来的呢?有趣的是,如果原始图像本身具有一定的透明度,则尊重该透明度,例如:

在此处输入图像描述

我无法自己弄清楚。我宁愿能够在 onDraw 上执行此操作,而不是预先创建位图,因为它仅适用于作为源和掩码的位图。我希望能够使用渐变和纯色等其他可绘制对象来做到这一点,但在这些情况下,宽度和高度没有设置。

4

3 回答 3

28

在研究了所有 stackoverflow 帖子后,我找到了创建没有黑色边框的遮罩的完美组合。它非常适合我的目的。

目前我正在使用一个普通图像和一个遮罩图像(具有透明度的 png)创建一个可拖动视图,因此我需要覆盖 onDraw 函数。

private Bitmap mImage = ...;
private Bitmap mMask = ...;  // png mask with transparency
private int mPosX = 0;
private int mPosY = 0;

private final Paint maskPaint;
private final Paint imagePaint;

public CustomView (final Context context) {
    maskPaint = new Paint();
    maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

    imagePaint = new Paint();
    imagePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
}

/* TODO
 if you have more constructors, make sure you initialize maskPaint and imagePaint
 Declaring these as final means that all your constructors have to initialize them.
 Failure to do so = your code won't compile.
*/

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

    canvas.save();      
    canvas.drawBitmap(mMask, 0, 0, maskPaint);
    canvas.drawBitmap(mImage, mPosX, mPosY, imagePaint);
    canvas.restore();
}
于 2013-07-05T11:23:28.627 回答
2

回答我自己的问题。Xfermode 按预期工作。油漆使结果是画布透明(这是窗口活动使用的画布)。由于画布本身被设置为透明,窗口显示了它背后的东西:黑色背景。

为了正确地做到这一点,确实必须创建一个新的位图来保存 alpha 蒙版的结果。我更新了代码以考虑所有类型的可绘制对象。

于 2013-02-12T18:56:27.133 回答
0

在此代码中适用:

 mask_over = BitmapFactory.decodeResource(
            getResources(), mask_over1[0]);
    icon = Bitmap.createScaledBitmap(icon, screenwidth, screenwidth, false);
    mask_over = Bitmap.createScaledBitmap(mask_over, screenwidth, screenwidth, false);
             back_img=createBitmap_ScriptIntrinsicBlur(Bitmap.createScaledBitmap(cropview.croppedImage, screenwidth, screenwidth, false),25.0f);
    LinearLayout.LayoutParams layoutParams111 = new LinearLayout.LayoutParams(screenwidth, screenwidth);
于 2017-09-15T04:26:52.600 回答