安卓SDK 23中RecyclerView无法滚动的问题

5

我正在实现一个 RecyclerView,并将其放在一个 ScrollView 中。为了让整个页面只有一个滚动行为,我实现了一个名为 NonScrollRecyclerView 的版本。具体实现如下:

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

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

    public NonScrollRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev){

        if(ev.getAction() == MotionEvent.ACTION_MOVE)
            return true;

        return super.dispatchTouchEvent(ev);
    }
}

当我将编译和目标设置更新到SDK 23后,我在包含“NonScrollRecyclerView”的页面上滚动时遇到了困难。具体问题是,在滚动到可滚动视图部分之前,页面可以正常滚动,但一旦滚动到此视图,我就无法再向上或向下滚动。
我在SDK 22及以下版本中没有遇到这个问题。
我的XML如下:
XML“@layout/rv”包含可滚动视图。
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@color/background_gray">

 <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/background_gray"
    android:orientation="vertical">

    <include
        layout="@layout/row_mall_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/cv_mall_header"
        android:layout_marginTop="8dp"/>

    <include
        layout="@layout/row_mall_shops"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/cv_mall_shops"
        android:layout_marginTop="8dp"/>

    <include
        layout="@layout/row_mall_coupons"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/cv_mall_coupons"
        android:layout_marginTop="8dp"/>

    <include
        layout="@layout/rv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/cv_mall_feeds"
        android:layout_marginTop="8dp"/>

  </LinearLayout>
</ScrollView>

XML - @layout/rv

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical" android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@color/background_gray"
  android:id="@+id/ll_mall_feeds">

 <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:paddingTop="6dp"
    android:paddingBottom="6dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv_feedcount"
        android:textColor="@color/semi_theme_blue"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginLeft="12dp"
        android:layout_centerVertical="true" />

 </RelativeLayout>

 <com.project.ui.NonScrollRecyclerView
     android:id="@+id/nrv"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:divider="@android:color/transparent"
     android:listSelector="@android:color/transparent" />

</LinearLayout>

2
为什么不直接使用LinearLayout而不是RecyclerView呢?你实际上是将RecyclerView转换成了一个LinearLayout,但是带来了更多的开销。 - Mike M.
同意上面的评论,只需摆脱recyclerView,如果你这样做了,就不会再问关于xml布局问题的事情了。http://stackoverflow.com/questions/29956014/why-should-we-use-xml-layouts - Nanoc
你可以根据自己的需求创建自己的线性布局管理器...请查看此链接 https://github.com/serso/android-linear-layout-manager/blob/master/lib/src/main/java/org/solovyev/android/views/llm/LinearLayoutManager.java - H Raval
2个回答

2

不建议在ScrollView中使用RecyclerView和ListView,因为在渲染ScrollView时,元素高度没有被计算。这意味着,在ScrollView显示时可能无法填充适配器,而当RecyclerView被通知数据更改时(例如初始化适配器时),没有办法重新计算元素高度。

这真的很麻烦,因为你必须尝试计算元素高度,而且永远不准确,所以在ScrollView中显示ListView或RecyclerView时会出现差异。一些如何计算元素高度的示例可以在这里这里查看。

我的建议是将RecyclerView转换为LinearLayout,并通过编程方式添加元素,以模拟ListView或RecyclerView的行为:

LinearLayout layout = (LinearLayout) rootView.findViewById(R.id.files);
layout.removeAllViews();

for (int i = 0; i < fileAdapter.getCount(); i++) {
    final View item = fileAdapter.getView(i, null, null);
item.setClickable(true);

    item.setId(i);

    item.setOnClickListener(new View.OnClickListener() {
        @Override
            public void onClick(View v) {

                fileContentRowPosition = v.getId();

        # Your click action here


    }
});


layout.addView(item);

}

这是文件定义的XML内容:

示例:

<ScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

...

    <LinearLayout
        android:id="@+id/files"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:orientation="vertical">
    </LinearLayout>


</ScrollView>

整个Java代码可以在这里查看,整个布局可以在这里查看。
另外,如果您仍想继续实现,并且关于您的问题,您可以查看这篇文章:在ScrollView中处理可滚动控件 此致敬礼。

1

如果整个页面只需要滚动一次,您可以使用 NestedScrollView 替代 ScrollView 并设置 recyclerView.setNestedScrollingEnabled(false);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接