2014-11-10 13 views
5

Chcę zrobić animację w RecyclerView, która wymaga, aby dziecko miało większy indeks Z niż inne dziecko. Jednak gdy użyłem metody bringToFront w , to nie zadziałało.bringToFront nie działa w RecyclerView

Czy istnieje sposób, aby przyprowadzić dziecko do przodu w RecyclerView?

Odpowiedz

4

Kolejność dzieci jest kontrolowana przez LayoutManager. Zbudowany w LayoutManagers mają swój własny surowy porządek podrzędny ze względu na wydajność.

Obecna implementacja bringToFront po prostu przenosi dziecko na koniec listy dzieci, która nie będzie ładnie działała z istniejącymi użytkownikami LayoutManagers.

W przypadku kierowania na Lollipop można użyć metody setElevation. Aby kierować reklamy na starsze platformy, potrzebujesz niestandardowego menedżera LayoutManager, który nie jest zależny od kolejności dzieci.

+1

Dzięki, ale zwyczaj LayoutManager może budzić pewną złożoność, udało mi się zrobić jakąś sztuczkę sklonować pogląd Chcę animować. – Juude

7

Rzeczywiście, bringToFront() nie pomaga; zmienia po prostu kolejność elementów podrzędnych w tablicy potomnej rodzica, ale nie zmienia kolejności, w jakiej są renderowane elementy podrzędne.

Jeśli używasz interfejsu API-21 lub nowszego, możesz po prostu zmienić wartość widoku Z (view.setZ(..)) w celu przeniesienia go na wierzch.

Poniżej interfejsu API-21 można użyć wywołania zwrotnego: RecyclerView.ChildDrawingOrderCallback. Dzięki niemu możesz zdefiniować kolejność, w jakiej dzieci powinny być renderowane. (Możesz także użyć tego z API-21 +, jeśli nie podoba ci się dodatkowy cień, który otrzymujesz, zmieniając wartość Z.)

Przykład:

final int indexOfFrontChild = rv.indexOfChild(desiredFrontView); 
rv.setChildDrawingOrderCallback(new RecyclerView.ChildDrawingOrderCallback() { 

    private int nextChildIndexToRender; 

    @Override 
    public int onGetChildDrawingOrder(int childCount, int iteration) { 
     if (iteration == childCount - 1) { 
      // in the last iteration return the index of the child 
      // we want to bring to front (and reset nextChildIndexToRender) 
      nextChildIndexToRender = 0; 
      return indexOfFrontChild; 
     } else { 
      if (nextChildIndexToRender == indexOfFrontChild) { 
       // skip this index; we will render it during last iteration 
       nextChildIndexToRender++; 
      } 
      return nextChildIndexToRender++; 
     } 
    } 
}); 
rv.invalidate(); 

Zasadniczo onGetChildDrawingOrder(...) zostanie wywołana childCount razy iw każdym iteration możemy określić, które dziecko do renderowania (wracając swój indeks).

+1

Próbowałem tego kodu. Powoduje awarię aplikacji po jej użyciu podczas próby przewinięcia okna RecyclerView. – 0101100101

+0

@ 0101100101, czy na pewno twoja indexOfFrontChild jest w zakresie [0, childCount-1]? Lub zapytać inaczej, czy jesteś pewien, że wybrany FrontView jest dzieckiem Twojego RecyclerView? –

+1

Obie tak. Animacja faktycznie działa doskonale z tym kodem, a jedynie przewijanie po tym nie działa. – 0101100101

0

Odpowiedź powyżej przez @Zsolt Safrany opiera się na założeniu, że wywołanie zwrotne jest zawsze wywoływane z iteracji 0, co, jak testowałem, nie jest prawdą.

Tutaj zamieszczam działającą implementację, która nie jest przekazywana na zewnętrzny licznik.

//index of item you want to be displayed on top 
private int indexOfFrontChild = 2; 

    @Override 
     public int onGetChildDrawingOrder(int childCount, int iteration) { 
      int childPos = iteration; 
      //index must be in at least smaller than all children's 
      if (indexOfFrontChild < childCount) { 
       //in the last iteration we return view we want to have on top 
       if (iteration == childCount - 1) { 
        childPos = indexOfFrontChild; 
       }else if (iteration >= indexOfFrontChild) { 
        childPos = iteration + 1; 
       } 
      } 
      return childPos; 
     } 

W moim przypadku przedmioty były w stanie zmienić ich wysokość, więc 1 pozycja mogła zająć cały ekran. Więc dobrze jest sprawdzić, czy pozycja indexOfFrontChild jest wyświetlanych

if (indexOfFrontChild < childCount) 
Powiązane problemy