2016-12-21 28 views
6

Mam układ, w którym mam NestedScrollView zawierający obraz, wiele przycisków i RecycleView.RecyclerView scroll nie działa z NestedScrollView

Kiedy mówię recycleView.smoothScrollToPosition lub recycleView.scrollToPosition() nie robi nic w tej chwili. Odmów przewijania nawet piksela. Jeśli usunę NestedScrollView działa dobrze, ale w przypadku utraty efektu przewijania na okolicznych obszarach.

Czy ktoś z was już wcześniej napotkał ten problem?

<?xml version="1.0" encoding="utf-8"?> 
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:fitsSystemWindows="true" 
tools:context="world.the.rule.com.testtollbarstuff.ScrollingActivity"> 

<android.support.design.widget.AppBarLayout 
    android:id="@+id/app_bar" 
    android:layout_width="match_parent" 
    android:layout_height="@dimen/app_bar_height" 
    android:fitsSystemWindows="true" 
    android:orientation="vertical" 
    android:theme="@style/AppTheme.AppBarOverlay"> 


    <android.support.v7.widget.Toolbar 
     android:id="@+id/toolbar" 
     android:layout_width="match_parent" 
     android:layout_height="?attr/actionBarSize" 
     app:layout_collapseMode="none" 
     app:popupTheme="@style/AppTheme.PopupOverlay" /> 


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

<android.support.design.widget.CollapsingToolbarLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:fitsSystemWindows="true" 
    app:contentScrim="?attr/colorPrimary" 
    app:layout_scrollFlags="scroll"> 

    <android.support.v4.widget.NestedScrollView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <LinearLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:orientation="vertical" 
      app:layout_collapseMode="parallax"> 

      <ImageView 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:adjustViewBounds="true" 
       android:clickable="true" 
       android:src="@drawable/mock_image" /> 

      <include layout="@layout/content_scrolling" /> 

     </LinearLayout> 
    </android.support.v4.widget.NestedScrollView> 
</android.support.design.widget.CollapsingToolbarLayout> 

+0

Zrobiłem to teraz, ale teraz efekt! – Karoly

+1

w twoim 'LinearLayout' dodaj tę własność' android: descendantFocusability = "blocksDescendants" '. – Ironman

+0

'recycleView.post (new Runnable() {public void run() {recycleView.smoothScrollToPosition (80);});' – Blackbelt

Odpowiedz

2

Jeśli potrzebujesz tylko płynnego przewijania, nie trzeba przewijać, jak wspomniałem wcześniej w innym wątku.

Dodaj linie jak poniżej, gdy kiedykolwiek chcesz rozpocząć gładka przewijać

appBarLayout.setExpanded(false, /*true if animation required else false*/true); 
recyclerView.smoothScrollToPosition(position); 

Dodatkowe informacje

