2015-04-26 15 views
55

Với thư viện hỗ trợ-v4 22.1.0 android hỗ trợ cuộn lồng nhau (pre android 5.0). Thật không may, tính năng này không thực sự được ghi lại. Có hai giao diện (NestedScrollingParentNestedScrollingChild) cũng như hai lớp đại biểu trợ giúp (NestedScrollingChildHelperNestedScrollingParentHelper).Cách triển khai NestedScrolling trên Android?

Có ai đã làm việc với NestedScrolling trên Android không?

Tôi đã cố gắng thiết lập một ví dụ nhỏ, nơi tôi sử dụng NestedScrollView thực hiện cả hai NestedScrollingParentNestedScrollingChild.

bố trí của tôi trông như thế này:

<android.support.v4.widget.NestedScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/parent" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".MainActivity"> 

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

    <View 
     android:id="@+id/header" 
     android:layout_width="match_parent" android:layout_height="100dp" 
     android:background="#AF1233"/> 

    <android.support.v4.widget.NestedScrollView 
     android:id="@+id/child" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     > 

     <FrameLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:orientation="vertical"> 

     <TextView 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="#12AF33" 
      android:text="@string/long_text"/> 

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

    </LinearLayout> 

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

Tôi muốn hiển thị một header view và một NestedScrollView (id = con) trong một NestedScrollView (id = mẹ).

Ý tưởng là, để điều chỉnh chiều cao của xem di chuyển con trong thời gian chạy bằng cách sử dụng một OnPredrawListener:

public class MainActivity extends Activity { 

    @Override protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    final NestedScrollView parentScroll = (NestedScrollView) findViewById(R.id.parent); 
    final NestedScrollView nestedScroll = (NestedScrollView) findViewById(R.id.child); 
    parentScroll.setNestedScrollingEnabled(false); 
    final View header = findViewById(R.id.header); 

    parentScroll.getViewTreeObserver() 
     .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 
      @Override public boolean onPreDraw() { 
      if (parentScroll.getHeight() > 0) { 
       parentScroll.getViewTreeObserver().removeOnPreDrawListener(this); 
       nestedScroll.getLayoutParams().height = parentScroll.getHeight() - 40; 
       nestedScroll.setLayoutParams(nestedScroll.getLayoutParams()); 
       nestedScroll.invalidate(); 
       return false; 
      } 
      return true; 
      } 
     }); 

    } 
} 

Vì vậy, quan điểm tiêu đề sẽ được cuộn đi một phần, 40 pixel sẽ vẫn nhìn thấy kể từ khi tôi đặt chiều cao của chế độ xem cuộn con lồng nhau đến parentScroll.getHeight() - 40. Được rồi, đặt chiều cao lúc chạy và cuộn chế độ xem cuộn chính sẽ hoạt động như mong đợi (tiêu đề cuộn ra, 40 pixel vẫn hiển thị và sau đó cuộn con sẽ lấp đầy phần còn lại của màn hình bên dưới tiêu đề). Tôi mong rằng "NestedScrolling" có nghĩa là tôi có thể tạo một cử chỉ di chuyển ở bất cứ nơi nào trên màn hình (sự kiện chạm được bắt bởi chế độ xem cuộn phụ huynh) và nếu chế độ xem cuộn chính đã đến cuối màn hình cuộn con lồng nhau bắt đầu cuộn . Tuy nhiên, có vẻ như không phải là trường hợp (không cho cử chỉ di chuyển đơn giản hay cử chỉ trượt).

Sự kiện liên lạc luôn được xử lý bởi cuộn con lồng nhau nếu sự kiện chạm bắt đầu trong ranh giới của nó, nếu không, bằng cách cuộn theo chế độ xem chính.

Đó có phải là hành vi mong đợi của "cuộn lồng nhau" hay không có tùy chọn để thay đổi hành vi đó?

Tôi cũng đã cố gắng thay thế chế độ xem cuộn con lồng nhau bằng NestedRecyclerView. Tôi subclassed RecyclerView và thực hiện NestedScrollingChild nơi tôi giao toàn bộ phương pháp để NestedScrollingChildHelper:

public class NestedRecyclerView extends RecyclerView implements NestedScrollingChild { 

    private final NestedScrollingChildHelper scrollingChildHelper = 
     new NestedScrollingChildHelper(this); 


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

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

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

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

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

    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, 
     int dyUnconsumed, int[] offsetInWindow) { 

    return scrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, 
     dyUnconsumed, offsetInWindow); 
    } 

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

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

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

nhưng NestedRecyclerView không di chuyển chút nào. Tất cả các sự kiện cảm ứng đều bị bắt bởi chế độ xem cuộn của bố mẹ.

+0

Tôi phải đối mặt với cùng một vấn đề và nghĩ rằng tiện ích con này sẽ được cải thiện để cho phép phụ huynh gửi di chuyển không mong muốn đến con của nó. –

+0

Tôi nghĩ việc tạo ra chế độ xem tái chế là một lồng nhauScrollingChild không phải là dễ dàng, vì nó sử dụng LayoutManager để cuộn và định vị mục của nó. Do đó, chỉ thực hiện NestedScrollingChild với NestedScrollingChildHelper sẽ không hoạt động vì những hàm này không được gọi trong khi cuộn. –

+0

Tôi không chắc chắn. Tôi đoán rằng NestedScrollingParent/NestedScrollingChild được sử dụng để chuyển tiếp sự kiện cảm ứng. Tôi hy vọng rằng 'NestedScrollingChild' nội bộ làm điều đó, tôi không thể thấy bất kỳ lý do tại sao nó sẽ làm việc cho' ScrollView' nhưng không cho 'RecyclerView' ...' LayoutManager' không phải là một vấn đề ... – sockeqwe

Trả lời

3

Tôi đã dành khá nhiều thời gian cho việc này chỉ cần thực hiện qua mã Android để tìm hiểu điều gì đang diễn ra trong NestedScrollView. Sau đây sẽ làm việc.

public abstract class ParentOfNestedScrollView extends NestedScrollView{ 

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

    /* 
    Have this return the range you want to scroll to until the 
    footer starts scrolling I have it as headerCard.getHeight() 
    on most implementations 
    */ 
    protected abstract int getScrollRange(); 

    /* 
    This has the parent do all the scrolling that happens until 
    you are ready for the child to scroll. 
    */ 
    @Override 
    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed){ 
     if (dy > 0 && getScrollY() < getScrollRange()) { 
      int oldScrollY = getScrollY(); 
      scrollBy(0, dy); 
      consumed[1] = getScrollY() - oldScrollY; 
     } 
    } 

    /* 
    Sometimes the parent scroll intercepts the event when you don't 
    want it to. This prevents this from ever happening. 
    */ 
    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     return false; 
    } 
} 

Một số mã của tôi được mượn từ số question này. Từ đây tôi chỉ mở rộng lớp này khi cần thiết. Xml của tôi có con như một NestedScrollView như một đứa trẻ và cha mẹ như thế này. Điều này không xử lý tình trạng treo cũng như tôi muốn, đó là một công việc đang tiến hành.

+0

Tôi đã mất một ngày về vấn đề này và giải pháp của bạn đã cứu tôi, cảm ơn! –

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