2016-01-29 11 views
6

Chcę animować zmianę mojego RecyclerView s GridLayoutManager. I wadliwy pokazuje listę elementów w siatce z 3 kolumnami, a użytkownik może wybrać wyświetlanie mniej więcej kolumn.RecyclerView - animowana zmiana kolumn menedżera układu siatki

Chciałbym, aby views w RecyclerView przesuwać/skalować do ich nowych pozycji, ale nie mam pojęcia, jak to zrobić.

Co chcę w końcu

  • umożliwiają skalowanie sieci poprzez rozwijanie/zamówienia dotykowym gest => wiem jak to zrobić
  • animować zmiana LayoutManager

Czy ktoś wie, w jaki sposób mogę animować zmianę LayoutManager?

+0

można spojrzeć na podobnym [Pytanie] (http://stackoverflow.com/questions/26539663/how-do-i-use-a-gridlayoutanimation-in-a-recyclerview) i pokrewnych [ gist] (https://gist.github.com/Musenkishi/8df1ab549857756098ba) – Droidekas

+0

Następnie wywołanie 'setSpanCount', po którym następuje' notifyDatasetChanged() '? – Droidekas

+0

Innym sposobem, w jaki widzę, że robi się to przy założeniu bardzo dużej rozpiętości (100 lub więcej) i gestem przedmiotu, możesz zmienić rozmiar rozpiętości dla wszystkich pozycji. – Droidekas

Odpowiedz

11

Źródłem inspiracji tutaj byłoby aplikację Zdjęcia Google, akcje Sony App Gallery

Istnieją zasadniczo dwa podejścia można przejść z:

  1. modyfikować spancount z GridLayoutManager korzystania setSpanCount(int)

  2. Ustawiasz bardzo dużą rozpiętość (~ 100) użyj SpanSizeLookUp, aby zmienić na pozycję spanSize w locie.

    • Użyłem Gist dostarczone przez Musenkishi dla this answer zapewnienie animatora do animowania zmian w układzie siatki zmienia
    • Użyłem tego podejścia w sample GitHub project wykonawczych takie same.
    • Ostrzeżenia:
      • Mam aktualnie używany kliknij słuchacza zachować modyfikację tych wielkości rozpiętość up.This wygląd może zostać zmieniona na ItemGestureListener uchwycić dociskowe wydarzenia zoom i zmienić odpowiednio.
      • Musisz określić sposób wyboru liczenia rozpiętości tak, że wszystkie elementy w jednym rzędzie zajmują całą szerokość ekranu (a więc nie widać żadnej pustej przestrzeni)
      • zadzwonić notifyItemRangeChanged użyciu runnable słupek opóźnione od nie można wywoływać metod notifyChanged z poziomu bindView/createView itp.
      • Po zmianie rozmiaru rozpiętości, trzeba notifyItemRangeChanged z odpowiednim zakresie, tak aby wszystkie elementy aktualnie wyświetlane na ekranie są przesunięte accordingly.I wykorzystali (kod na dole)

To nie jest kompletne rozwiązanie, ale rozwiązanie 2 godzinne na to samo.Możesz oczywiście poprawić wszystkie wymienione punkty :). Mam nadzieję, że będę aktualizować próbkę, ponieważ tego rodzaju widoki zawsze mnie fascynowały. Nie należy traktować tego jako ostatecznego rozwiązania, ale po prostu szczególny sposób osiągnięcia tego podejścia. Jeśli zamiast tego użyjesz StaggerredLayoutManager, możesz łatwo uniknąć pustych spacji między przedmiotami.

public int calculateRange() { 
    int start = ((GridLayoutManager)  grv.getLayoutManager()).findFirstVisibleItemPosition(); 
    int end = ((GridLayoutManager) grv.getLayoutManager()).findLastVisibleItemPosition(); 
    if (start < 0) 
     start = 0; 
    if (end < 0) 
     end = getItemCount(); 
    return end - start; 
    } 
+1

Dzięki za to (o wiele łatwiejsze niż myślałem) rozwiązanie. Zmiana licznika rozpiętości (sam mogłem o tym pomyśleć) jest sposobem na przejście do IMHO. Ożywia całkiem dobrze. A po zmianie, po prostu wywołanie adapterów 'notifyItemRangeChanged' uruchomi animację poprawnie ... Jedyną wadą jest (ale nie pytałem o więcej w moim pytaniu), musisz użyć' GridLayoutManager' tylko i nie można przełączać pomiędzy różne 'LayoutManagers' ... Chociaż, jeśli chcesz,' GridLayoutManager' obsługuje również 1 kolumnę i dlatego może być przynajmniej używany jako 'LinearLayoutManager' również ... – prom85

