2016-03-15 26 views
11

W wersji 23.2 możemy teraz używać WRAP_CONTENT dla wysokości recyclerView, co jest świetne. Robię to, jednak chcę ponownie przeliczyć wysokość po dodaniu (lub usunięciu) elementu do adaptera (zwiększając lub zmniejszając wysokość).RecyclerView recalculate WRAP_CONTENT

Mój konkretny RecyclerView rozpoczyna się od 1 pozycji, a następnie dodaje elementy, gdy użytkownik dokonuje wyboru. Potrzebuję więc układu RecyclerView, aby zwiększyć wysokość, do pewnego stopnia. Idealnie byłoby, gdyby animacja była płynna, gdy lista rośnie lub maleje.

Jak możemy to zrobić WRAP_CONTENT po jego rozłożeniu?

Tried:

recyclerview.requestLayout(); 

recyclerview.invalidate(); 
+0

może Pan wyjaśnić, co chce osiągnąć więcej szczegółów? dodanie układu xml i trochę kodu będzie również świetny ... – crazyPixel

+1

Upewnij się, że nie wywołasz 'setHasFixedSize' w widoku recyklera. – Wukash

+0

Miałem ten problem. Będziesz musiał wywołać miarę, ale w Androidzie M występuje błąd, jeśli korzystasz z wielu układów potomnych. Aby obejść ten problem, dodaj GlobalLayoutListener i ustaw wysokość naGlobalLayout – zafrani

Odpowiedz

5

Spodziewam się go do pracy z View.invalidate().

Jeśli to nie działa, spróbuj zadzwonić pod numer requestLayout lub invalidate w widoku rodzica.

+0

Wywołanie unieważnionego w widoku nadrzędnym załatwiło sprawę. Oczywiście nie animuje ona wzrostu ani kurczenia się. Animowanie jest znacznie trudniejszym problemem, ale jest to najbliższe rozwiązanie mojego problemu. – Patrick

1

Wariant I

Widziałeś ten answer?

Nie korzysta z urządzenia recyklingowego ViewSync WRAP_CONTENT, ale może działać.

Można również utworzyć własny niestandardowy recyclerView (rozszerza RecyclerView) i zastąpić tam metodę onMeasure(), korzystając z menedżera layoutManager w łączu.

Wariant II

Spróbuj ustawić params układu przed rysunek widoku. Nie sprawdziłem, czy jest wywołana, gdy zmienia się układ recyclerView, ale jeśli tak, to zadziała. Coś jak to (w swojej działalności/Fragment onCreate()/onCreateView() metoda:

recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 
      @Override 
      public boolean onPreDraw() { 
       recyclerView.getViewTreeObserver().removeOnPreDrawListener(this); 

       YourParentLayoutType.LayoutParams params = (YourParentLayoutType.LayoutParams) recyclerView.getLayoutParams(); 
       params.height = YourParentLayoutType.LayoutParams.WRAP_CONTENT; 
       recyclerView.setLayoutParams(params); 

       return true; 
      } 
     }); 

Użyj układ nadrzędny recyclerView typ zamiast YourParentLayoutType w kodzie nie jestem pewien, że to będzie działać, gdy odświeża układu, ale może warto. spróbować

0

użyj tej klasy.

Proszę używać 23.2.1 jako 23,2 była droga buggy

również próbowałeś zadzwonić. 0 na adapterze recyclerview, ile myślę, że powinno rozwijać się bez problemu, jeśli dałeś wrap_content w wysokości recyclerview

jeszcze u mogą korzystać z tej klasy:

import android.content.Context; 
import android.support.v7.widget.LinearLayoutManager; 
import android.support.v7.widget.RecyclerView; 
import android.view.View; 
import android.view.ViewGroup; 

public class MyLinearLayoutManager extends LinearLayoutManager { 

    public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { 
     super(context, orientation, reverseLayout); 

    } 



    private int[] mMeasuredDimension = new int[2]; 


