Android 如何将RecyclerView放入NestedScrollView?

Android 如何将RecyclerView放入NestedScrollView?,android,android-recyclerview,nestedscrollview,Android,Android Recyclerview,Nestedscrollview,通过创建,您可以将滚动视图放在另一个滚动视图中,只要这些视图实现正确 (这是一个不错的设计模式“Ian Lake(来自谷歌)实际上建议在nestedscrollview中放置一个RecyclerView,如下所示:plus.Google.com/u/0/+AndroidDevelopers/posts/9kZ3SsXdT2T”) 我想把它放在里面,幸运的是,回收工具可以放在里面 我读过这些帖子: 但大多数投票的解决方案的问题是,它调用RecyclerView的所有项,因此,例如,如果它是一个

通过创建,您可以将滚动视图放在另一个滚动视图中,只要这些视图实现正确

(这是一个不错的设计模式“Ian Lake(来自谷歌)实际上建议在nestedscrollview中放置一个
RecyclerView
,如下所示:plus.Google.com/u/0/+AndroidDevelopers/posts/9kZ3SsXdT2T”)

我想把它放在里面,幸运的是,回收工具可以放在里面

我读过这些帖子:

但大多数投票的解决方案的问题是,它调用
RecyclerView
的所有项,因此,例如,如果它是一个无止境的RecyclerView,当用户到达列表末尾时,您希望发出网络请求,那么使用该解决方案,
RecyclerView
会重复调用服务器,因为它会自动到达
RecyclerView
的最后一项

无论如何,如何设置参数,以便将
RecyclerView
放入
NestedScrollView
中(实际上,我想将framelayout或relativelayout这样的视图组作为NestedScrollView的单个子视图,然后将RecyclerView放入framelayout或relativelayout中)

当我将
RecyclerView
放入
NestedScrollView
中时,没有任何显示


为了创建一个示例项目,您可以使用并更改
CheeseDetailActivity
以创建一个RecyclerView



虽然BNK的答案不正确,但BNK已经尝试了很多。所以我给了他赏金。仍然在寻找很好的解决方案……

因此,将RecyclerView直接放在NestedScrollView中,不幸的是,不会显示任何内容。但是,有一种方法可以间接地将recyclerview放在NestedScrollView中—只需使用frameLayout作为第三方来保存你的recyclerview

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/post_container"
        android:background="#E0E0E0">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/my_recycler_view"
                android:scrollbars="vertical"

                android:layout_width="match_parent"
                android:layout_height="match_parent">
            </android.support.v7.widget.RecyclerView>


    </RelativeLayout>
这是一个framelayout,它在您的活动中保存嵌套的recyclerview类:

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context=".ExampleFragment"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            >
        </android.support.v4.widget.NestedScrollView>
   </FrameLayout>
 ExampleFragment exampleFragment = new ExampleFragment();

    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.add(R.id.container, exampleFragment);
    ft.commit();
在您的示例片段中,您可以放置您的recyclerview

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/post_container"
        android:background="#E0E0E0">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/my_recycler_view"
                android:scrollbars="vertical"

                android:layout_width="match_parent"
                android:layout_height="match_parent">
            </android.support.v7.widget.RecyclerView>


    </RelativeLayout>
以下是您应该具有的奶酪广场XML布局:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/detail_backdrop_height"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:fitsSystemWindows="true">

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

            <ImageView
                android:id="@+id/backdrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin" />

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

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

   <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context=".ExampleFragment"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            >
        </android.support.v4.widget.NestedScrollView>
   </FrameLayout>

    <android.support.design.widget.FloatingActionButton
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"
        android:src="@drawable/ic_discuss"
        android:layout_margin="@dimen/fab_margin"
        android:clickable="true"/>

</android.support.design.widget.CoordinatorLayout>

以下是我的最新答案:

<android.support.v4.widget.NestedScrollView
        android:id="@+id/scrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.CardView
                android:id="@+id/cardview1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Info CardView1"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/cheese_ipsum" />

                </LinearLayout>

            </android.support.v7.widget.CardView>

            <android.support.v7.widget.CardView
                android:id="@+id/cardview2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/cardview1"
                android:layout_margin="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Info CardView2"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/cheese_ipsum" />

                </LinearLayout>

            </android.support.v7.widget.CardView>

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recyclerview"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/cardview2"
                android:clipToPadding="false"
                android:paddingTop="0dp"/>

        </RelativeLayout>

    </android.support.v4.widget.NestedScrollView>
我也更新到

