Recyclerview 在 scrollview 中- 如何滚动整个内容?

12

我在ScrollView中使用了RecyclerView

 <Scrollview
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

    <LinearLayout
        android:id="@+id/layoutStaticContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

       //Static content.
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="100dp">
           .
           .
        <LinearLayout>

         //Dynamic content(newsfeed)
         <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>
 </ScrollView>

现在在滚动时,layoutStaticContent固定在顶部,而recyclerview内容独立地在底部滚动。 如何滚动整个内容即(layoutStaticContent + recyclerview内容),以便只有1个scrollview? 我也尝试用Nestedscrollview替换scrollview,但没有成功。

5个回答

13

使用 android.support.v4.widget.NestedScrollView,然后在两个布局中包含NestedScrollView


我已经寻找这个解决方案好几天了。 - Andrei
如果有人使用的是 AndroidX 库而不是 Support 库,则 AndroidX 的等效库为:androidx.core.widget.NestedScrollView - Francis Laclé
你能否重新措辞一下吗?这是指用NestedScrollView替换ScrollView吗? - Mo...

8
将包含静态和动态数据的LinearLayout放入NestedScrollView中,它将像魔术般工作。
以下是所需代码:
<android.support.v4.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<LinearLayout
    android:id="@+id/layoutStaticContent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

   //Static content.
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp">
       .
       .
    <LinearLayout>

     //Dynamic content(newsfeed)
     <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>
</android.support.v4.widget.NestedScrollView>

我希望你能有所帮助!

4

解决这个问题的一种可能方法是仅在RecyclerView中使用静态内容作为标题。

然后布局将变得非常简单:

//Dynamic content(newsfeed)
     <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

您的静态内容将有一个list_item_header.xml布局:

//Static content.
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="100dp">
   .
   .
<LinearLayout>

您需要更改recyclerview适配器内容为:

private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;

@Override
public int getItemCount()
{
    int itemCount = super.getItemCount();
    if (mIsHeaderPresent)
    {
        itemCount += 1;
    }
    return itemCount;
}


@Override
public int getItemViewType(int position)
{
    if (mIsHeaderPresent && position == 0)
    {
        return TYPE_HEADER;
    }
    return TYPE_ITEM;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
    if (viewType == TYPE_HEADER)
    {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item_header, parent, false);
        ViewHolderHeader viewHolder = new ViewHolderHeader(itemView);
        return viewHolder;
    } else if (viewType == TYPE_ITEM)
    {
        return getItemViewHolder(parent);
    }

    throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder passedViewHolder)
{
    if (mIsHeaderPresent && passedViewHolder instanceof ViewHolderHeader)
    {
        onBindHeaderViewHolder((ViewHolderHeader) passedViewHolder);
    } else
    {
        onBindItemViewHolder(passedViewHolder);
    }
}

Ankit,静态内容中可能有许多项,并且这些项在不同的屏幕上可能是不同的。而动态内容布局是固定的。因此,我更喜欢不修改适配器,因为我在许多地方都使用了这个适配器。 - Rushikesh Talokar

2

如果您想滚动所有数据,我认为您需要使用CoordinatorLayout。在CoordinatorLayout中,您可以使用AppBarLayout和CollapsingToolbarLayout来放置静态内容。因为在Android中,在另一个可滚动容器中使用可滚动容器是错误的方法。您可以像这样使用协调员布局。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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" 
android:fitsSystemWindows="true"
>
<android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:contentScrim="?attr/colorPrimary"
        android:fitsSystemWindows="true"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleMarginEnd="64dp"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

    //Static content.
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp">
       .
       .
    <LinearLayout>

</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>

  <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
  />
</android.support.design.widget.CoordinatorLayout>

谢谢你的回答。但我不想要可折叠的解决方案。这种解决方案的问题是,当向下滚动时,静态内容会立即开始出现,而不是像整个内容一样。 - Rushikesh Talokar
所以你希望你的静态内容看起来也像是您回收视图的一部分。只有当它到达第一个位置时,静态内容才会可见。 - Ankur1994a
我认为@Aniket的第二个答案会对您有所帮助。 - Ankur1994a

1

经过大量搜索和尝试,我找到了解决方案:

1. 在 ScrollView 中设置 RecyclerView 的高度:

    <ScrollView
       android:id="@+id/scrollView"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:fillViewport="true">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    ...
    <android.support.v7.widget.RecyclerView
            android:id="@+id/myPostsRecyclerView"
            android:layout_width="match_parent"
            **android:layout_height="550dp"**
            android:layout_below="@+id/textView7"
            android:background="@drawable/background"
            android:padding="5dp"
            **android:visibility="gone"**
            tools:listitem="@layout/item_send" />
    </RelativeLayout>
    </ScrollView>

2. 在适配器中,设置数据列表的位置:

public void setData(List<Post> posts) {
    this.posts.clear();
    this.posts.addAll(posts);
    notifyDataSetChanged();
    if (posts.size() < 1)
        activity.recyclerView.setVisibility(View.GONE);
    else {
        activity.recyclerView.setVisibility(View.VISIBLE);
        ViewGroup.LayoutParams params=activity.recyclerView.getLayoutParams();
        params.height=ViewGroup.LayoutParams.WRAP_CONTENT;
        activity.recyclerView.setLayoutParams(params);
    }

 }

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