2

我試圖建立使用CoordinatorLayout和AppBarLayout接下來的佈局exitUntilCollapsed scrollFlag另一種觀點認爲:使用與enterAlways scrollFlag一個視圖和一個AppBarLayout

|查看1(頭)|
|查看2 ------------ |
| RecyclerView --- |

我要實現的行爲是爲以下幾點:

  • 當我滾動RecyclerView,查看1將徹底崩潰。
  • 隨着我繼續滾動,視圖2將崩潰,直到它處於「摺疊」狀態。
  • RecyclerView應該開始滾動一次View 2已摺疊。
  • 當我從中間向上滾動RecyclerView時,視圖1應該馬上回來,而視圖2保留爲其摺疊狀態。
  • 一旦RecyclerView到達頂部,它應該擴大視圖2.

這是我作爲一個概念證明創建的測試佈局。

<android.support.design.widget.CoordinatorLayout 
    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.AppBarLayout 
     android:id="@+id/app_bar_layout" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <TextView 
      android:id="@+id/view1" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      android:text="TEST TITLE" 
      android:textSize="50sp" 
      app:layout_scrollFlags="scroll|enterAlways|snap" /> 

     <TextView 
      android:id="@+id/view2" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:text="TEST TEST TEST TEST TEST TEST TEST TEST" 
      android:textSize="70sp" 
      android:minHeight="50dp" 
      app:layout_scrollFlags="scroll|exitUntilCollapsed" /> 

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

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

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

我創建了一個測試適配器,在RV中添加幾個TextView項目(這裏沒有什麼特別的)。當我運行代碼時,它實際上並不像預期的那樣工作。

  1. Initial Screen

  2. 當我向下滾動,我確認了察看1完全崩潰了。

  3. 向下滾動更多。查看2崩潰,直到它達到minHeight。之後RV開始滾動。到目前爲止,這是按預期工作的。

  4. Here comes the problem. When I scroll up the RV. View 2 is expanded by the height of View 1. I'd like to see View 1 appear again.

我看着AppBarLayout實施和問題似乎是因爲AppBarLayout計算基礎上,scrollFlags整個視圖的滾動範圍,並抵消了整體視圖基於滾動偏移量,而不是更新每個子View。

有誰知道是否有任何解決方法或開源的lib來解決這個問題?它不一定是CoordinatorLayout/AppBarLayout方法,但我需要產生這種行爲。

預先感謝您。

回答

0

好吧,我自己找到了一個解決方案,並決定爲有類似問題的人發佈我的解決方案。

的解決方案是創建一個通過實施NestedScollingChild,使我們可以在兩個AppBarLayouts之間的互動延伸CoordinatorLayout一個NestedCoordinatorLayout。我引用了NestedScrollView源代碼和本文中的答案,https://stackoverflow.com/a/36881816/6272520,但我不得不做一些更改,使其按照我想要的方式工作。

下面是NestedCoordinatorLayout的代碼。

public class NestedCoordinatorLayout extends CoordinatorLayout implements NestedScrollingChild { 

    private final NestedScrollingChildHelper scrollingChildHelper; 

    private final int[] parentOffsetInWindow = new int[2]; 
    private final int[] parentScrollConsumed = new int[2]; 

    public NestedCoordinatorLayout(Context context) { 
     this(context, null); 
    } 

    public NestedCoordinatorLayout(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public NestedCoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     scrollingChildHelper = new NestedScrollingChildHelper(this); 
     setNestedScrollingEnabled(true); 
    } 

    //NestedScrollingChild 

    @Override 
    public void setNestedScrollingEnabled(boolean enabled) { 
     scrollingChildHelper.setNestedScrollingEnabled(enabled); 
    } 

    @Override 
    public boolean isNestedScrollingEnabled() { 
     return scrollingChildHelper.isNestedScrollingEnabled(); 
    } 

    @Override 
    public boolean startNestedScroll(int axes) { 
     return scrollingChildHelper.startNestedScroll(axes); 
    } 

    @Override 
    public void stopNestedScroll() { 
     scrollingChildHelper.stopNestedScroll(); 
    } 

    @Override 
    public boolean hasNestedScrollingParent() { 
     return scrollingChildHelper.hasNestedScrollingParent(); 
    } 

    @Override 
    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, 
            int dyUnconsumed, int[] offsetInWindow) { 
     return scrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); 
    } 

    @Override 
    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { 
     return scrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); 
    } 

    @Override 
    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 
     return scrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); 
    } 

    @Override 
    public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 
     return scrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY); 
    } 

    //NestedScrollingParent 

    @Override 
    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { 
     scrollingChildHelper.startNestedScroll(nestedScrollAxes); 
     return super.onStartNestedScroll(child, target, nestedScrollAxes); 
    } 

    @Override 
    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { 
     final int[] parentConsumed = parentScrollConsumed; 
     //This is where the most important change happens. 
     //During the prescroll, we want to decrease dx/dy. 
     //This will make sure the top bar gets the scroll event first. 
     if (dispatchNestedPreScroll(dx, dy, parentConsumed, null)) { 
      dx -= parentConsumed[0]; 
      dy -= parentConsumed[1]; 
      consumed[0] += parentConsumed[0]; 
      consumed[1] += parentConsumed[1]; 
     } 
     super.onNestedPreScroll(target, dx, dy, consumed); 
    } 

    @Override 
    public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 
     dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, parentOffsetInWindow); 
     super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); 
    } 

    @Override 
    public void onStopNestedScroll(View target) { 
     scrollingChildHelper.onStopNestedScroll(target); 
     super.onStopNestedScroll(target); 
    } 

    @Override 
    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { 
     scrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); 
     return super.onNestedFling(target, velocityX, velocityY, consumed); 
    } 

    @Override 
    public boolean onNestedPreFling(View target, float velocityX, float velocityY) { 
     scrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY); 
     return super.onNestedPreFling(target, velocityX, velocityY); 
    } 

    @Override 
    public void onNestedScrollAccepted(View child, View target, int axes) { 
     super.onNestedScrollAccepted(child, target, axes); 
     startNestedScroll(axes & ViewCompat.SCROLL_AXIS_VERTICAL); 
    } 
} 

和更新的XML文件看起來像這樣:

<?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" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <android.support.design.widget.AppBarLayout 
     android:id="@+id/app_bar_layout_for_view1" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <TextView 
      android:id="@+id/view1" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      android:text="TEST TITLE" 
      android:background="@android:color/white" 
      android:textSize="50sp" 
      app:layout_scrollFlags="scroll|enterAlways|snap" /> 

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

    <!-- Consider this like a NestedScrollView. 
     You need to have a scrolling behavior --> 
    <NestedCoordinatorLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

     <android.support.design.widget.AppBarLayout 
      android:id="@+id/app_bar_layout_for_view2" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content"> 

      <TextView 
       android:id="@+id/view2" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:minHeight="50dp" 
       android:text="TEST TEST TEST TEST TEST TEST TEST TEST" 
       android:textSize="70sp" 
       app:layout_scrollFlags="scroll|exitUntilCollapsed" /> 

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

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

    </NestedCoordinatorLayout> 

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

它就像一個魅力

相關問題