当在nestedscrollview的recyclerview中将项目拖出可见空间时-nestedscrollView不滚动
Posted
技术标签:
【中文标题】当在nestedscrollview的recyclerview中将项目拖出可见空间时-nestedscrollView不滚动【英文标题】:When drag item out of visible space in recyclerview in nestedscrollview - nestedscrollView doesn't scroll 【发布时间】:2017-07-28 21:17:55 【问题描述】:我有两个项目,它们是静态的和带有可拖动项目的 recyclerview。两种类型的视图都由 LinearLayout 包装。 LinearLayout 被 NestedScrollView 包裹起来。
XML解释:
<NestScrollView>
<LinearLayout>
<View></View>
<View></View>
<RecyclerView></RecyclerView>
</LinearLayout>
</NestScrollView>
图片说明:
我从本教程中提取的拖动项目的实现:https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-6a6f0c422efd#.yc7me2ikf
问题是当我将他的孩子拖出屏幕时,RecyclerView
不滚动。 (但是,如果我没有 NestedScrollView
作为父母,RecyclerView
将按预期工作。)
我搜索了与此相关的所有问题,但没有找到任何解决方案。
【问题讨论】:
同意下面的答案,这不是一个好习惯。请尝试改变您的方法。 你是否在你的 recyclerView 中添加了 NestedScrollingEnabled=false? 我建议你摆脱嵌套的滚动视图,将文本视图放在父视图中,并将该视图作为标题添加到 recyclerView 中。以下是如何将标头添加到 recyclerview (***.com/questions/26448717/…) 您最终找到解决方案了吗?如果没有嵌套滚动视图,我的折叠工具栏将无法工作 有没有人试图覆盖 interpolateOutOfBoundsScroll? 【参考方案1】:将recyclerView
放入NestedScrollView
不是一个好习惯。我建议您将其他视图用作RecyclerView
项目。正如您所说,我确信这会解决您的问题“但是,如果我没有 NestedScrollView 作为父级,RecyclerView 会按预期工作。”
【讨论】:
好的,但我必须有滚动,我还必须有 recyclerview @deadfish 向导是对的,你不应该把滚动视图放在滚动视图里面,就像你不把listView放在滚动视图里面一样,会导致问题【参考方案2】:通过将android:fillViewport="true"
添加到回收器,使 NestedScrollView 和 RecyclerView 一起玩得很好
当您开始拖动项目或到达屏幕边缘时,您还可以使用mRecyclerView.setNestedScrollingEnabled(false)
关闭回收器的嵌套行为。这将导致嵌套视图本身滚动,以便用户继续向下循环。
完成后,再次将嵌套滚动设置为 true。
或者您需要考虑委托谁获得触摸事件,就像我为另一个问题 here 概述的那样。对于您的示例,它可能很简单:
当拖动开始时调用nestedScrollView.requestDisallowInterceptTouchEvent(true);
当拖动结束时requestDisallowInterceptTouchEvent(false)
重新启用滚动视图
如果 requestDisallowInterceptTouchEvent 无法正常工作,那么您可以创建 NestedScrollView 的子类并覆盖 onInterceptTouchEvent
就像我的链接答案一样
【讨论】:
很遗憾,fillViewport
和 setNestedScrollingEnabled
都没有解决问题
你试过拦截触摸事件吗? (见编辑)【参考方案3】:
我也遇到过同样的问题。我将其他视图用作回收站视图。 首先,我们必须在 getItemViewType() 中返回两个视图。
public int getItemViewType(int position)
if(position == 0)
return HEADERVIEW;
return LISTVIEW;
现在,我们将另一个视图添加为列表中的 HeaderView,因此我们将调整列表计数:
@Override public int getItemCount()
return arrayList.size()+1;
现在在 getItemViewType() 的基础上正确绑定 onBindViewHolder 中的视图
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i)
if(viewHolder.getItemViewType() == HEADERVIEW )
HeaderViewHolder headerViewHolder = (HeaderViewHolder)viewHolder;
headerViewHolder.headertextview.SetText("LongText");
else
MyHolder myHolder = (MyHolder) viewHolder;
myHolder.name.setText(arrayList.get(i-1).name);
现在在 Item Touch Listener Callback 中,我们必须调整 onMove() 方法:
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
// get the viewHolder's and target's positions in your adapter data, swap them
if(viewHolder.getItemViewType() != target.getItemViewType())
return false;
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
if(dragFrom == -1)
dragFrom = fromPosition;
dragTo = toPosition;
if(dragFrom != -1 && dragTo != -1 && dragFrom != dragTo)
reallyMoved(dragFrom, dragTo);
dragFrom = dragTo = -1;
// and notify the adapter that its dataset has changed
adapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
现在如果所有逻辑都正确,那么我们移动项目并调用 onreallyMoved() 方法:
private void reallyMoved(int dragFrom, int dragTo)
if(dragFrom == 0 || dragTo == arrayList.size())
return;
Collections.swap(arrayList, dragFrom-1, dragTo-1);
如果您想了解更多信息,请查看my blog post。
【讨论】:
【参考方案4】:另一种解决方案是使用 linearLayout 而不是 NestedScrollView。在其根目录下,将 recyclerView 与参数 : sethasFixedSize(true) 放在您的 Java 文件中,并在 xml 中使用 match_parent 高度。
回顾:
<LinearLayout
android:layout_
android:layout_
android:orientation="vertical">
<RecyclerView
...
android:layout_
android:layout_/>
</LinearLayout>
别忘了设置 recyclerView.setHasFixedSize(true);在你的 Java 文件中
【讨论】:
【参考方案5】:使用类似的东西:
<FrameLayout
android:layout_
android:layout_
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v4.widget.NestedScrollView
android:id="@+id/view_noRecord"
android:layout_
android:layout_
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:id="@+id/tv_no_record"
android:layout_
android:layout_
android:layout_gravity="top"
android:layout_marginBottom="@dimen/_20sdp"
android:gravity="center_horizontal"
android:padding="@dimen/_10sdp"
android:text="@string/no_data_found"
android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.v4.widget.NestedScrollView>
<android.support.v7.widget.RecyclerView
android:id="@+id/common_recycler_view"
android:layout_
android:layout_
android:fadeScrollbars="true"
android:scrollbars="vertical"
android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</FrameLayout>
或者尝试将布局中的内容作为 RecyclerView 的标题
<LinearLayout>
<View></View>
<View></View>
</LinearLayout>
【讨论】:
我可以将标题添加到 recyclerview,但我不想将它们视为列表的子项。整个布局必须是可滚动的。 通过添加标题可以让整个布局也可以滚动,我最近也是这样做的。以上是关于当在nestedscrollview的recyclerview中将项目拖出可见空间时-nestedscrollView不滚动的主要内容,如果未能解决你的问题,请参考以下文章
具有固定高度的 Recyclerview 不会在 nestedscrollview 内滚动
NestedScrollView内部的RecyclerView ViewHolder创建
Espresso,当 NestedScrollView 或 RecyclerView 在 CoordinatorLayout 中时滚动不起作用