ScrollView中的RecyclerView不起作用

我试图实现一个布局,其中包含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的最后一个元素

我尝试过的事情:

  1. 卡片视图内的ScrollView(现在ScrollView包含RecyclerView) -可以看到卡片直到RecyclerView
  2. 最初的想法是使用RecyclerView而不是ScrollView来实现这个viewGroup,其中一个视图类型是CardView,但我得到了与ScrollView完全相同的结果
263304 次浏览
< p > <强> < em >更新: 这个答案现在已经过时了,因为有像NestedScrollView和RecyclerView这样的小部件支持嵌套滚动

永远不要把一个可滚动视图放在另一个可滚动视图中!

我建议你让你的主布局回收者视图,并把你的视图作为项目回收者视图。

看看这个例子,它展示了如何在回收器视图适配器中使用多个视图。 链接到示例 < / p >

尽管建议

永远不要把一个可滚动视图放在另一个可滚动视图中

这是一个很好的建议,但是如果你在回收器视图上设置了一个固定的高度,它应该可以正常工作。

如果你知道适配器项布局的高度,你就可以计算出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) {


}
});

实际上,RecyclerView的主要目的是补偿ListViewScrollView。而不是做你实际上在做的事情:在ScrollView中有一个RecyclerView,我建议只有一个RecyclerView,可以处理许多类型的子类型。

在ScrollViews中放入RecyclerViews很好,只要它们不是自己滚动。在这种情况下,将其设置为固定高度是有意义的。

正确的解决方案是在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,以编程方式膨胀子视图,并将它们添加到布局中。

手动计算RecyclerView的高度并不好,更好的方法是使用自定义的LayoutManager

出现上述问题的原因是,任何具有滚动(ListViewGridViewRecyclerView)的视图在添加为另一个具有滚动的视图的子视图时未能计算出它的高度。所以重写它的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,你可以使用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>

不需要通过代码进一步调整高度。

新的Android支持库23.2解决了这个问题,你现在可以将wrap_content设置为你的RecyclerView的高度并正确工作。

Android支持库23.2

使用NestedScrollView代替ScrollView

更多信息请参见NestedScrollView引用文档

并将recyclerView.setNestedScrollingEnabled(false);添加到你的RecyclerView

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

而且它没有任何问题

首先,你应该使用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的活动/片段中实现以下代码:

 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!");
}
}
});

我知道我迟到了,但即使谷歌已经对android.support.v7.widget.RecyclerView进行了修复,问题仍然存在

我现在得到的问题是RecyclerView,其中layout_height=wrap_content不取ScrollView中所有项目的高度,只有发生在Marshmallow和Nougat+ (API 23, 24, 25)版本上 (更新:用android.support.v4.widget.NestedScrollView替换ScrollView对所有版本都有效。我不知何故错过了测试接受的解决方案。在我的github项目中添加了这个演示。)

在尝试了不同的方法之后,我找到了解决这个问题的方法。

以下是我的布局结构:

<ScrollView>
<LinearLayout> (vertical - this is the only child of scrollview)
<SomeViews>
<RecyclerView> (layout_height=wrap_content)
<SomeOtherViews>

解决方法是用RelativeLayout包装RecyclerView。不要问我是怎么找到这个变通办法的!!¯\_(ツ)_/¯

<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中找到

下面是一个演示截图,展示了修复的操作:

截屏

我也有同样的问题。我试过了,而且成功了。我正在分享我的xml和java代码。希望这能帮助到一些人。

这是xml文件

<?xml version="1.0" encoding="utf-8"?>

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

下面是相关的java代码。这招很管用。

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setNestedScrollingEnabled(false);

如果RecyclerView只显示ScrollView中的一行。你只需要将行高度设置为android:layout_height="wrap_content"

你也可以这样用:

将这一行添加到您的recyclerView xml视图中:

        android:nestedScrollingEnabled="false"

