如何把RecyclerView里面的NestedScrollView?

创buildNestedScrollView ,只要那些实现了NestedScrollingChild和NestedScrollingParent ,就可以将滚动视图放在另一个滚动视图中。

(这不是糟糕的devise模式“Ian Lake(来自Google)实际上build议在这里添加一个RecyclerView在一个nestedscrollview中:plus.google.com/u/0/+AndroidDevelopers/posts/9kZ3SsXdT2T”)

我想把RecyclerView放在NestedScrollView中 ,幸运的是RecyclerView实现了NestedScrollingChild,所以你可以把它放在NestedScrollView中 。

 public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild 

我读过这些post:

如何在NestedScrollView中使用RecyclerView?

NestedScrollView,RecyclerView(水平),在CoordinatorLayout内

但是大多数投票解决scheme的问题是,它调用RecyclerView所有项目,例如,如果它是一个无尽的RecyclerView,并且当用户到达列表的末尾,您想要发出networking请求,那么RecyclerView调用该解决scheme服务器反复,因为它会自动到达RecyclerView的最后一个项目。

无论如何,如何设置参数,所以我可以把RecyclerView里面的NestedScrollView (实际上我想把一个像framelayout或relativelayout作为一个nestedscrollview单一的childe,然后我想把recyclerview里面framelayout或relativelayout)

当我把RecyclerView放在NestedScrollView里面的时候什么也没有显示。


为了创build示例项目,您可以使用cheesesquare并将CheeseDetailActivity更改为具有RecyclerView。


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

以下是我最新更新的答案:

 <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> 

在活动中:

  RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(true); // true: with header RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); final MyLinearLayoutManager layoutManager = new MyLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false, getScreenHeight(this)); // final CustomLinearLayoutManager layoutManager = new CustomLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(recyclerViewAdapter); // recyclerView.setNestedScrollingEnabled(false); // Disables scrolling for RecyclerView, however, CustomLinearLayoutManager used instead of MyLinearLayoutManager 

我也更新到我的GitHub的示例项目

截图:

在这里输入图像说明


只有当你真的需要加载更多的数据时,这里才是调用服务器的解决scheme。 通过这种方式,您可以将无尽的RecyclerView和NestedScrollView中的许多其他视图。 对我来说,它运作良好。

1.创buildEndlessParentScrollListener类来处理来自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); } 

2.设置监听器

 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(); } 

简短的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: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> 

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

这是在您的活动类中保存嵌套的recyclerview的framelayout:

  <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> 

把你的片段放入framelayout (代码位于activity类中):

  ExampleFragment exampleFragment = new ExampleFragment(); FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.add(R.id.container, exampleFragment); ft.commit(); 

在你的exampleFragment ,你可以把你的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> 

这是片段代码:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); llLayout = (RelativeLayout) inflater.inflate(R.layout.example_fragment_layout, container, false); mRecyclerView = (RecyclerView) llLayout.findViewById(R.id.my_recycler_view); 

以下是您应该拥有的CheeseSquare 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>