2016-02-05 17 views
9

Tôi có một chức năng Danh sách khá điển hình sử dụng một CoordinatorLayout, AppBarLayout, SwipeRefreshLayout và RecyclerView -Dừng AppBarLayout di chuyển ra khỏi màn hình khi NestedScrollView trống

Khi RecyclerView có đủ nội dung để di chuyển, trang có vẻ tốt đẹp. Tuy nhiên, khi RecyclerView trống hoặc không có đủ nội dung để cuộn, hành vi là các trẻ em AppBarLayout có app:layout_scrollFlags="scroll|enterAlwaysCollapsed" sẽ tiếp tục cuộn - trông có vẻ kỳ quặc.

Có cách nào để ngăn chặn trẻ em AppBarLayout cuộn khi NestedScrollView trống không?

enter image description here

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout 
    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/coordinatorLayout" 
     android:background="@android:color/transparent" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <android.support.design.widget.AppBarLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="@android:color/transparent" 
      android:elevation="4dp"> 

      <LinearLayout 
       android:id="@+id/eventHeader" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:padding="16dp" 
       android:background="@color/green" 
       android:orientation="horizontal" 
       app:layout_scrollFlags="scroll|enterAlwaysCollapsed"> 

       <View 
        android:layout_width="0dp" 
        android:layout_height="0dp" 
        android:layout_weight="1"/> 

       <TextView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="scroll|enterAlwaysCollapsed" 
        android:textColor="@color/white" 
        android:textSize="15sp"/> 

       <View 
        android:layout_width="0dp" 
        android:layout_height="0dp" 
        android:layout_weight="1"/> 

      </LinearLayout> 

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

     <android.support.v4.widget.SwipeRefreshLayout 
      android:id="@+id/swipeToRefresh" 
      android:layout_width="match_parent" 
      android:layout_gravity="fill_vertical" 
      android:layout_height="match_parent" 
      app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

      <android.support.v7.widget.RecyclerView 
       android:id="@+id/recyclerView" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:background="@android:color/transparent" 
       android:dividerHeight="0dp" 
       android:layout_gravity="fill_vertical" 
       android:drawSelectorOnTop="true" 
       android:listSelector="@drawable/selector_ripple_grey_transparent" 
       android:scrollbars="vertical"/> 

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

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

    <TextView 
     android:id="@+id/noData" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center" 
     android:padding="16dp" 
     android:text="@string/no_data_available" 
     android:textSize="17sp"/> 

</FrameLayout> 

Trả lời

5

Không chắc cách tao nhã một giải pháp này là nhưng, tôi gạt sự kiện onStartNestedScroll() để chỉ cháy nếu NestedScrollView là cuộn (Trong trường hợp này một RecyclerView)

trong onCreate ():

CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams(); 
layoutParams.setBehavior(new AppBarLayoutNoEmptyScrollBehavior(mAppBarLayout, mRecyclerView)); 

Hành vi:

public class AppBarLayoutNoEmptyScrollBehavior extends AppBarLayout.Behavior { 

    AppBarLayout mAppBarLayout; 
    RecyclerView mRecyclerView; 
    public AppBarLayoutNoEmptyScrollBehavior(AppBarLayout appBarLayout, RecyclerView recyclerView) { 
     mAppBarLayout = appBarLayout; 
     mRecyclerView = recyclerView; 
    } 

    public boolean isRecylerViewScrollable(RecyclerView recyclerView) { 
     int recyclerViewHeight = recyclerView.getHeight(); // Height includes RecyclerView plus AppBarLayout at same level 
     int appCompatHeight = mAppBarLayout != null ? mAppBarLayout.getHeight() : 0; 
     recyclerViewHeight -= appCompatHeight; 

     return recyclerView.computeVerticalScrollRange() > recyclerViewHeight; 
    } 

    @Override 
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) { 
     if (isRecylerViewScrollable(mRecyclerView)) { 
      return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes); 
     } 
     return false; 
    } 

} 

EDIT

giải pháp Sửa như RecyclerView cho chiều cao như nhìn thấy chiều cao RecyclerView và AppBarLayout chiều cao (đó là chiều cao CoordinatorLayout).

Tuy nhiên, nếu cử chỉ cuộn của bạn bắt đầu trên vùng AppBarLayout hiển thị, một cuộn sẽ vẫn còn diễn ra, ngay cả khi bạn thêm Hành vi này vào AppBarLayout. Câu trả lời này do đó không phải là một sửa chữa cho vấn đề.

2

(Dựa trên: Reference)

(1) Tạo lớp này.

public class AppBarLayoutBehaviorForEmptyRecyclerView extends AppBarLayout.Behavior 
{ 
    private boolean canRecyclerViewBeScrolled = false; 

    public AppBarLayoutBehaviorForEmptyRecyclerView() 
    { 
    } 

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

    @Override 
    public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) 
    { 
     return canRecyclerViewBeScrolled && super.onInterceptTouchEvent(parent, child, ev); 
    } 

    @Override 
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) 
    { 
     updateScrollable(target); 
     return canRecyclerViewBeScrolled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes); 
    } 

    @Override 
    public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) 
    { 
     return canRecyclerViewBeScrolled && super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed); 
    } 

    private void updateScrollable(View targetChild) 
    { 
     if(targetChild instanceof RecyclerView) 
     { 
      RecyclerView.Adapter adapter = ((RecyclerView) targetChild).getAdapter(); 

      canRecyclerViewBeScrolled = adapter != null && adapter.getItemCount() > 0; 
     } 
     else 
     { 
      canRecyclerViewBeScrolled = true; 
     } 
    } 
} 

(2) Thêm vào phần tử XML AppBarLayout của bạn thuộc tính sau:

app:layout_behavior="com.xxxx.xxxxxx.AppBarLayoutBehaviorForEmptyRecyclerView" 
0

Sau khi nạp dữ liệu để RecyclerView của bạn, nếu nó trống rỗng, chỉ disalbe cờ cuộn bằng tay:

AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mEventHeader.getLayoutParams(); 
toolbarLayoutParams.setScrollFlags(0); 
mEventHeader.setLayoutParams(toolbarLayoutParams); 

Và nếu không trống, hãy đặt lại cờ cuộn:

AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mEventHeader.getLayoutParams(); 
toolbarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); 
mEventHeader.setLayoutParams(toolbarLayoutParams); 
0

Graeme Câu trả lời là ok nhưng tôi cũng được thêm vào trong constructor

public AppBarLayoutOnEmptyRecyclerViewScrollBehavior(@NonNull AppBarLayout appBarLayout, @NonNull RecyclerView recyclerView) { 
    this.appBarLayout = checkNotNull(appBarLayout); 
    this.recyclerView = checkNotNull(recyclerView); 

    setDragCallback(new DragCallback() { 
     @Override 
     public boolean canDrag(@NonNull AppBarLayout appBarLayout) { 
      return isRecylerViewScrollable(recyclerView); 
     } 
    }); 
} 

nên khi RecyclerView rỗng Tôi cũng vô hiệu hóa kéo từ AppBarLayout

Các vấn đề liên quan