Dodatkowo, nie widzę żadnego RecyclerView w układzie i są szanse, że Ty zachowałeś to w LinearLayout, który ponownie jest częścią CollapsingToolbarLayout. Nie mam absolutnie żadnego pojęcia, dlaczego zachowałeś RecyclerView jako część CollapsingToolbarLayout. Podam układ (uproszczony), którego używam.

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <android.support.design.widget.CoordinatorLayout 
     android:id="@+id/container" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <android.support.design.widget.AppBarLayout 
      android:id="@+id/app_bar_layout" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      app:expanded="true" 
      app:layout_behavior="com.company.app.custom.CustomRecyclerScrollBehavior"> 

      <android.support.design.widget.CollapsingToolbarLayout 
       android:id="@+id/collapsing_toolbar" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       app:contentScrim="?attr/colorPrimary" 
       app:expandedTitleMarginEnd="64dp" 
       app:expandedTitleMarginStart="48dp" 
       app:layout_scrollFlags="scroll|exitUntilCollapsed"> 

       <FrameLayout 
        android:id="@+id/header_frame" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        app:layout_collapseMode="parallax" 
        app:layout_collapseParallaxMultiplier="0.8"> 

        <com.company.app.custom.CustomViewPager 
         android:id="@+id/view_pager" 
         android:layout_width="match_parent" 
         android:layout_height="wrap_content" 
         app:calculation="height" 
         app:height_ratio="@integer/product_listitem_img_width_ratio" 
         app:width_ratio="@integer/product_listitem_img_height_ratio" /> 

        <com.company.app.custom.CustomImageView 
         android:id="@+id/img_stock_layer" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
         android:adjustViewBounds="true" 
         android:scaleType="fitXY" 
         android:src="@color/transparent_app_black" 
         android:visibility="gone" 
         app:calculation_type="height" 
         app:ratio_height="@integer/product_listitem_img_width_ratio" 
         app:ratio_width="@integer/product_listitem_img_height_ratio" /> 

        <com.inneex.www.customfonts.FontTextView 
         android:id="@+id/lbl_out_of_stock" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
         android:layout_gravity="center" 
         android:text="@string/out_of_stock" 
         android:textColor="?android:attr/textColorPrimaryInverse" 
         android:textSize="13sp" 
         android:visibility="gone" 
         app:customFont="@string/font_ss_semibold" /> 

        <LinearLayout 
         android:id="@+id/ll_page" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
         android:layout_gravity="bottom|center_horizontal" 
         android:orientation="horizontal" 
         android:paddingBottom="@dimen/inspire_detail_oval_margin_bottom" /> 

       </FrameLayout> 

       <android.support.v7.widget.Toolbar 
        android:id="@+id/main_toolbar" 
        android:layout_width="match_parent" 
        android:layout_height="@dimen/toolbar_height" 
        android:background="?attr/colorPrimary" 
        app:layout_anchor="@id/header_frame" 
        app:layout_collapseMode="pin" 
        app:title=""> 

        <LinearLayout 
         android:layout_width="wrap_content" 
         android:layout_height="match_parent" 
         android:orientation="horizontal"> 

         <com.inneex.www.customfonts.FontTextView 
          android:id="@+id/lbl_toolbar_product_name" 
          android:layout_width="0dp" 
          android:layout_height="wrap_content" 
          android:layout_gravity="center" 
          android:layout_weight="1" 
          android:ellipsize="end" 
          android:lines="1" 
          android:maxLines="1" 
          android:minLines="1" 
          android:textColor="?android:attr/textColorPrimary" 
          android:textSize="18sp" 
          app:customFont="@string/font_ss_semibold" /> 

        </LinearLayout> 
       </android.support.v7.widget.Toolbar> 
      </android.support.design.widget.CollapsingToolbarLayout> 

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

     <ImageView 
      android:id="@+id/img_back" 
      android:layout_width="@dimen/toolbar_height" 
      android:layout_height="@dimen/toolbar_height" 
      android:layout_gravity="top|start" 
      android:scaleType="fitXY" 
      android:src="@drawable/back" 
      app:layout_collapseMode="parallax" /> 

     <android.support.v7.widget.RecyclerView 
      android:id="@+id/recycler_view" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:background="@color/white" 
      app:layout_behavior="@string/appbar_scrolling_view_behavior" /> 

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

    <include 
     layout="@layout/listitem_product_detail_buy_cheap" 
     android:layout_width="match_parent" 
     android:layout_height="@dimen/product_detail_button_buy_cheap_height" 
     android:layout_alignParentBottom="true" 
     android:layout_gravity="bottom" /> 

</RelativeLayout> 

FrameLayout id header_frame odpowiedzialny jest za duży pasku narzędzi, które nie runie na przewijanie. Toolbar o id main_toolbar odpowiada za zwinięty widok paska narzędzi. RecyclerView jest poniżej AppBarLayout. ImageView jest dla przycisku Wstecz, który zostanie wyświetlony po zwinięciu zostanie wyświetlony kod Toolbar.

Aby ułatwić przewijanie, dodałem CustomRecyclerScrollBehavior, z którym rozmawiałem wcześniej. To co to jest

import android.content.Context; 
import android.support.design.widget.AppBarLayout; 
import android.support.design.widget.CoordinatorLayout; 
import android.support.v7.widget.RecyclerView; 
import android.util.AttributeSet; 
import android.view.View; 

import java.lang.ref.WeakReference; 
import java.util.HashMap; 
import java.util.Map; 

/** 
* Created by jimitpatel on 13/12/16. 
*/ 

public class CustomRecyclerScrollBehavior extends AppBarLayout.Behavior { 

    private Map<RecyclerView, RecyclerViewScrollListener> scrollListenerMap = new HashMap<>(); //keep scroll listener map, the custom scroll listener also keep the current scroll Y position. 


