154

Tôi không thể vô hiệu hóa cuộn trong RecyclerView. Tôi đã thử gọi rv.setEnabled(false)nhưng tôi vẫn có thể cuộn.

Làm thế nào tôi có thể vô hiệu hóa cuộn?

|
  • Điểm sử dụng RecyclerViewnếu bạn không muốn cuộn là gì?

    – Vũ Ngọc Huy 14:16:48 29/05/2015
  • 12

    @CommonsWare, tôi chỉ muốn tắt nó tạm thời, ví dụ, trong khi tôi đang thực hiện một hoạt hình tùy chỉnh với một trong những đứa con của nó.

    – Tạ Đan Linh 14:18:55 29/05/2015
  • 1

    Ah, OK, điều đó có ý nghĩa. Có lẽ tôi đã đặt một lớp trong suốt Viewlên trên RecyclerView, chuyển đổi giữa VISIBLEGONEkhi cần, nhưng cách tiếp cận của bạn có vẻ hợp lý.

    – Hoàng Mạnh Dũng 14:21:12 29/05/2015
  • Hy vọng điều này sẽ giúp tìm ra một giải pháp tốt hơn.

    – Lê Yến Trinh 19:25:41 24/09/2015
  • 1

    @CommonsWare, đây là những gì tôi cần nó, ví dụ. Tôi cần hiển thị hình ảnh trong RecyclerView một lần, không có hình ảnh hiển thị một phần, chỉ có một hình ảnh trong chế độ xem của tôi. Và có những mũi tên ở bên trái và bên phải mà người dùng có thể điều hướng. Tùy thuộc vào hình ảnh nào hiện đang được hiển thị (chúng thuộc nhiều loại khác nhau), một số thứ bên ngoài RecyclerView được kích hoạt. Đó là thiết kế mà khách hàng của chúng tôi muốn.

    – Nguyễn Xuân Hương 10:50:03 05/05/2016
299

Bạn nên ghi đè trình bố trí của biểu đồ tái chế của bạn cho việc này. Bằng cách này, nó sẽ chỉ vô hiệu hóa cuộn, không có chức năng nào khác. Bạn vẫn có thể xử lý nhấp chuột hoặc bất kỳ sự kiện chạm nào khác. Ví dụ:-

Nguyên:

 public class CustomGridLayoutManager extends LinearLayoutManager {
 private boolean isScrollEnabled = true;

 public CustomGridLayoutManager(Context context) {
  super(context);
 }

 public void setScrollEnabled(boolean flag) {
  this.isScrollEnabled = flag;
 }

 @Override
 public boolean canScrollVertically() {
  //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
  return isScrollEnabled && super.canScrollVertically();
 }
}

Tại đây, sử dụng cờ "isScrollEnabled", bạn có thể bật / tắt chức năng cuộn của chế độ xem tái chế của mình tạm thời.

Cũng thế:

Đơn giản ghi đè thực hiện hiện tại của bạn để vô hiệu hóa cuộn và cho phép nhấp.

 linearLayoutManager = new LinearLayoutManager(context) {
 @Override
 public boolean canScrollVertically() {
  return false;
 }
};
|
  • 1

    Đây phải là câu trả lời chính xác vì nó vô hiệu hóa cuộn trong khi cho phép tôi nhấp.

    – Phan Bảo Lan 21:36:16 09/01/2016
  • 1

    Vô hiệu hóa cuộn trên LayoutMangers mặc định đã tồn tại, người dùng API không cần phải làm điều này. Cảm ơn vì câu trả lời!

    – Tạ Bảo Kiên 22:55:30 14/02/2016
  • 1

    Điều gì xảy ra nếu tôi muốn vô hiệu hóa cuộn chỉ từ một mục nhất định? Có nghĩa là bạn có thể cuộn xuống (hoặc lên) đến nó, nhưng sau đó bị chặn, cho đến khi tôi kích hoạt lại nó?

    – Lý Thế Quyền 13:51:13 23/11/2017
  • 1

    Điều này cũng vô hiệu hóa smoothScrollToPocation

    – Tạ Việt Mi 14:02:37 29/11/2017
  • 1

    bạn thêm đối tượng phiên bản kotlin: linearLayoutManager (this) {ghi đè vui vẻ canScrollVertively (): Boolean {return false}}

    – Hồ Trung Nhân 07:21:53 07/05/2018
108

Câu trả lời thực sự là

recyclerView.setNestedScrollingEnabled(false);

Thêm thông tin trong tài liệu

