同じレイアウトでRecyclerViewとScrollViewを含むレイアウトを実装しようとしています。
レイアウトテンプレート:
<RelativeLayout>
<ScrollView Android:id="@+id/myScrollView">
<unrelated data>...</unrealated data>
<Android.support.v7.widget.RecyclerView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:id="@+id/my_recycler_view"
/>
</ScrollView>
</RelativeLayout>
問題:ScrollView
の最後の要素までスクロールできます
私が試したこと:
ScrollView
内のカードビュー(現在のScrollView
はRecyclerView
を含む) - RecyclerView
までカードを見ることができるviewGroup
の代わりにRecyclerView
を使ってこのScrollView
を実装することでした。ビュータイプの1つはCardView
ですが、ScrollView
とまったく同じ結果が得られましたNestedScrollView
の代わりにScrollView
を使用する
NestedScrollViewのリファレンスドキュメント を参照してください。
RecyclerView
にrecyclerView.setNestedScrollingEnabled(false);
を追加します
私はゲームに遅れていることは知っていますが、GoogleがAndroid.support.v7.widget.RecyclerView
を修正した後でもこの問題は依然として存在します
私が今得ている問題は、RecyclerView
with layout_height=wrap_content
であり、ScrollView
内のすべてのアイテム問題の高さを取得していないことonlyMarshmallowおよびNougat +(API 23、24、25)バージョンで発生します。
(UPDATE:ScrollView
をAndroid.support.v4.widget.NestedScrollView
に置き換えると、すべてのバージョンで機能します。テストに失敗しました accepted solution 。デモとしてのgithubプロジェクト。)
別のことを試した後、この問題を修正する回避策を見つけました。
これが私のレイアウト構造の概要です:
<ScrollView>
<LinearLayout> (vertical - this is the only child of scrollview)
<SomeViews>
<RecyclerView> (layout_height=wrap_content)
<SomeOtherViews>
回避策は、RecyclerView
をRelativeLayout
でラップすることです。この回避策を見つけた方法を聞かないでください!!! ¯\_(ツ)_/¯
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:descendantFocusability="blocksDescendants">
<Android.support.v7.widget.RecyclerView
Android:layout_width="match_parent"
Android:layout_height="wrap_content" />
</RelativeLayout>
完全な例は、GitHubプロジェクトで利用できます- https://github.com/amardeshbd/Android-recycler-view-wrap-content
修正の実際を示すデモのスクリーンキャストは次のとおりです。
お勧めは
スクロール可能なビューを別のスクロール可能なビューの中に置いてはいけません。
確かなアドバイスですが、リサイクル業者のビューで固定の高さを設定した場合は正常に機能するはずです。
アダプタ項目のレイアウトの高さがわかっている場合は、RecyclerViewの高さを計算するだけで済みます。
int viewHeight = adapterItemSize * adapterData.size();
recyclerView.getLayoutParams().height = viewHeight;
RecyclerViewに固定の高さを設定しても(私のような)誰かにはうまくいかない場合は、固定高さのソリューションに追加したものがあります。
mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
rv.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
新しい Android Support Library 23.2 はこの問題を解決し、wrap_contentをRecyclerView
の高さとして設定できるようになり、正しく動作します。
それらが自分自身をスクロールしていない限り、RecyclerViewsはScrollViewsに入れるのが良いです。この場合、それを固定の高さにすることは理にかなっています。
適切な解決策は、RecyclerViewの高さにwrap_content
を使用してから、ラッピングを正しく処理できるカスタムのLinearLayoutManagerを実装することです。
このLinearLayoutManagerをあなたのプロジェクトにコピーしてください: https://github.com/serso/Android-linear-layout-manager/blob/master/lib/src/main/Java/org/solovyev/Android/views/llm/LinearLayoutManager .Java
次にRecyclerViewをラップします。
<Android.support.v7.widget.RecyclerView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"/>
そしてそれを次のように設定します。
RecyclerView list = (RecyclerView)findViewById(R.id.list);
list.setHasFixedSize(true);
list.setLayoutManager(new com.example.myapp.LinearLayoutManager(list.getContext()));
list.setAdapter(new MyViewAdapter(data));
編集:RecyclerViewがScrollViewのタッチイベントを盗むことができるので、これはスクロールの複雑さを引き起こす可能性があります。私の解決策は、単にRecyclerViewを全部捨ててLinearLayoutを使い、プログラム的にサブビューを膨らませてそれらをレイアウトに追加することでした。
ScrollView
の場合、fillViewport=true
を使用して、以下のようにlayout_height="match_parent"
を作成して、リサイクルビューを内側に配置することができます。
<ScrollView
Android:fillViewport="true"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_below="@+id/llOptions">
<Android.support.v7.widget.RecyclerView
Android:id="@+id/rvList"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
/>
</ScrollView>
コードによるそれ以上の高さ調整は必要ありません。
手動でRecyclerView
の高さを計算するのは良くありません。カスタムLayoutManager
を使うのが良いでしょう。
上記の問題の理由は、別のビューの子として追加したときにスクロールがある場合、そのスクロール(ListView
、GridView
、RecyclerView
)が高さの計算に失敗したビューです。そのため、onMeasure
メソッドをオーバーライドすると問題が解決します。
デフォルトのレイアウトマネージャを以下のものに置き換えてください。
public class MyLinearLayoutManager extends Android.support.v7.widget.LinearLayoutManager {
private static boolean canMakeInsetsDirty = true;
private static Field insetsDirtyField = null;
private static final int CHILD_WIDTH = 0;
private static final int CHILD_HEIGHT = 1;
private static final int DEFAULT_CHILD_SIZE = 100;
private final int[] childDimensions = new int[2];
private final RecyclerView view;
private int childSize = DEFAULT_CHILD_SIZE;
private boolean hasChildSize;
private int overScrollMode = ViewCompat.OVER_SCROLL_ALWAYS;
private final Rect tmpRect = new Rect();
@SuppressWarnings("UnusedDeclaration")
public MyLinearLayoutManager(Context context) {
super(context);
this.view = null;
}
@SuppressWarnings("UnusedDeclaration")
public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
this.view = null;
}
@SuppressWarnings("UnusedDeclaration")
public MyLinearLayoutManager(RecyclerView view) {
super(view.getContext());
this.view = view;
this.overScrollMode = ViewCompat.getOverScrollMode(view);
}
@SuppressWarnings("UnusedDeclaration")
public MyLinearLayoutManager(RecyclerView view, int orientation, boolean reverseLayout) {
super(view.getContext(), orientation, reverseLayout);
this.view = view;
this.overScrollMode = ViewCompat.getOverScrollMode(view);
}
public void setOverScrollMode(int overScrollMode) {
if (overScrollMode < ViewCompat.OVER_SCROLL_ALWAYS || overScrollMode > ViewCompat.OVER_SCROLL_NEVER)
throw new IllegalArgumentException("Unknown overscroll mode: " + overScrollMode);
if (this.view == null) throw new IllegalStateException("view == null");
this.overScrollMode = overScrollMode;
ViewCompat.setOverScrollMode(view, overScrollMode);
}
public static int makeUnspecifiedSpec() {
return View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
}
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
final boolean hasWidthSize = widthMode != View.MeasureSpec.UNSPECIFIED;
final boolean hasHeightSize = heightMode != View.MeasureSpec.UNSPECIFIED;
final boolean exactWidth = widthMode == View.MeasureSpec.EXACTLY;
final boolean exactHeight = heightMode == View.MeasureSpec.EXACTLY;
final int unspecified = makeUnspecifiedSpec();
if (exactWidth && exactHeight) {
// in case of exact calculations for both dimensions let's use default "onMeasure" implementation
super.onMeasure(recycler, state, widthSpec, heightSpec);
return;
}
final boolean vertical = getOrientation() == VERTICAL;
initChildDimensions(widthSize, heightSize, vertical);
int width = 0;
int height = 0;
// it's possible to get scrap views in recycler which are bound to old (invalid) adapter entities. This
// happens because their invalidation happens after "onMeasure" method. As a workaround let's clear the
// recycler now (it should not cause any performance issues while scrolling as "onMeasure" is never
// called whiles scrolling)
recycler.clear();
final int stateItemCount = state.getItemCount();
final int adapterItemCount = getItemCount();
// adapter always contains actual data while state might contain old data (f.e. data before the animation is
// done). As we want to measure the view with actual data we must use data from the adapter and not from the
// state
for (int i = 0; i < adapterItemCount; i++) {
if (vertical) {
if (!hasChildSize) {
if (i < stateItemCount) {
// we should not exceed state count, otherwise we'll get IndexOutOfBoundsException. For such items
// we will use previously calculated dimensions
measureChild(recycler, i, widthSize, unspecified, childDimensions);
} else {
logMeasureWarning(i);
}
}
height += childDimensions[CHILD_HEIGHT];
if (i == 0) {
width = childDimensions[CHILD_WIDTH];
}
if (hasHeightSize && height >= heightSize) {
break;
}
} else {
if (!hasChildSize) {
if (i < stateItemCount) {
// we should not exceed state count, otherwise we'll get IndexOutOfBoundsException. For such items
// we will use previously calculated dimensions
measureChild(recycler, i, unspecified, heightSize, childDimensions);
} else {
logMeasureWarning(i);
}
}
width += childDimensions[CHILD_WIDTH];
if (i == 0) {
height = childDimensions[CHILD_HEIGHT];
}
if (hasWidthSize && width >= widthSize) {
break;
}
}
}
if (exactWidth) {
width = widthSize;
} else {
width += getPaddingLeft() + getPaddingRight();
if (hasWidthSize) {
width = Math.min(width, widthSize);
}
}
if (exactHeight) {
height = heightSize;
} else {
height += getPaddingTop() + getPaddingBottom();
if (hasHeightSize) {
height = Math.min(height, heightSize);
}
}
setMeasuredDimension(width, height);
if (view != null && overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS) {
final boolean fit = (vertical && (!hasHeightSize || height < heightSize))
|| (!vertical && (!hasWidthSize || width < widthSize));
ViewCompat.setOverScrollMode(view, fit ? ViewCompat.OVER_SCROLL_NEVER : ViewCompat.OVER_SCROLL_ALWAYS);
}
}
private void logMeasureWarning(int child) {
if (BuildConfig.DEBUG) {
Log.w("MyLinearLayoutManager", "Can't measure child #" + child + ", previously used dimensions will be reused." +
"To remove this message either use #setChildSize() method or don't run RecyclerView animations");
}
}
private void initChildDimensions(int width, int height, boolean vertical) {
if (childDimensions[CHILD_WIDTH] != 0 || childDimensions[CHILD_HEIGHT] != 0) {
// already initialized, skipping
return;
}
if (vertical) {
childDimensions[CHILD_WIDTH] = width;
childDimensions[CHILD_HEIGHT] = childSize;
} else {
childDimensions[CHILD_WIDTH] = childSize;
childDimensions[CHILD_HEIGHT] = height;
}
}
@Override
public void setOrientation(int orientation) {
// might be called before the constructor of this class is called
//noinspection ConstantConditions
if (childDimensions != null) {
if (getOrientation() != orientation) {
childDimensions[CHILD_WIDTH] = 0;
childDimensions[CHILD_HEIGHT] = 0;
}
}
super.setOrientation(orientation);
}
public void clearChildSize() {
hasChildSize = false;
setChildSize(DEFAULT_CHILD_SIZE);
}
public void setChildSize(int childSize) {
hasChildSize = true;
if (this.childSize != childSize) {
this.childSize = childSize;
requestLayout();
}
}
private void measureChild(RecyclerView.Recycler recycler, int position, int widthSize, int heightSize, int[] dimensions) {
final View child;
try {
child = recycler.getViewForPosition(position);
} catch (IndexOutOfBoundsException e) {
if (BuildConfig.DEBUG) {
Log.w("MyLinearLayoutManager", "MyLinearLayoutManager doesn't work well with animations. Consider switching them off", e);
}
return;
}
final RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) child.getLayoutParams();
final int hPadding = getPaddingLeft() + getPaddingRight();
final int vPadding = getPaddingTop() + getPaddingBottom();
final int hMargin = p.leftMargin + p.rightMargin;
final int vMargin = p.topMargin + p.bottomMargin;
// we must make insets dirty in order calculateItemDecorationsForChild to work
makeInsetsDirty(p);
// this method should be called before any getXxxDecorationXxx() methods
calculateItemDecorationsForChild(child, tmpRect);
final int hDecoration = getRightDecorationWidth(child) + getLeftDecorationWidth(child);
final int vDecoration = getTopDecorationHeight(child) + getBottomDecorationHeight(child);
final int childWidthSpec = getChildMeasureSpec(widthSize, hPadding + hMargin + hDecoration, p.width, canScrollHorizontally());
final int childHeightSpec = getChildMeasureSpec(heightSize, vPadding + vMargin + vDecoration, p.height, canScrollVertically());
child.measure(childWidthSpec, childHeightSpec);
dimensions[CHILD_WIDTH] = getDecoratedMeasuredWidth(child) + p.leftMargin + p.rightMargin;
dimensions[CHILD_HEIGHT] = getDecoratedMeasuredHeight(child) + p.bottomMargin + p.topMargin;
// as view is recycled let's not keep old measured values
makeInsetsDirty(p);
recycler.recycleView(child);
}
private static void makeInsetsDirty(RecyclerView.LayoutParams p) {
if (!canMakeInsetsDirty) {
return;
}
try {
if (insetsDirtyField == null) {
insetsDirtyField = RecyclerView.LayoutParams.class.getDeclaredField("mInsetsDirty");
insetsDirtyField.setAccessible(true);
}
insetsDirtyField.set(p, true);
} catch (NoSuchFieldException e) {
onMakeInsertDirtyFailed();
} catch (IllegalAccessException e) {
onMakeInsertDirtyFailed();
}
}
private static void onMakeInsertDirtyFailed() {
canMakeInsetsDirty = false;
if (BuildConfig.DEBUG) {
Log.w("MyLinearLayoutManager", "Can't make LayoutParams insets dirty, decorations measurements might be incorrect");
}
}
}
これを試して。非常に遅い答えです。しかし、きっと誰かを助けてくれるでしょう。
ScrollviewをNestedScrollViewに設定します
<Android.support.v4.widget.NestedScrollView>
<Android.support.v7.widget.RecyclerView>
</Android.support.v7.widget.RecyclerView>
</Android.support.v4.widget.NestedScrollView>
あなたのRecyclerviewに
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
更新:入れ子になったスクロールをサポートするNestedScrollViewやRecyclerViewのようなウィジェットがあるので、この答えは現在古くなっています。
スクロール可能なビューを別のスクロール可能なビューの中に入れないでください。
メインレイアウトのリサイクラービューを作成し、そのビューをリサイクラービューの項目として配置することをお勧めします。
この例を見てみましょう。これは、リサイクラビューアダプタ内で複数のビューを使用する方法を示しています。 例へのリンク
RecyclerView
をNestedScrollView
の内側に入れてrecyclerView.setNestedScrollingEnabled(false);
を有効にすると、スクロールはうまく動作するになります。
しかし、問題があります
RecyclerView
リサイクルしないでください
たとえば、RecyclerView
(NestedScrollView
またはScrollView
内)には100個の項目があります。Activity
の起動時に、100個のitem 作成されます(100個のitemのonCreateViewHolder
とonBindViewHolder
が同時に呼び出されます)。
たとえば、各アイテムについて、API => activity created - > 100のイメージから大きなイメージをロードします。
それは活動の開始を遅らせ、遅らせる。
可能な解決策:
- 複数の型でRecyclerView
を使うことを考えています。
ただし、RecyclerView
の中にごく少数の項目しかなく、リサイクルまたはリサイクルしないがパフォーマンスに大きな影響を与えない場合は、単純にRecyclerView
の中にScrollView
を使用できます
この方法を使うことができます:
この行をrecyclerView xmlビューに追加します。
Android:nestedScrollingEnabled="false"
試してみてください、recyclerviewは柔軟な高さで滑らかにスクロールされます
これが助けになることを願っています。
私は同じ問題を抱えていました。それが私が試したことで、うまくいきます。 xmlとJavaコードを共有しています。これが誰かに役立つことを願っています。
これがxmlです
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<LinearLayout
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<ImageView
Android:id="@+id/iv_thumbnail"
Android:layout_width="match_parent"
Android:layout_height="200dp" />
<TextView
Android:id="@+id/tv_description"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="Description" />
<Button
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="Buy" />
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="Reviews" />
<Android.support.v7.widget.RecyclerView
Android:id="@+id/rc_reviews"
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
</Android.support.v7.widget.RecyclerView>
</LinearLayout>
</ScrollView>
これが関連するJavaコードです。それは魅力のように働きます。
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setNestedScrollingEnabled(false);
NestedScrollView
は問題を解決するようです。私はこのレイアウトを使ってテストしました:
<Android.support.v4.widget.NestedScrollView
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:id="@+id/activity_main"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
>
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical"
>
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="@string/dummy_text"
/>
<Android.support.v7.widget.CardView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginLeft="16dp"
Android:layout_marginRight="16dp"
>
<Android.support.v7.widget.RecyclerView
Android:id="@+id/recycler_view"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"/>
</Android.support.v7.widget.CardView>
</LinearLayout>
そしてそれは問題なく動作します
これがトリックです:
recyclerView.setNestedScrollingEnabled(false);
実際のRecyclerView
の主な目的はListView
とScrollView
を補うことです。 RecyclerView
にScrollView
を含めることで、多くの種類の子を処理できるRecyclerView
のみを持つことをお勧めします。
パーティーに遅刻して申し訳ありませんが、それはあなたが言及したケースのために完璧に動作する別の解決策があるようです。
リサイクラビューをリサイクラビュー内で使用する場合、それは完璧に動作するようです。私は個人的に試してみましたが、遅くもぎくしゃくも全くしていないようです。これが良い習慣であるかどうかはわかりませんが、複数のリサイクラービューをネストすると、ネストしたスクロールビューでさえ遅くなります。しかしこれはうまくいくようです。試してみてください。ネスティングはこれで完全にうまくいくと確信しています。
CustomLayoutManagerを使用してRecyclerView Scrollingを無効にしました。また、WrapContentとしてRecycler Viewを使用しないでください。0dp、Weight = 1として使用してください。
public class CustomLayoutManager extends LinearLayoutManager {
private boolean isScrollEnabled;
// orientation should be LinearLayoutManager.VERTICAL or HORIZONTAL
public CustomLayoutManager(Context context, int orientation, boolean isScrollEnabled) {
super(context, orientation, false);
this.isScrollEnabled = isScrollEnabled;
}
@Override
public boolean canScrollVertically() {
//Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
return isScrollEnabled && super.canScrollVertically();
}
}
RecyclerViewでCustomLayoutManagerを使用します。
CustomLayoutManager mLayoutManager = new CustomLayoutManager(getBaseActivity(), CustomLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(mLayoutManager);
((DefaultItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
recyclerView.setAdapter(statsAdapter);
UI XML
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@drawable/background_main"
Android:fillViewport="false">
<LinearLayout
Android:id="@+id/contParentLayout"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<FrameLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<edu.aku.family_hifazat.libraries.mpchart.charts.PieChart
Android:id="@+id/chart1"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginBottom="@dimen/x20dp"
Android:minHeight="@dimen/x300dp">
</edu.aku.family_hifazat.libraries.mpchart.charts.PieChart>
</FrameLayout>
<Android.support.v7.widget.RecyclerView
Android:id="@+id/recyclerView"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1">
</Android.support.v7.widget.RecyclerView>
</LinearLayout>
</ScrollView>
ScrollView内にRecyclerViewが1行のみを表示している場合。行の高さをAndroid:layout_height="wrap_content"
に設定するだけです。
また、リサイクルビューを円滑にロールバックするためにLinearLayoutManagerをオーバーライドすることもできます。
@Override
public boolean canScrollVertically(){
return false;
}
まずNestedScrollView
の代わりにScrollView
を使用し、RecyclerView
をNestedScrollView
の内側に配置します。
カスタムレイアウトクラスを使用して画面の高さと幅を測定します。
public class CustomLinearLayoutManager extends LinearLayoutManager {
public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
private int[] mMeasuredDimension = new int[2];
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
int width = 0;
int height = 0;
for (int i = 0; i < getItemCount(); i++) {
if (getOrientation() == HORIZONTAL) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
heightSpec,
mMeasuredDimension);
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
measureScrapChild(recycler, i,
widthSpec,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
height = height + mMeasuredDimension[1];
if (i == 0) {
width = mMeasuredDimension[0];
}
}
}
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
width = widthSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
height = heightSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
recycler.bindViewToPosition(view, position);
if (view != null) {
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
getPaddingLeft() + getPaddingRight(), p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
getPaddingTop() + getPaddingBottom(), p.height);
view.measure(childWidthSpec, childHeightSpec);
measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
}
}
そしてRecyclerView
のactivity/fragmentに以下のコードを実装します。
final CustomLinearLayoutManager layoutManager = new CustomLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(mAdapter);
recyclerView.setNestedScrollingEnabled(false); // Disables scrolling for RecyclerView, CustomLinearLayoutManager used instead of MyLinearLayoutManager
recyclerView.setHasFixedSize(false);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
int lastVisibleItemPos = layoutManager.findLastVisibleItemPosition();
Log.i("getChildCount", String.valueOf(visibleItemCount));
Log.i("getItemCount", String.valueOf(totalItemCount));
Log.i("lastVisibleItemPos", String.valueOf(lastVisibleItemPos));
if ((visibleItemCount + lastVisibleItemPos) >= totalItemCount) {
Log.i("LOG", "Last Item Reached!");
}
}
});