    public CustomRecyclerScrollBehavior() { 
    } 

    public CustomRecyclerScrollBehavior(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    /** 
    * 
    * @param coordinatorLayout 
    * @param child The child that attached the behavior (AppBarLayout) 
    * @param target The scrolling target e.g. a recyclerView or NestedScrollView 
    * @param velocityX 
    * @param velocityY 
    * @param consumed The fling should be consumed by the scrolling target or not 
    * @return 
    */ 
    @Override 
    public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) { 
     if (target instanceof RecyclerView) { 
      final RecyclerView recyclerView = (RecyclerView) target; 
      if (scrollListenerMap.get(recyclerView) == null) { 
       RecyclerViewScrollListener recyclerViewScrollListener = new RecyclerViewScrollListener(coordinatorLayout, child, this); 
       scrollListenerMap.put(recyclerView, recyclerViewScrollListener); 
       recyclerView.addOnScrollListener(recyclerViewScrollListener); 
      } 
      scrollListenerMap.get(recyclerView).setVelocity(velocityY); 
      consumed = scrollListenerMap.get(recyclerView).getScrolledY() > 0; //recyclerView only consume the fling when it's not scrolled to the top 
     } 
     return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed); 
    } 

    private static class RecyclerViewScrollListener extends RecyclerView.OnScrollListener { 
     private int scrolledY; 
     private boolean dragging; 
     private float velocity; 
     private WeakReference<CoordinatorLayout> coordinatorLayoutRef; 
     private WeakReference<AppBarLayout> childRef; 
     private WeakReference<CustomRecyclerScrollBehavior> behaviorWeakReference; 

     public RecyclerViewScrollListener(CoordinatorLayout coordinatorLayout, AppBarLayout child, CustomRecyclerScrollBehavior barBehavior) { 
      coordinatorLayoutRef = new WeakReference<>(coordinatorLayout); 
      childRef = new WeakReference<>(child); 
      behaviorWeakReference = new WeakReference<>(barBehavior); 
     } 

     @Override 
     public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 
      dragging = newState == RecyclerView.SCROLL_STATE_DRAGGING; 
     } 

     public void setVelocity(float velocity) { 
      this.velocity = velocity; 
     } 

     public int getScrolledY() { 
      return scrolledY; 
     } 

     @Override 
     public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 
      scrolledY += dy; 

      if (scrolledY <= 0 && !dragging && childRef.get() != null && coordinatorLayoutRef.get() != null && behaviorWeakReference.get() != null) { 
       //manually trigger the fling when it's scrolled at the top 
       behaviorWeakReference.get().onNestedFling(coordinatorLayoutRef.get(), childRef.get(), recyclerView, 0, velocity, false); 
      } 
     } 
    } 
} 

Klasa ta służy do utrzymywania prędkości przewijania dla RecyclerView w zagnieżdżonych zwoje. Został zmieniony tutaj

Mam nadzieję, że to zadziała!

+0

Dzięki za dodanie tego, działa dobrze na moim projekcie dla zwierząt domowych, wdrażam na moim projekcie produktu! – Karoly

0

zrobić

recycleView.smoothScrollToPosition(80); 

później, a nie wewnątrz onCreate sposób, można użyć opóźnione wątku lub w inny sposób overide.

przykład:

 new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 
       recycleView.smoothScrollToPosition(80); 
     } 
    }, 150); 
+0

Dziękuję kolego, ale już próbowałem tego dodawania do onPostResume. Nic się nie dzieje :( – Karoly

+0

spróbuj z przykładem, to musi działać, zachować go w oncreate i umieścić tam przykład – yanivtwin

0

dać pewną stałą wysokość zamiast match_parent lub wrap_content do recyclerview.Because gdy recyclerview wewnątrz Scrollview, Jej wysokość wll być całkowita wysokość jego pozycji, więc będzie wyłączyć zwój widoku recyclerview i włącz tylko widok nestedscrollview.

+0

To ma sens, przewijanie pozycji działa teraz dobrze, ale nie mogę przewinąć RW – Karoly

+0

przykro mi nie dostałem twojego pytania –

+0

usuń tę linię ze swojego kodu 'recycleView.setNestedScrollingEnabled (false);' –