|
  • 1

    Điều này sẽ chỉ vô hiệu hóa cuộn lồng nhau, không phải tất cả các cuộn. Cụ thể, nếu RecyclerView của bạn ở trong ScrollView nhưng không lấp đầy màn hình, ScrollView sẽ không cuộn (nội dung vừa với màn hình) và bạn sẽ nhận được giao diện người dùng cuộn trong RecyclerView (kết thúc danh sách khi thử cuộn ) mặc dù nó sẽ không cuộn khi nó lớn hơn. Mở rộng LayoutManager thực sự làm công việc.

    – Bùi Thành Đạt 04:58:29 17/03/2016
  • 1

    @ personne3000 Tôi tin recyclerView.setHasFixedSize (true) thực hiện công việc đó. Chỉnh sửa: Tôi cũng sử dụng kết hợp này với setFillViewport (true) vì vậy tôi thực sự không chắc chắn cái nào trong hai cái đó sửa được nó.

    – Hồ Tuyết Oanh 10:59:33 12/08/2016
  • 1

    Điều này hoạt động tốt với tôi, nhưng "RecyclerView" của tôi nằm trong bố cục Fragment bằng "ScrollView", vì vậy tôi đã phải thay đổi "ScrollView" bằng "NestedScrollView", như được mô tả ở đây: stackoverflow.com/a/38088902/618464

    – Tạ Tuyết Loan 13:15:33 18/11/2017
  • 1

    Hãy nhớ sử dụng tên lớp đầy đủ cho NestedScrollView: android.support.v4.widget.NestedScrollView, như được mô tả ở đây, bởi Chessdork: stackoverflow.com/questions/37846245/

    – Dương Uyển My 03:31:50 31/08/2018
41

Đây là một chút cách giải quyết nhưng nó hoạt động; bạn có thể bật / tắt cuộn trong RecyclerView.

Đây là một hành vi RecyclerView.OnItemTouchListenerđánh cắp trống mọi sự kiện chạm do đó vô hiệu hóa mục tiêu RecyclerView.

public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return true;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}

Sử dụng nó:

RecyclerView rv = ...
RecyclerView.OnItemTouchListener disabler = new RecyclerViewDisabler();

rv.addOnItemTouchListener(disabler);        // disables scolling
// do stuff while scrolling is disabled
rv.removeOnItemTouchListener(disabler);     // scrolling is enabled again 
|
29

Đối với API 21 trở lên:

Không cần mã java. Bạn có thể đặt android:nestedScrollingEnabled="false" trong xml:

<android.support.v7.widget.RecyclerView
     android:id="@+id/recycler"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:clipToPadding="true"
     android:nestedScrollingEnabled="false"
     tools:listitem="@layout/adapter_favorite_place">
|
  • 1

    Tôi nghĩ rằng đây phải là câu trả lời được chấp nhận, mà không cần bất kỳ nỗ lực nào trong lớp, bạn có thể vô hiệu hóa cuộn và cảm ứng được cho phép trong bố cục.

    – Huỳnh Ðăng Minh 07:23:18 04/01/2018
27

Điều này làm việc cho tôi:

  recyclerView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          return true;
      }
  });
|
8

Tạo lớp mở rộng lớp RecyclerView

    public class NonscrollRecylerview extends RecyclerView {

public NonscrollRecylerview(Context context) {
    super(context);
}

public NonscrollRecylerview(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

public NonscrollRecylerview(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
            Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
    ViewGroup.LayoutParams params = getLayoutParams();
    params.height = getMeasuredHeight();
}
}

Điều này sẽ vô hiệu hóa sự kiện cuộn, nhưng không phải là sự kiện nhấp

Sử dụng điều này trong XML của bạn làm như sau:

  <com.yourpackage.xyx.NonscrollRecylerview 
 ...
 ... >

 ...
 ...

</com.yourpackage.xyz.NonscrollRecylerview >
|
  • 1

    Cảm ơn! Tất cả điều này là cần thiết khi chúng tôi muốn cho phép chế độ xem tái chế lấy toàn bộ chiều cao theo nội dung mà không cần cuộn bên trong. :)

    – Đỗ Tuyết Oanh 05:01:09 21/03/2018
  • 1

    Nhưng nếu chế độ xem trình tái chế này ở chế độ xem cuộn (egScrollView) thì trình quản lý bố cục sẽ ghi đè phương thức canScrollVertively () trả về sai từ nó.

    – Dương Phương Dung 05:13:30 21/03/2018
  • 1

    @RahulRastogi sử dụng NestedScrollView thay vì ScrollView

    – Lý Nam Phi 09:19:04 21/03/2018
  • 1

    Xin chào @AshishMangave, Vui lòng cho biết cách bật lại chương trình

    – Hoàng Khải Tâm 05:50:06 20/04/2018
  • 1

    @Shruti chúng tôi không thể làm điều này theo chương trình. bcz chúng tôi trực tiếp ghi đè phương thức onMeasure của recyclerview. Bạn có thể thử với recyclerView.setNestedScrollingEnables (false) này. Điều này sẽ giúp bạn

    – Tạ Ðông Nguyên 06:13:19 20/04/2018
7