    @Override 
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, 
          int widthSpec, int heightSpec) { 
     final int widthMode = View.MeasureSpec.getMode(widthSpec); 
     final int heightMode = View.MeasureSpec.getMode(heightSpec); 
     final int widthSize = View.MeasureSpec.getSize(widthSpec); 
     final int heightSize = View.MeasureSpec.getSize(heightSpec); 



     int width = 0; 
     int height = 0; 
     for (int i = 0; i < getItemCount(); i++) { 
      if (getOrientation() == HORIZONTAL) { 
       measureScrapChild(recycler, i, 
         View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), 
         heightSpec, 
         mMeasuredDimension); 

       width = width + mMeasuredDimension[0]; 
       if (i == 0) { 
        height = mMeasuredDimension[1]; 
       } 
      } else { 
       measureScrapChild(recycler, i, 
         widthSpec, 
         View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), 
         mMeasuredDimension); 

       height = height + mMeasuredDimension[1]; 
       if (i == 0) { 
        width = mMeasuredDimension[0]; 
       } 
      } 
     } 


     switch (widthMode) { 
      case View.MeasureSpec.EXACTLY: 
       width = widthSize; 
      case View.MeasureSpec.AT_MOST: 
      case View.MeasureSpec.UNSPECIFIED: 
     } 

     switch (heightMode) { 
      case View.MeasureSpec.EXACTLY: 
       height = heightSize; 
      case View.MeasureSpec.AT_MOST: 
      case View.MeasureSpec.UNSPECIFIED: 
     } 

     int widthDesired = Math.min(widthSize,width); 
     setMeasuredDimension(widthDesired, height); 
    } 

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, 
            int heightSpec, int[] measuredDimension) { 
     View view = recycler.getViewForPosition(position); 
     // For adding Item Decor Insets to view 
     super.measureChildWithMargins(view, 0, 0); 
     RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); 
     int childWidthSpec = ViewGroup.getChildMeasureSpec(
       widthSpec, 
       getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view), 
       p.width); 
     int childHeightSpec = ViewGroup.getChildMeasureSpec(
       heightSpec, 
       getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view) , 
       p.height); 
     view.measure(childWidthSpec, childHeightSpec); 

     // Get decorated measurements 
     measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin; 
     measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin; 
     recycler.recycleView(view); 
     } 
    } 
+1

Powinieneś sprawdzać licznik pętli w stosunku do stanu itemCount 'i

3

Jak sama RecyclerView Resize w oparciu o z nowym interfejsem LayoutManger

Widżet RecyclerView zapewnia zaawansowaną i elastyczną podstawę do tworzenia list i siatki, a także wspierających animacje. Ta wersja wprowadza ekscytującą nową funkcję do interfejsu API LayoutManager: auto-pomiar!Pozwala to na zmianę rozmiaru samego RecyclerView w oparciu o rozmiar jego zawartości. Oznacza to, że możliwe są już wcześniej niedostępne scenariusze, takie jak użycie WRAP_CONTENT dla wymiaru RecyclerView. Znajdziesz wszystkie wbudowane w LayoutManagers teraz obsługują auto-pomiar.

Z powodu tej zmiany należy dokładnie sprawdzić parametry układu widoków elementów: uprzednio zignorowane parametry układu (takie jak MATCH_PARENT w kierunku przewijania) będą teraz w pełni przestrzegane.

Jeśli masz niestandardowy menedżer LayoutManager, który nie rozszerza jednego z wbudowanych menedżerów LayoutManager, jest to interfejs API akceptacji - będziesz musiał wywołać setAutoMeasureEnabled (true), a także wprowadzić drobne zmiany zgodnie z opisem w Javadoc metody.

Należy pamiętać, że chociaż RecyclerView animuje swoje dzieci, nie animuje własnych zmian granic. Jeśli chcesz animować granice RecyclerView podczas ich zmiany, możesz użyć interfejsów API Transition.

Proszę przeczytać this

Powiązane problemy