I'm trying to mask a FrameLayout with a mask defined as a nine patch. However, although it works fine on 5.0+ on older versions (such as 4.4.4), the patch leaves an opaque black background. Is there anything that can be done to avoid this other than drawing to an off screen bitmap before rendering to the screen or reverting to software layers?
public class MaskedLayout extends FrameLayout {
private final static PorterDuffXfermode DST_IN = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private NinePatchDrawable mMask;
private boolean mShowTail = true;
private boolean mReverseLayout;
public ChatBubbleLayout(Context context) {
this(context, null);
}
public ChatBubbleLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ChatBubbleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false);
setLayerType(LAYER_TYPE_HARDWARE, mPaint);
mMask = createMask(R.drawable.mask);
}
private NinePatchDrawable createMask(@DrawableRes int res) {
final Bitmap maskBitmap = BitmapFactory.decodeResource(getResources(), res);
final NinePatch patch = new NinePatch(maskBitmap, maskBitmap.getNinePatchChunk(), "Mask");
return new NinePatchDrawable(getResources(), patch);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w != oldw || h != oldh) {
mMask.setBounds(0, 0, w, h);
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
mMask.getPaint().setXfermode(DST_IN);
mMask.draw(canvas);
}
}
try this: