2016-09-27 75 views
2

我有一個CoordinatorLayout有兩個孩子,一個View充當頭和RecyclerView定製CoordinatorLayout.Behavior和RecyclerView滾動已發行

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

    <LinearLayout 
     android:id="@+id/view" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical" 
     android:gravity="center_horizontal" 
     app:layout_behavior="some.package.AlphaBehavior"> 

     <ImageView 
      android:id="@+id/header_iv" 
      style="@style/some_style"/> 

     <TextView 
      android:id="@+id/header_retails_tv" 
      style="@style/some_style_tv" 
      android:text="@string/some_text"/> 

     </LinearLayout> 

     <android.support.v7.widget.RecyclerView 
      android:id="@+id/recyclerview" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:clipToPadding="false" /> 

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

我動態設置填充到RecyclerView用頭和我的尺寸將clipToPadding設置爲false,因此RecyclerView顯示在標題下方,當用戶向上滾動時,RecyclerView顯示在標題視圖上方。

我爲了再次實現淡出視圖當用戶滾動了list和當標題有褪色可見一個定製CoordinatorLayout.BehaviorAlphaBehavior

public class AlphaBehavior extends CoordinatorLayout.Behavior { 

    private float alpha     = 1.0f; 
    private float scrolly    = 0.f; 
    private int headerSize = 0; 

    private Animation defaultFadeInAnimation; 

    public AlphaBehavior(Context context, AttributeSet attrs) { 
     super(context, attrs); 


     defaultFadeInAnimation = AnimationUtils.loadAnimation(context, android.R.anim.fade_in); 
    } 

    public void setHeaderSize(int headerSize) { 
     this.headerSize = headerSize; 
    } 

    @Override 
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { 
     return dependency instanceof RecyclerView; 
    } 


    @Override 
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 

     scrolly += dyConsumed; 

     Log.d(Constants.TAG, dyConsumed + "/" + dyUnconsumed + "/" + scrolly); 

     float totalScrollY = ((RecyclerView)target).computeVerticalScrollOffset(); 

     Log.d(Constants.TAG, "totalScrollY:" + totalScrollY); 

     alpha = (headerSize - totalScrollY)/headerSize; 

     if (alpha < 0.f) alpha = 0.f; 
     if (alpha > 1.0f) alpha = 1.f; 

     if (dyConsumed < 0 && totalScrollY > headerSize) { 
      alpha = 0.f; 
     } 

     Log.d(Constants.TAG, "alpha:" + alpha); 

     child.setAlpha(alpha); 
    } 

    @Override 
    public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) { 

     int pos = ((LinearLayoutManager)((RecyclerView)target).getLayoutManager()).findFirstCompletelyVisibleItemPosition(); 

     Log.d(Constants.TAG, "pos:" + pos); 

     if (pos == 0 && child.getAlpha() == 0.f) { 
      child.startAnimation(defaultFadeInAnimation); 
     } 
    } 



    // overriding this in case we don't the other events are not called 
    @Override 
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { 
     return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL; 
    } 
} 

但我遇到了一個問題:如果用戶滾動速度非常快,則行爲事件的調用不正確。 scrollY成員與總卷和totalScrollY成員(從計算從RecyclerView的捲動中獲得的)成員關係不正確。即使我試圖找到onStopNestedScroll事件中的firstCompletelyVisibleItem,但當recyclerView達到列表的開始時,它將返回位置2或3。

+0

請檢查伊恩湖的[答案](https://medium.com/@ianhlake/flings-are-definitely-quite-a-bit-different-from-regular-scrolling-in-being-much-less-fine-grained-3dfc82062aaf )。 – wonsuc

回答

3

最後,我解決了它使用OnScrollListener而不是使用CoordinatorLayout.Behavior,它的工作就像一個魅力。我把代碼,也許是有用的人:

定製onScrollListener隱藏一個觀點:

public class HideViewOnScrollListener extends RecyclerView.OnScrollListener { 

    private float alpha = 1.f; 
    private float scrolly = 0.f; 

    private int heightViewToHide; 
    private final View viewToHide; 

    public HideViewOnScrollListener(View viewToHide) { 
     this.viewToHide = viewToHide; 

     heightViewToHide = viewToHide.getHeight(); 
     if (heightViewToHide == 0) { 

      ViewTreeObserver viewTreeObserver = viewToHide.getViewTreeObserver(); 
      viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
       @Override 
       public void onGlobalLayout() { 

        heightViewToHide = viewToHide.getHeight(); 

        if (heightViewToHide > 0) 
         viewToHide.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
       } 
      }); 
     } 

    } 

    @Override 
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 
     super.onScrolled(recyclerView, dx, dy); 

     scrolly += dy; 

     alpha = (heightViewToHide - scrolly)/heightViewToHide; 

     if (alpha < 0.f) alpha = 0.f; 
     if (alpha > 1.0f) alpha = 1.f; 

     if (dy < 0 && scrolly > heightViewToHide) { 
      alpha = 0.f; 
     } 

     viewToHide.setAlpha(alpha); 
    } 
} 

,你可以添加到RecyclerView這樣:

recyclerView.addOnScrollListener(new HideViewOnScrollListener(viewToHide));