Nếu bạn chỉ vô hiệu hóa chức năng cuộn của RecyclerViewthì bạn có thể sử dụng setLayoutFrozen(true);phương pháp RecyclerView. Nhưng nó không thể vô hiệu hóa sự kiện cảm ứng.

your_recyclerView.setLayoutFrozen(true);
|
5

Một cách khác là setLayoutFrozen, nhưng nó đi kèm với một loạt các tác dụng phụ khác.

https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html#setLayoutF Frozen (boolean)

|
4

Bạn có thể vô hiệu hóa cuộn bằng cách đóng băng RecyclerView của bạn.

Đóng băng: recyclerView.setLayoutFrozen(true)

Để giải phóng: recyclerView.setLayoutFrozen(false)

|
  • 1

    Lưu ý: chế độ xem con không được cập nhật khi RecyclerView bị đóng băng. Tôi cần tắt cuộn khi có đủ chỗ trên màn hình để hiển thị tất cả các mục. Ôi ... Thật là một API Android tuyệt vời cho nhiệm vụ này ...

    – Bùi Hoàng Thái 15:19:17 28/01/2019
4
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            // Stop only scrolling.
            return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
        }
    });

|
4

Mở rộng LayoutManagervà ghi đè canScrollHorizontally()canScrollVertically()để vô hiệu hóa cuộn.

Xin lưu ý rằng việc chèn các mục ở đầu sẽ không tự động cuộn trở lại từ đầu, để giải quyết vấn đề này như sau:

  private void clampRecyclerViewScroll(final RecyclerView recyclerView)
  {
    recyclerView.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver()
    {
      @Override
      public void onItemRangeInserted(int positionStart, int itemCount)
      {
        super.onItemRangeInserted(positionStart, itemCount);
        // maintain scroll position at top
        if (positionStart == 0)
        {
          RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
          if (layoutManager instanceof GridLayoutManager)
          {
            ((GridLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
          }else if(layoutManager instanceof LinearLayoutManager)
          {
            ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
          }
        }
      }
    });
  }
|
3

Đã viết một phiên bản kotlin:

class NoScrollLinearLayoutManager(context: Context?) : LinearLayoutManager(context) {
    private var scrollable = true

    fun enableScrolling() {
        scrollable = true
    }

    fun disableScrolling() {
        scrollable = false
    }

    override fun canScrollVertically() =
            super.canScrollVertically() && scrollable


    override fun canScrollHorizontally() =
            super.canScrollVertically()

 && scrollable
}

sử dụng:

recyclerView.layoutManager = NoScrollLinearLayoutManager(context)
(recyclerView.layoutManager as NoScrollLinearLayoutManager).disableScrolling()
|
3

Tôi biết điều này đã có câu trả lời được chấp nhận, nhưng giải pháp không tính đến trường hợp sử dụng mà tôi gặp phải.

Tôi đặc biệt cần một mục tiêu đề vẫn có thể nhấp được, nhưng đã vô hiệu hóa cơ chế cuộn của RecyclerView. Điều này có thể được thực hiện với mã sau đây:

recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
                    @Override
                    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                        return e.getAction() == MotionEvent.ACTION_MOVE;
                    }

                    @Override
                    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

                    }

                    @Override
                    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

                    }
                });
|
  • 1

    Đối với một số lý do, bạn phải bấm vừa phải, mà không di chuyển để làm việc này.

    – Đỗ Nam Phi 21:35:37 09/01/2016
  • 1

    Điểm tốt, @JaredBurrows. Điều này là do chúng tôi không quan tâm đến ACTION_MOVE. Để cảm ứng trở nên tự nhiên, có một số cho giữa chạm và chuyển động nhẹ trên màn hình. Thật không may, tôi đã không thể giải quyết vấn đề đó.

    – Lý Mộng Liễu 22:23:27 15/01/2016
2

trong XML: -

Bạn có thể thêm

android:nestedScrollingEnabled="false"

trong tệp XML bố trí RecyclerView con

hoặc là

trong Java: -

childRecyclerView.setNestedScrollingEnabled(false);

để RecyclerView của bạn trong mã Java.

Sử dụng ViewCompat (Java): -

childRecyclerView.setNestedScrollingEnabled(false);sẽ chỉ hoạt động trong android_version> 21 thiết bị. để làm việc trong tất cả các thiết bị sử dụng như sau

ViewCompat.setNestedScrollingEnabled(childRecyclerView, false);

|
2

Ghi đè onTouchEvent () và onInterceptTouchEvent () và trả về false nếu bạn không cần OnItemTouchListener. Điều này không vô hiệu hóa OnClickListener của ViewHolders.

public class ScrollDisabledRecyclerView extends RecyclerView {
    public ScrollDisabledRecyclerView(Context context) {
        super(context);
    }

    public ScrollDisabledRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollDisabledRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return false;
    }
}
|

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.