尝试一下,recyclerview将平滑滚动,高度灵活

希望这对你有所帮助。

你也可以覆盖LinearLayoutManager使recyclerview滚动顺畅

@Override
public boolean canScrollVertically(){
return false;
}

抱歉迟到了,但似乎有另一种解决方案可以完美地解决你提到的情况。

如果在回收器视图中使用回收器视图,它似乎工作得非常好。我亲自尝试并使用过它,它似乎一点也不慢,一点也不突兀。现在我不确定这是否是一个好做法,但嵌套多个回收器视图,甚至嵌套滚动视图减慢。但这似乎工作得很好。请试一试。我确信嵌套在这方面是完全没问题的。

**对我有效的解决方案
使用高度为wrap_content的NestedScrollView

<br> RecyclerView
android:layout_width="match_parent"<br>
android:layout_height="wrap_content"<br>
android:nestedScrollingEnabled="false"<br>
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
tools:targetApi="lollipop"<br><br> and view holder layout
<br> android:layout_width="match_parent"<br>
android:layout_height="wrap_content"

//你的行内容在这里

试试这个。很晚才回答。但将来肯定能帮助到任何人。

设置你的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);

这招很管用:

recyclerView.setNestedScrollingEnabled(false);
如果你把RecyclerView放在NestedScrollView中,并启用recyclerView.setNestedScrollingEnabled(false);,滚动将工作得很好.
. > 然而,有一个问题

RecyclerView 不回收

例如,你的RecyclerView(在NestedScrollViewScrollView中)有100个元素 当Activity启动时,100个item 将创建(100个item的onCreateViewHolderonBindViewHolder将同时被调用).
例如,对于每个项目,你将从API => activity created ->加载一个大图像 它使启动活动缓慢和滞后。
可能的解决方案: < br > -考虑在多个类型中使用RecyclerView。< / p >

然而,如果在你的情况下,RecyclerView中只有几个项,而回收不回收对性能影响不大,你可以简单地在ScrollView中使用RecyclerView

我使用CustomLayoutManager禁用RecyclerView滚动。 也不要使用回收器视图作为WrapContent,使用它作为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中使用ConstraintLayout:

<ScrollView>
<ConstraintLayout> (this is the only child of ScrollView)
<...Some Views...>
<RecyclerView> (layout_height=wrap_content)
<...Some Other Views...>

但我仍然坚持androidx.core.widget.NestedScrollView 方法,由杨培勇提出

您可以尝试将回收器视图的高度设置为wrap_content。 在我的情况下,它工作得很好。我尝试在滚动视图中使用2个不同的回收器视图

最好的解决方案是将__ABC0保存在Single View / View Group中,然后将该视图保存在SrcollView中。 < / >强ie。

格式 -

<ScrollView>
<Another View>
<RecyclerView>
<TextView>
<And Other Views>
</Another View>
</ScrollView>

如。

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">


<TextView
android:text="any text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>




<TextView
android:text="any text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>

另一个。ScrollView的多个视图

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_weight="1">


<androidx.recyclerview.widget.RecyclerView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
/>


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:orientation="vertical">


<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/CategoryItem"
android:textSize="20sp"
android:textColor="#000000"
/>


<TextView
android:textColor="#000000"
android:text="₹1000"
android:textSize="18sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:textColor="#000000"
android:text="so\nugh\nos\nghs\nrgh\n
sghs\noug\nhro\nghreo\nhgor\ngheroh\ngr\neoh\n
og\nhrf\ndhog\n
so\nugh\nos\nghs\nrgh\nsghs\noug\nhro\n
ghreo\nhgor\ngheroh\ngr\neoh\nog\nhrf\ndhog"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>


</LinearLayout>


</LinearLayout>


</ScrollView>

对于那些试图这样做的人只是为了设计目的 -离开。重新设计你的应用,只留下RecyclerView。这将是比执行任何硬代码更好的解决方案。