2013-08-24 7 views
12

E 'possibile in Android impostare una vista in modo che applichi un filtro di colore a tutto ciò che è visibile nei suoi limiti? Come in questo esempio:Effetti colore PorterDuff in Android per visualizzazioni sotto una determinata vista

filtering view

Basta una semplice visione rettangolare che inverte i colori del tutto al di sotto di esso. Ovviamente quando l'utente scorre la lista si riflette anche nella casella invertita. C'è un modo semplice per farlo usando i filtri colorati, le modalità PorterDuff, ecc.?

risposta

12

Stai cercando di risolvere questo problema utilizzando una gerarchia vista come questa:

  • Parent
    • ListView
    • InverterView

Il problema è che, in questa posizione, InverterView non ha alcun controllo come viene disegnato ListView. Ma sai chi ha il controllo su come viene disegnato ListView? Il layout principale di ListView lo fa. In altre parole, ciò che si vuole veramente è una gerarchia simile a questo:

  • Parent
    • InverterLayout
      • ListView

Ora InverterLayout è responsabile per il disegno ListView, e possono applicare gli effetti ad esso.

class InverterLayout extends FrameLayout 
{ 
    // structure to hold our color filter 
    private Paint paint = new Paint(); 
    // the color filter itself 
    private ColorFilter cf; 
    // the rectangle we want to invert 
    private Rect inversion_rect = new Rect(100, 100, 300, 300); 

    public InverterLayout(Context context) 
    { 
     super(context); 
     // construct the inversion color matrix 
     float[] mat = new float[] 
     { 
      -1, 0, 0, 0, 255, 
      0, -1, 0, 0, 255, 
      0, 0, -1, 0, 255, 
      0, 0, 0, 1, 0 
     }; 
     cf = new ColorMatrixColorFilter(new ColorMatrix(mat)); 
    } 

    @Override protected void dispatchDraw(Canvas c) 
    { 
     // create a temporary bitmap to draw the child views 
     Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); 
     Canvas cc = new Canvas(b); 
     // draw them to that temporary bitmap 
     super.dispatchDraw(cc); 
     // copy the temporary bitmap to screen without the inversion filter 
     paint.setColorFilter(null); 
     c.drawBitmap(b, 0, 0, paint); 
     // copy the inverted rectangle 
     paint.setColorFilter(cf); 
     c.drawBitmap(b, inversion_rect, inversion_rect, paint); 
    } 
} 

Quando si utilizza questa, garantire la vostra vista bambino ha il suo sfondo. Se la vista è trasparente e lo sfondo della finestra viene visualizzato, lo sfondo della finestra non verrà invertito, poiché InverterLayout non ha alcun controllo su come viene disegnata la finestra.

1

Se potessi semplicemente commentare lo farei, perché non sono sicuro di essere corretto qui. Quindi, l'acquirente fa attenzione, eccola:

Penso che potresti riuscire a ottenere questo effetto sfruttando View.OnDragEve [] ntListener. Ecco lo documentation.

Penso che dovresti modificare il modello di trigger drag and drop utilizzato in Android (ovvero i mezzi di comunicazione tra app e sistema operativo). Il modo in cui lo modifichi dipenderà interamente dal meccanismo (o dai meccanismi) all'interno della tua app che forza una vista verso i limiti di un'altra. Una volta capito, puoi fare una magia a colori avanzata con: ColorMatrix, PorterDuffColorFilter e molti altri.

Questo mi sembra molto più semplice dell'alternativa Xfermode. In bocca al lupo!

1

Ecco cosa farei:

Vista gerarchia:

  • RelativeLayout (o FrameLayout)
    • ListView
      • CustomInverterView

InverterView viene posizionato dal OnTouch della vista primaria (RelativeLayout) nella onTouchListener:

if (event.getAction() == MotionEvent.ACTION_MOVE) 
      // Set Coordinates for the custom View. 
      // Copy the bitmapCache of the ListView (jsut the portion you need 
      // and send it to the customView. 
      // Apply the filters you want. 
      // Invalidate! 

ho implementato una lente utilizzando questo metodo. Esso funziona magicamente. Forse potrò postare qualche altro codice in seguito, ma al momento sono un po 'impegnato.

Problemi correlati