截图:



这是一种仅当您确实需要加载更多数据时才调用服务器的解决方案。通过这种方式,您可以将无休止的RecyclerView和许多其他视图放在NestedScrollView中。对我来说,它工作得很好

1。创建EndlessParentScrollListener类来处理NestedSrollView中的滚动事件

public abstract class EndlessParentScrollListener implements NestedScrollView.OnScrollChangeListener {
        // The current offset index of data you have loaded
        private int currentPage = 0;
        // The total number of items in the dataset after the last load
        private int previousTotalItemCount = 0;
        // True if we are still waiting for the last set of data to load.
        private boolean loading = true;
        // Sets the starting page index
        private int startingPageIndex = 0;
        // The minimum amount of pixels to have below your current scroll position
        // before loading more.
        private int visibleThresholdDistance = 300;

        RecyclerView.LayoutManager mLayoutManager;

        public EndlessParentScrollListener(RecyclerView.LayoutManager layoutManager) {
            this.mLayoutManager = layoutManager;
        }

        @Override
        public void onScrollChange(NestedScrollView scrollView, int x, int y, int oldx, int oldy) {
            // We take the last son in the scrollview
            View view = scrollView.getChildAt(scrollView.getChildCount() - 1);
            int distanceToEnd = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));

            int totalItemCount = mLayoutManager.getItemCount();
            // If the total item count is zero and the previous isn't, assume the
            // list is invalidated and should be reset back to initial state
            if (totalItemCount < previousTotalItemCount) {
                this.currentPage = this.startingPageIndex;
                this.previousTotalItemCount = totalItemCount;
                if (totalItemCount == 0) {
                    this.loading = true;
                }
            }

            // If it’s still loading, we check to see if the dataset count has
            // changed, if so we conclude it has finished loading and update the current page
            // number and total item count.
            if (loading && (totalItemCount > previousTotalItemCount)) {
                loading = false;
                previousTotalItemCount = totalItemCount;
            }

            // If it isn’t currently loading, we check to see if we have breached
            // the visibleThreshold and need to reload more data.
            // If we do need to reload some more data, we execute onLoadMore to fetch the data.
            // threshold should reflect how many total columns there are too
            if (!loading && distanceToEnd <= visibleThresholdDistance) {
                currentPage++;
                onLoadMore(currentPage, totalItemCount);
                loading = true;
            }
        }

        // Defines the process for actually loading more data based on page
        public abstract void onLoadMore(int page, int totalItemsCount);
    }
