2013-08-24 22 views
12

Czy to możliwe w Androidzie ustawić widok w taki sposób, że stosuje filtr koloru do wszystkiego poniżej tego, co jest widoczne w jego granicach? Jak w poniższym przykładzie:Efekty kolorystyczne PorterDuff w Androidzie dla widoków pod danym widokiem

filtering view

tylko prosty prostokątny zdania, że ​​odwraca kolory wszystkiego poniżej. Oczywiście, gdy użytkownik przewija listę, jest to również odzwierciedlone w odwróconym polu. Czy jest jakiś łatwy sposób na to, używając filtrów kolorów, trybów PorterDuff itd.?

Odpowiedz

12

Starasz się rozwiązać ten problem za pomocą hierarchii widok jak to:

  • nadrzędna
    • ListView
    • InverterView

Problem jest w tym położeniu, InverterView nie ma kontroli nad jak narysowany jest ListView. Ale czy wiesz, kto ma kontrolę nad sposobem rysowania ListView? Macierzowy układ ListView. Innymi słowy, co naprawdę chcesz to hierarchia tak:

  • nadrzędna
    • InverterLayout
      • ListView

Teraz InverterLayout jest odpowiedzialny za opracowanie ListView, można zastosować efekty do niego.

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

Przy zastosowaniu tego zapewnić Pana zdaniem dziecko ma swoje własne tło. Jeśli widok jest przezroczysty i widać tło okna, to tło okna nie zostanie odwrócone, ponieważ InverterLayout nie ma kontroli nad sposobem rysowania okna.

1

Gdybym mógł po prostu skomentować, zrobiłbym to, ponieważ nie jestem pewien, czy mam tu rację. Więc kupujący uważaj, oto:

Myślę, że możesz być w stanie osiągnąć ten efekt, korzystając z View.OnDragEve [] ntListener. Oto documentation.

Myślę, że należy ulepszyć model wyzwalacza "przeciągnij i upuść" używany w Androidzie (tj. Sposób komunikacji między aplikacją a systemem operacyjnym). Sposób jego zmiany zależy wyłącznie od mechanizmu (ów) w aplikacji, który zmusza jeden widok do granic innego. Gdy już to określisz, możesz wykonać zaawansowaną magię kolorów za pomocą: ColorMatrix, PorterDuffColorFilter i kilku innych.

To brzmi dla mnie dużo łatwiej niż alternatywa Xfermode. Powodzenia!

1

Oto co zrobię:

Zobacz hierarchię:

  • RelativeLayout (lub FrameLayout)
    • ListView
      • CustomInverterView

InverterView zostaje umieszczona przez OnTouch widoku nadrzędnego (RelativeLayout) w 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! 

zaimplementowałem lupę tą metodą. To działa jak urok. Może później mogę zamieścić więcej kodu, ale jestem teraz trochę zajęty.