2016-02-03 7 views
11

Korzystam z układu widoku z układami przerywanych recyklerów, aby wyświetlić listę zdjęć. Chcę, aby odstępy po bokach były zerowe, zachowując odstęp między dwiema kolumnami. Używam subklasy dekoracji przedmiotów, aby uzyskać odstępy widoczne na załączonym zdjęciu. Wiem, że mam kontrolę nad lewym i prawym odstępem, ale problem polega na tym, że nigdy nie wiem, w której kolumnie znajduje się zdjęcie. Wygląda na to, że zdezagregowany menedżer układu wykonuje niektóre własne porządki. Próbowałem użyć getChildAdapterPosition, ale wydaje się, że zwraca pozycję w tablicy źródło danych, a nie rzeczywistą pozycję zdjęcia w układzie. Masz pomysł, jak mam to podejść? enter image description hereJak określić pozycję kolumny w menedżerze układu siatki o naprzemiennych numerach

+0

Właśnie o to właśnie teraz staram się dowiedzieć. Menedżer ustawia widoki w zależności od ich wielkości, a nigdy nie będziesz mieć pewności, że na przykład pozycje nieparzyste będą po lewej stronie, a pozycje po prawej. Tak właśnie próbowałem rozwiązać to w moim dekoratorze przedmiotów, sprawdzając pozycję% 2 == 0, a następnie ustawiając margines rect.left ... ale to nie działa tak, ponieważ w niektórych przypadkach pozycja z pozycją 6 może być na prawo, a czasem po lewej stronie. – Tooroop

Odpowiedz

24

Udało mi się sprawić, żeby działało. Więc w moim przypadku nie potrzebuję żadnych granic na lewej i prawej krawędzi ekranu. Potrzebowałem tylko granic w środku i na dole. Rozwiązaniem jest uzyskanie parametrów układu widoku o typie StaggeredGridLayoutManager.LayoutParams. W tych parametrach można uzyskać spanIndex, który mówi, który indeks jest tym widokiem. Więc jeśli masz spanCount z 2, lewa widok będzie mieć spanIndex 0 i właściwą widok będzie mieć spanIndex od 1.

Oto mój kod, więc może to pomoże Ci

public class SpaceItemDecoration extends RecyclerView.ItemDecoration { 
private int space; 

public SpaceItemDecoration(int space) { 
    this.space = space; 
} 


@Override 
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 
    int position = parent.getChildAdapterPosition(view); 

    StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams)view .getLayoutParams(); 
    int spanIndex = lp.getSpanIndex(); 

    if(position > 0){ 
     if(spanIndex == 1){ 
      outRect.left = space; 
     } else{ 
      outRect.right = space; 
     } 

     outRect.bottom = space * 2; 
    } 
} 

}

W moim przypadku najpierw muszę uzyskać pozycję, ponieważ na indeksie 0 Mam widok nagłówka, który nie ma żadnych granic. Potem otrzymuję indeks zakresu i zależnie od niego ustawiam granicę, której potrzebuję w tym widoku. I na koniec ustawiam dolną granicę na każdym widoku.

+0

Dziękuję, próbowałem to zhakować dla mojego układu, który ma jeden typ widoku nagłówka, typ widoku nagłówka podrzędnego i typ widoku elementu.Jest to naprawdę eleganckie rozwiązanie i działa również z regularnym GridLayoutManager. – kvgr

+0

Czy masz działający przykład tego kodu? Próbowałem w moim projekcie, z pewnych powodów, których nie rozumiem, spanIndex jest zawsze 0. Wydaje się, że StaggeredGridLayoutManager wywołuje getItemOffsets, zanim zdecyduje, do którego z widoków potomnych należy. – LiuJian

+0

Działa jak urok ................... – Vicky

2

więc jedynym rozwiązaniem, z którego mogłem skorzystać był dekorator przedmiotów, ale zdecydowanie jest to trochę dziwne/hacky.

Zasadniczo dostosujesz zewnętrzny prostokąt elementu na podstawie jego położenia w kolumnie (lub czegoś podobnego). Rozumiem, że zewnętrzny prostokąt jest mniej więcej odstępem, który chcesz zmienić. Podać kod poniżej spróbować, oczywiście trzeba zrobić własne regulacje i logiki „oblicz”, która kolumna pozycja jest włączona, ale to powinno wystarczyć, aby zrozumieć to, miejmy nadzieję:

recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { 
     public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 
      int left = outRect.left; 
      int right = outRect.right; 
      int top = outRect.top; 
      int bottom = outRect.bottom; 
      int idx = parent.getChildPosition(view); 
      int perRow = gridLayoutManager.getSpanCount(); 

      int adj = blahh... // some adjustment 

      if (idx < itemsPerRow) { 
       // on first row, adjust top if needed 
      } 

      if(idx % perRow == 0){ 
       // on first column, adjust. Left magically adjusts bottom, so adjust it too... 
       left += adj; 
       bottom -= adj; 
      } 

      if(idx % itemsPerRow == perRow - 1){ 
       // on last column, adjust. Right magically adjusts bottom, so adjust it too... 
       right += adjustment; 
       bottom -= adjustment; 
      } 

      outRect.set(left, top, right, bottom); 
     } 
    }); 

Znowu jest hacky i pobiera kilka prób i błędów, aby uzyskać prawo.

Innym rozwiązaniem, które próbowałem z pewnym powodzeniem, jest zdefiniowanie różnych widoków dla różnych kolumn. W twoim przypadku kolumny miałyby widoki z różnymi, ujemnymi marginesami, po lewej i prawej stronie, aby uzyskać pożądany efekt.

Na marginesie zakładam, że używasz elewacji w widoku karty. Jedną z rzeczy, które zauważyłem, jest to, że jeśli widok karty NIE ma wysokości, a zamiast tego sam sobie z nią radzisz (tak, wiem, to nie jest cel, aby nie obsługiwać samemu elewacji) wiele z tej trudności znika i rzeczy zaczynają się zachowywać , prawdopodobnie z powodu obliczeń elewacji/cienia. Ale w każdym razie ... Mam nadzieję, że jest to co najmniej pomocne ...

+0

Hej, gdzie jest instancja 'itemsPerRow'? Dzięki –

Powiązane problemy