公共抽象类EndlessParentScrollListener实现NestedScrollView.OnScrollChangeListener{
//已加载数据的当前偏移索引
private int currentPage=0;
//上次加载后数据集中的项目总数
private int previousTotalItemCount=0;
//如果仍在等待加载最后一组数据,则为True。
私有布尔加载=真;
//设置起始页索引
私有int startingPageIndex=0;
//低于当前滚动位置的最小像素数
//在加载更多之前。
私有int VisibleSthresholdDistance=300;
RecyclerView.LayoutManager mllayoutmanager;
public EndlessParentScrollListener(RecyclerView.LayoutManager LayoutManager){
this.mLayoutManager=layoutManager;
}
@凌驾
public void onScrollChange(嵌套滚动视图滚动视图,int x,int y,int oldx,int oldy){
//我们在滚动视图中取最后一个儿子
View=scrollView.getChildAt(scrollView.getChildCount()-1);
int distanceToEnd=(view.getBottom()-(scrollView.getHeight()+scrollView.getScrollY());
int totalItemCount=mLayoutManager.getItemCount();
//如果项目总数为零,而前一个不是,则假定
//列表无效,应重置回初始状态
if(totalItemCountpreviousTotalItemCount)){
加载=假;
previousTotalItemCount=totalItemCount;
}
//如果当前未加载,我们将检查是否已违反
//VisibleSThreshold已关闭,需要重新加载更多数据。
//如果确实需要重新加载一些数据,则执行onLoadMore来获取数据。
//阈值应反映出有多少个总列
如果(!加载和距离结束(&D)

我已经浪费了至少一周的时间,唯一有效的解决办法是删除
嵌套滚动视图
。我知道这不是在
嵌套滚动视图
中添加
回收视图
这一特定问题的答案,但要让回收视图真正回收视图,你必须ong>必须删除
nestedscrollview
。如果您碰巧有多个
视图
,而不仅仅是
回收视图
,则必须通过设置不同的视图持有者,然后添加它们,将其作为
回收视图
的项目添加

app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout\u behavior=“@string/appbar\u scrolling\u view\u behavior”

到recyclerview或
public abstract class EndlessParentScrollListener implements NestedScrollView.OnScrollChangeListener {
        // The current offset index of data you have loaded
        private int currentPage = 0;
        // The total number of items in the dataset after the last load
        private int previousTotalItemCount = 0;
        // True if we are still waiting for the last set of data to load.
        private boolean loading = true;
        // Sets the starting page index
        private int startingPageIndex = 0;
        // The minimum amount of pixels to have below your current scroll position
        // before loading more.
        private int visibleThresholdDistance = 300;

        RecyclerView.LayoutManager mLayoutManager;

        public EndlessParentScrollListener(RecyclerView.LayoutManager layoutManager) {
            this.mLayoutManager = layoutManager;
        }

        @Override
        public void onScrollChange(NestedScrollView scrollView, int x, int y, int oldx, int oldy) {
            // We take the last son in the scrollview
            View view = scrollView.getChildAt(scrollView.getChildCount() - 1);
            int distanceToEnd = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));

            int totalItemCount = mLayoutManager.getItemCount();
            // If the total item count is zero and the previous isn't, assume the
            // list is invalidated and should be reset back to initial state
            if (totalItemCount < previousTotalItemCount) {
                this.currentPage = this.startingPageIndex;
                this.previousTotalItemCount = totalItemCount;
                if (totalItemCount == 0) {
                    this.loading = true;
                }
            }

            // If it’s still loading, we check to see if the dataset count has
            // changed, if so we conclude it has finished loading and update the current page
            // number and total item count.
            if (loading && (totalItemCount > previousTotalItemCount)) {
                loading = false;
                previousTotalItemCount = totalItemCount;
            }

            // If it isn’t currently loading, we check to see if we have breached
            // the visibleThreshold and need to reload more data.
            // If we do need to reload some more data, we execute onLoadMore to fetch the data.
            // threshold should reflect how many total columns there are too
            if (!loading && distanceToEnd <= visibleThresholdDistance) {
                currentPage++;
                onLoadMore(currentPage, totalItemCount);
                loading = true;
            }
        }

        // Defines the process for actually loading more data based on page
        public abstract void onLoadMore(int page, int totalItemsCount);
    }
private void initRecycler() {  
        //TODO init recycler adapter here

        recycler.setNestedScrollingEnabled(false);          
        LinearLayoutManager _layoutManager = new LinearLayoutManager(this);
        recycler.setLayoutManager(_layoutManager);
        NestedScrollView scrollView = (NestedScrollView) findViewById(R.id.scrollView);
        scrollView.setOnScrollChangeListener(new EndlessParentScrollListener(_layoutManager) {
                @Override
                public void onLoadMore(int page, int totalItemsCount) {                     
                    if (loadedItemCount < serverItemsCount)
                        customLoadMoreDataFromApi();
                }
            });
        customLoadMoreDataFromApi();
    }
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/background_light"
        android:fitsSystemWindows="true">


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

        <android.support.v4.widget.NestedScrollView
            android:id="@+id/scrollView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            android:scrollbars="vertical"
            android:scrollbarAlwaysDrawVerticalTrack="true"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:scrollbarAlwaysDrawVerticalTrack="false"
                android:scrollbars="vertical">

                <!-- some views goes here-->

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerFeed"
                    android:scrollbars="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

                <!-- and possibly here-->

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

    </android.support.design.widget.CoordinatorLayout>
  <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:fitsSystemWindows="true"
        app:layout_constraintTop_toTopOf="parent">

        <!-- Scrollable view here -->

        <com.google.android.material.appbar.AppBarLayout
            ....   >

            <com.google.android.material.appbar.CollapsingToolbarLayout
                ....>

                <androidx.appcompat.widget.Toolbar
                    ....>

                    <include
                        android:id="@+id/toolbar_header_view"
                        .... />
                </androidx.appcompat.widget.Toolbar>

                <include layout="@layout/widget_header" />
            </com.google.android.material.appbar.CollapsingToolbarLayout>
        </com.google.android.material.appbar.AppBarLayout>

        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            ....>
            <LinearLayout orientation="vertical" ....>
                <View .../>  <!-- I needed to have these two views along with recyclerview and i wanted them to do nestedscroll along with recyclerview -->
                <View .../>
                <androidx.recyclerview.widget.RecyclerView
                .... />
        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
app:layout_behavior="@string/appbar_scrolling_view_behavior"