0

Ich versuche, ein FrameLayout mit einer Maske als neun Patch zu maskieren. Auch wenn es bei älteren Versionen (z. B. 4.4.4) unter 5.0+ funktioniert, hinterlässt der Patch einen undurchsichtigen schwarzen Hintergrund. Gibt es etwas, das getan werden kann, um dies zu vermeiden, abgesehen von dem Zeichnen auf eine Bitmap außerhalb des Bildschirms, bevor auf dem Bildschirm gerendert oder zu Software-Layern zurückgekehrt wird?PorterDuff Maskierung verlässt opak schwarzen Hintergrund

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

Antwort

3

versuchen Sie dies:

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

und wenn Sie 'Drawable' wollen "Maske" Ihr' FrameLayout' müssten Sie eine weitere "Schicht" ('saveLayer()'), da es keine ist Weg zu 'Drawable's' Paint' Objekt – pskink

+0

Danke, ich werde es in Kürze versuchen. Wird die Verwendung von saveLayer eine Performancekosten beim Rendern der Ansicht haben? Und wissen Sie, warum der Code auf 5.0 aber nicht 4.x funktioniert? – Kingamajick

+0

sollte es keinen wesentlichen Einfluss haben, auf Pre-v4-Geräten wurde es zum Beispiel für Alpha-Animationen verwendet, die mit 20+ fps aufgerufen wurden, und diese Geräte waren keine Geschwindigkeitsdämonen, ich habe keine Ahnung, warum es nicht funktioniert hat 4.4 – pskink

Verwandte Themen