0

Я пытаюсь замаскировать FrameLayout маской, определенной как девять патчей. Однако, хотя он работает отлично на 5.0+ в более старых версиях (например, 4.4.4), патч оставляет непрозрачный черный фон. Есть ли что-то, что можно сделать, чтобы избежать этого, кроме как рисовать на растровое изображение вне экрана, прежде чем отображать на экране или возвращаться к слоям программного обеспечения?PorterDuff маскирует листья непрозрачным черным фоном

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); 
    } 
} 

ответ

3

попробовать это:

public class MaskedLayout extends FrameLayout { 

    private NinePatchDrawable mMask; 

    public MaskedLayout(Context context) { 
     this(context, null); 
    } 

    public MaskedLayout(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public MaskedLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     mMask = (NinePatchDrawable) getResources().getDrawable(R.drawable.mask); 
     mMask.getPaint().setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); 
    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 
     mMask.setBounds(0, 0, w, h); 
    } 

    @Override 
    protected void dispatchDraw(Canvas canvas) { 
     canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG); 
     super.dispatchDraw(canvas); 
     mMask.draw(canvas); 
     canvas.restore(); 
    } 
} 
+0

и если вы хотите какой-либо 'Drawable' чтобы "замаскировать" ваш' FrameLayout' вам нужно будет еще один "слой" ('saveLayer()'), как нет способ доступа к объекту 'Drawable' 'Paint' – pskink

+0

Спасибо, я скоро отдам это. Будет ли использование saveLayer иметь производительность при рендеринге представления? И знаете ли вы, почему код работает на 5.0, но не на 4.x? – Kingamajick

+0

не должно быть значительного влияния, на устройствах pre v4 он использовался, например, для альфа-анимаций, которые были вызваны с 20 + fps, и эти устройства не были демонами скорости, я понятия не имею, почему это не сработало 4.4 – pskink

Смежные вопросы