当在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 就像我的链接答案一样

【讨论】:

很遗憾,fillViewportsetNestedScrollingEnabled 都没有解决问题 你试过拦截触摸事件吗? (见编辑)【参考方案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 中时滚动不起作用

NestedScrollView 修复 NestedScrollView 内部的视图顶部

有关NestedScrollView的问题

检查 NestedScrollView 是不是可滚动