13

Ho una progettazione dell'interfaccia utente con CollapsingToolbarLayout, come segue.NestedScrolling con NestedScrollView, RecyclerView (orizzontale), all'interno di un CoordinatorLayout

<android.support.design.widget.AppBarLayout 
    android:id="@+id/appbar" 
    android:layout_width="match_parent" 
    android:layout_height="@dimen/detail_backdrop_height" 
    android:fitsSystemWindows="true" 
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> 

    <android.support.design.widget.CollapsingToolbarLayout 

     android:id="@+id/collapsing_toolbar" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:fitsSystemWindows="true" 
     app:contentScrim="?attr/colorPrimary" 
     app:expandedTitleMarginEnd="64dp" 
     app:expandedTitleMarginStart="48dp" 
     app:layout_scrollFlags="scroll|exitUntilCollapsed"> 

     <ImageView 
      android:id="@+id/backdrop" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:fitsSystemWindows="true" 
      android:scaleType="centerCrop" 
      app:layout_collapseMode="parallax" /> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      app:layout_collapseMode="pin" 
      app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> 

    </android.support.design.widget.CollapsingToolbarLayout> 

</android.support.design.widget.AppBarLayout> 

<android.support.v4.widget.NestedScrollView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:fillViewport="true" 
    android:theme="@style/ThemeOverlay.AppCompat.Light" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical" 
     android:paddingTop="24dp"> 

     <!-- Hiding unrelated code --> 

     <android.support.v7.widget.CardView 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_margin="@dimen/card_margin" 
      android:padding="16dp"> 


       <android.support.v7.widget.RecyclerView 
        android:id="@+id/recycler_movie_suggestion" 
        android:layout_width="match_parent" 
        android:layout_height="170dp" 
        android:fillViewport="true" 
        android:nestedScrollingEnabled="false" 
        app:layout_behavior="@string/appbar_scrolling_view_behavior" /> 

      </LinearLayout> 

     </android.support.v7.widget.CardView> 

    </LinearLayout> 

</android.support.v4.widget.NestedScrollView> 

Il mio problema è, lo scorrimento va bene SOLO quando tocco e scorrere l'area esterna al RecyclerView. Se provo a scorrere verticalmente all'interno di RecyclerView, lo scorrimento è "intrappolato" e SOLO il NestedScrollView sta scorrendo, CollaspingToolbarLayout NON è collasping.

+0

Pensa che sia un bug, il nestedScrollingEnabled può essere fatto solo nel codice. farlo in XML non ha alcun effetto. –

risposta

34

È necessario disabilitare lo scorrimento annidato in modo programmatico. Non sembra funzionare correttamente se fatto in xml.

recyclerView.setNestedScrollingEnabled(false); 
+1

devo considerare l'attributo xml non funzionante come bug? –

+0

Se il mio schermo è di grandi dimensioni, che può essere visualizzato completamente in NestedScrollView (o principalmente, se si include l'altezza di CollaspingToolbarLayout, che fa un po 'di sovrascrittura in basso), la soluzione di cui sopra non funziona. Sembra che nessun evento venga inviato a CollaspingToolbarLayout per renderlo collasping. –

+0

Penso che sia vero anche senza un RecyclerView interno – tachyonflux

2

E se sei interessato ho creato un LayoutManager che dovrebbe risolvere il tuo problema.

public class ExpansiveLayoutManager extends LinearLayoutManager { 

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

public ExpansiveLayoutManager(Context context) { 
    super(context); 
} 

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

public ExpansiveLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
    super(context, attrs, defStyleAttr, defStyleRes); 
} 

@Override 
public boolean canScrollVertically() { 
    return false; 
} 

@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++) { 
     measureScrapChild(recycler, i, 
       View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), 
       View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), 
       mMeasuredDimension); 

     if (getOrientation() == HORIZONTAL) { 
      width = width + mMeasuredDimension[0]; 
      if (i == 0) { 
       height = mMeasuredDimension[1]; 
      } 
     } else { 
      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: 
    } 

    setMeasuredDimension(width, height); 
} 

private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, 
           int heightSpec, int[] measuredDimension) { 
    View view = recycler.getViewForPosition(position); 
    if (view != null) { 
     RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); 
     int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, 
       getPaddingLeft() + getPaddingRight(), p.width); 
     int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, 
       getPaddingTop() + getPaddingBottom(), p.height); 
     view.measure(childWidthSpec, childHeightSpec); 
     measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; 
     measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; 
     recycler.recycleView(view); 
    } 
} 
} 

https://github.com/emanuelet/LayoutManagers/blob/master/ExpansiveLayoutManager.java

0

Non è necessario mettere il recyclerView all'interno NestedScrollView.

3

Questo è il problema più comune durante l'utilizzo di recyclerview all'interno di nestedscrollview.

Ho risolto questo problema aggiungendo le seguenti righe in xml.

<android.support.v7.widget.RecyclerView 
      android:id="@+id/recycler_view_comments" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:nestedScrollingEnabled="false" 
      app:layout_behavior="@string/appbar_scrolling_view_behavior" /> 
0

Non è necessario utilizzare NestedScrollView. Lascialo solo LinearLayout.

Problemi correlati