+1

Jeśli naprawdę chcesz wygładzić animacje więcej i poprawić wydajność w układach z jedną kolumną, polecam pracować nad budowaniem własnego menedżera układu: [This] (http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/) przewodnik jest całkiem niezły. – Droidekas

+0

@Droidekas, czy możesz pomóc mi w tworzeniu animacji na Androidzie 7? (dzieje się to z szybkimi kaflami po rozwinięciu cienia - są one w jednym wierszu elementów, a następnie rozszerzają się do siatki o wymiarach 3x3.) –

1

Mam do czynienia z tym samym problemem co ty, a do tej pory nie znalazłem dobrego rozwiązania.

Prosta zmiana liczby kolumn w GridLayoutManager wydaje się dziwna, więc na razie używam animacji do zanikania/w całym układzie. Coś takiego:

private void animateRecyclerLayoutChange(final int layoutSpanCount) { 
    Animation fadeOut = new AlphaAnimation(1, 0); 
    fadeOut.setInterpolator(new DecelerateInterpolator()); 
    fadeOut.setDuration(400); 
    fadeOut.setAnimationListener(new Animation.AnimationListener() { 
     @Override 
     public void onAnimationStart(Animation animation) { 
     } 

     @Override 
     public void onAnimationRepeat(Animation animation) { 
     } 

     @Override 
     public void onAnimationEnd(Animation animation) { 
      productsRecyclerLayoutManager.setSpanCount(layoutSpanCount); 
      productsRecyclerLayoutManager.requestLayout(); 
      Animation fadeIn = new AlphaAnimation(0, 1); 
      fadeIn.setInterpolator(new AccelerateInterpolator()); 
      fadeIn.setDuration(400); 
      productsRecycler.startAnimation(fadeIn); 
     } 
    }); 
    productsRecycler.startAnimation(fadeOut); 
} 

Jeśli połączyć fade out/in animacji ze skalowaniem każdy widoczny element, to będzie przyzwoity animacja zmian GridLayoutManager.

+0

Mam podobne rozwiązanie obecnie ... Usuwanie wszystkich przedmiotów, zmiana Menedżer układu i dodanie z powrotem wszystkich elementów spowoduje również animację, ale też nie jest doskonały ... Dzięki za tę alternatywę. – prom85

1

Można to zrobić z „wykrywacz gest” zobaczyć przykładowy tutorial tutaj http://wiki.workassis.com/pinch-zoom-in-recycler-view/ W tym tutorialu będziemy pobierać obrazy z galerii i pokazać je w układzie siatki w widoku recyklera. Będziesz mógł zmienić układ gestem. Poniżej przedstawiono zrzuty ekranu różnych układów.

mScaleGestureDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.SimpleOnScaleGestureListener() { 
       @Override 
       public boolean onScale(ScaleGestureDetector detector) { 
        if (detector.getCurrentSpan() > 200 && detector.getTimeDelta() > 200) { 
         if (detector.getCurrentSpan() - detector.getPreviousSpan() < -1) { 
          if (mCurrentLayoutManager == mGridLayoutManager1) { 
           mCurrentLayoutManager = mGridLayoutManager2; 
           mRvPhotos.setLayoutManager(mGridLayoutManager2); 
           return true; 
          } else if (mCurrentLayoutManager == mGridLayoutManager2) { 
           mCurrentLayoutManager = mGridLayoutManager3; 
           mRvPhotos.setLayoutManager(mGridLayoutManager3); 
           return true; 
          } 
         } else if(detector.getCurrentSpan() - detector.getPreviousSpan() > 1) { 
          if (mCurrentLayoutManager == mGridLayoutManager3) { 
           mCurrentLayoutManager = mGridLayoutManager2; 
           mRvPhotos.setLayoutManager(mGridLayoutManager2); 
           return true; 
          } else if (mCurrentLayoutManager == mGridLayoutManager2) { 
           mCurrentLayoutManager = mGridLayoutManager1; 
           mRvPhotos.setLayoutManager(mGridLayoutManager1); 
           return true; 
          } 
         } 
        } 
        return false; 
       } 
      }); 
Powiązane problemy