我无法禁止在中滚动RecyclerView
。我尝试打电话,rv.setEnabled(false)
但仍然可以滚动。
如何禁用滚动?
View
在RecyclerView
,VISIBLE
以及GONE
根据需要切换之间放置了透明的内容,但是袖手旁观,您的方法似乎是合理的。
我无法禁止在中滚动RecyclerView
。我尝试打电话,rv.setEnabled(false)
但仍然可以滚动。
如何禁用滚动?
View
在RecyclerView
,VISIBLE
以及GONE
根据需要切换之间放置了透明的内容,但是袖手旁观,您的方法似乎是合理的。
Answers:
为此,您应该覆盖您的recycleview的layoutmanager。这样,它将仅禁用滚动,而没有其他功能。您仍然可以处理点击或任何其他触摸事件。例如:-
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();
}
}
在这里,使用“ isScrollEnabled”标志可以临时启用/禁用回收视图的滚动功能。
简单覆盖现有的实现即可禁用滚动并允许单击。
linearLayoutManager = new LinearLayoutManager(context) {
@Override
public boolean canScrollVertically() {
return false;
}
};
NestedScrollView
:android.support.v4.widget.NestedScrollView
,如此处所述,由chessdork编写:stackoverflow.com/questions/37846245/…–
REAL REAL的答案是: 对于API 21和更高版本:
无需Java代码。
您可以android:nestedScrollingEnabled="false"
在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">
这有点棘手,但可行。您可以在中启用/禁用滚动RecyclerView
。
这是一次空洞的RecyclerView.OnItemTouchListener
窃取,每一次触摸事件都会使目标无效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) {
}
}
使用它:
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
这对我有用:
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
Custom view 'RecyclerView' has setOnTouchListener called on it but does not override performClick
return e.getAction() == MotionEvent.ACTION_MOVE;
而return true;
不仅仅是取消滚动/滑动事件。
您可以通过冻结RecyclerView来禁用滚动。
冻结:
recyclerView.setLayoutFrozen(true)
要解冻: recyclerView.setLayoutFrozen(false)
创建扩展RecyclerView类的类
public class NonScrollRecyclerView extends RecyclerView {
public NonScrollRecyclerView(Context context) {
super(context);
}
public NonScrollRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public NonScrollRecyclerView(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();
}
}
这将禁用滚动事件,但不会禁用单击事件
在XML中使用它执行以下操作:
<com.yourpackage.xyx.NonScrollRecyclerView
...
...
/>
如果仅禁用的滚动功能,RecyclerView
则可以使用的setLayoutFrozen(true);
方法RecyclerView
。但是不能禁用触摸事件。
your_recyclerView.setLayoutFrozen(true);
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
// Stop only scrolling.
return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
}
});
有一个非常简单的答案。
LinearLayoutManager lm = new LinearLayoutManager(getContext()) {
@Override
public boolean canScrollVertically() {
return false;
}
};
上面的代码禁用了RecyclerView垂直滚动。
另一个选择是setLayoutFrozen
,但它还带有许多其他副作用。
编写了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
}
用法:
recyclerView.layoutManager = NoScrollLinearLayoutManager(context)
(recyclerView.layoutManager as NoScrollLinearLayoutManager).disableScrolling()
扩展LayoutManager
和覆盖canScrollHorizontally()
并canScrollVertically()
禁用滚动。
请注意,在开头插入项目不会自动回滚到开头,要解决此问题,请执行以下操作:
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);
}
}
}
});
}
我知道这已经有了一个可以接受的答案,但是该解决方案并未考虑到我遇到的一个用例。
我特别需要一个仍可单击的标题项,但禁用了RecyclerView的滚动机制。这可以通过以下代码完成:
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) {
}
});
如setLayoutFrozen
不建议使用的那样,您可以通过使用冻结冻结RecyclerView来禁用滚动suppressLayout
。
冻结:
recyclerView.suppressLayout(true)
要解冻:
recyclerView.suppressLayout(false)
在XML中:
你可以加
android:nestedScrollingEnabled="false"
在子RecyclerView布局XML文件中
要么
用Java:-
childRecyclerView.setNestedScrollingEnabled(false);
以Java代码访问您的RecyclerView。
使用ViewCompat(Java):
childRecyclerView.setNestedScrollingEnabled(false);
仅适用于android_version> 21设备。要在所有设备上工作,请使用以下命令
ViewCompat.setNestedScrollingEnabled(childRecyclerView, false);
由于某种原因,@ Alejandro Gracia答案仅在几秒钟后才开始起作用。我找到了一种可立即阻止RecyclerView的解决方案:
recyclerView.addOnItemTouchListener(new 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) {
}
});
重写onTouchEvent()和onInterceptTouchEvent(),如果根本不需要OnItemTouchListener,则返回false。这不会禁用ViewHolders的OnClickListeners。
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;
}
}
您可以在设置适配器后添加此行
ViewCompat.setNestedScrollingEnabled(recyclerView, false);
现在您的recyclerview将可以平滑滚动
我在这个问题上苦苦挣扎了一个小时,所以我想分享一下我的经验,对于layoutManager解决方案来说很好,但是如果您要重新启用滚动回收站,则会回到顶部。
到目前为止(至少对我而言)最好的解决方案是使用@Zsolt Safrany方法,但添加getter和setter,这样您就不必删除或添加OnItemTouchListener。
如下
public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {
boolean isEnable = true;
public RecyclerViewDisabler(boolean isEnable) {
this.isEnable = isEnable;
}
public boolean isEnable() {
return isEnable;
}
public void setEnable(boolean enable) {
isEnable = enable;
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
return !isEnable;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept){}
}
用法
RecyclerViewDisabler disabler = new RecyclerViewDisabler(true);
feedsRecycler.addOnItemTouchListener(disabler);
// TO ENABLE/DISABLE JUST USE THIS
disabler.setEnable(enable);
遇到了一个包含多个RecycleView的片段,因此我只需要一个滚动条,而不是每个RecycleView中的一个滚动条。
所以我只是将ScrollView放入包含2个RecycleViews的父容器中,并android:isScrollContainer="false"
在RecycleView中使用
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="LinearLayoutManager"
android:isScrollContainer="false" />
加
android:descendantFocusability="blocksDescendants"
在您的SrollView或NestedScrollView的子级中(以及ListView,recyclerview和gridview的父级)
有一种更简单的方法来禁用滚动(从技术上讲,它是拦截滚动事件并在满足条件时结束滚动事件),仅使用标准功能即可。RecyclerView
具有名为的方法addOnScrollListener(OnScrollListener listener)
,仅使用此方法就可以阻止其滚动,如下所示:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (viewModel.isItemSelected) {
recyclerView.stopScroll();
}
}
});
用例:
假设您要在单击其中一个项目时禁用滚动,RecyclerView
以便可以对其执行一些操作,而不会因意外滚动到另一个项目而分心,当您完成操作后,只需单击再次启用该项目以滚动。为此,您需要附加OnClickListener
到其中的每个项目RecyclerView
,因此当您单击某个项目时,它将isItemSelected
从切换false
为true
。这样,当您尝试滚动时,RecyclerView
将自动调用method,onScrollStateChanged
并且由于isItemSelected
设置为true
,它将在RecyclerView
有机会滚动。
注意:为提高可用性,请尝试使用GestureListener
而不是OnClickListener
防止accidental
点击。
stopScroll()
并不是要冻结滚动,而只是停止/停止滚动recyclerview。
isItemSelected
设置为的RecyclerView内容时,它都会这样做true
。否则,您将需要一个自定义的RecyclerView来永久禁用滚动,而我想避免这样做,因为我只需要此解决方案提供的一些额外功能。
要通过触摸停止滚动,但继续通过命令滚动:
如果(appTopBarMessagesRV == null){appTopBarMessagesRV = findViewById(R.id.mainBarScrollMessagesRV);
appTopBarMessagesRV.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
if ( rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING)
{
// Stop scrolling by touch
return false;
}
return true;
}
});
}
RecyclerView
如果不想滚动,使用的目的是什么?