NestedScrollView を作成すると、 NestedScrollingChild および NestedScrollingParent を正しく実装している限り、別のスクロールビュー内にスクロールビューを配置できます。
(これは悪いデザインパターンではありません。「Ian Lake(Googleから)実際にRecyclerView
をネストされたスクロールビュー内に配置することをお勧めします:plus.google.com/u/0/+AndroidDevelopers/posts/9kZ3SsXdT2T」)
RecyclerView を NestedScrollView に配置し、幸いなことにRecyclerViewは NestedScrollingChild を実装するため、 NestedScrollView に配置できます。
public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild
私はこれらの投稿を読みました:
NestedScrollView内でRecyclerViewを使用する方法
NestedScrollView、RecyclerView(Horizontal)、CoordinatorLayout内のNestedScrolling
しかし、ほとんどの投票されたソリューションの問題は、RecyclerView
のすべてのアイテムを呼び出すため、たとえば、それが無限のRecyclerViewであり、ユーザーがリストの最後に到達したときに、ネットワーク要求を作成したい場合ソリューションRecyclerView
は、RecyclerView
の最後の項目に自動的に到達するため、サーバーを繰り返し呼び出します。
とにかく、RecyclerView
をNestedScrollView
の内側に配置できるようにパラメーターを設定する方法(実際、framelayoutやrelativelayoutのようなビューグループをネストされたscrollviewの単一の子として配置し、recyclerviewをframelayoutまたはrelativelayout)
RecyclerView
をNestedScrollView
の中に入れると、表示するものは何もありません。
サンプルプロジェクトを作成するには、 cheesesquare を使用し、CheeseDetailActivity
をRecyclerViewに変更します。
BNKの答えは正しくありませんが、BNKは多くのことを試みました。だから私は彼に賞金を授与します。まだ素敵な解決策を探しています...
以下は私の新しい更新された答えです:
<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のサンプルプロジェクト にも更新しました
スクリーンショット:
より多くのデータをロードする必要がある場合にのみサーバーを呼び出すソリューションを次に示します。このようにして、NestedScrollView内に無限のRecyclerViewや他の多くのビューを配置できます。私にとってはうまく機能しています。
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);
}
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を保持するだけです。
これは、activityクラスのネストされた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>
これはfragmentコードです:
@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>