如何在RecyclerView
内使用NestedScrollView
?
设置适配器后,RecyclerView
内容不可见。
更新布局代码已更新。
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/keyline_1">
</RelativeLayout>
<View
android:id="@+id/separator"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#e5e5e5" />
<android.support.v7.widget.RecyclerView
android:id="@+id/conversation"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
答案 0 :(得分:184)
将recyclerView替换为,
NSWindows
这里,
<android.support.v7.widget.RecyclerView
android:id="@+id/conversation"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
将管理其余的事情。
还有一件事,不需要将您的recyclerView放在NestedScrollView
中答案 1 :(得分:112)
更新1
自Android支持库23.2.0以来,为LayoutManagers添加了方法setAutoMeasureEnabled(true)
。它使RecyclerView能够包装它的内容并像魅力一样工作
http://android-developers.blogspot.ru/2016/02/android-support-library-232.html
所以只需添加以下内容:
LayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setAutoMeasureEnabled(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setNestedScrollingEnabled(false);
更新2
由于不推荐使用27.1.0 setAutoMeasureEnabled
,因此您应该使用重写方法isAutoMeasureEnabled()
提供LayoutManager的自定义实现
但经过多次使用后,我强烈建议不要在包装模式中使用它,因为这不是它的目的。尝试使用具有多个项目类型的普通单个RecyclerView重构整个布局。或者使用LinearLayout的方法,我将在下面描述为最后的手段
旧答案(不推荐)
您可以在RecyclerView
内使用NestedScrollView
。
首先,您应该实现自己的自定义LinearLayoutManager
,它会让您的RecyclerView
包装其内容。
例如:
public class WrappingLinearLayoutManager extends LinearLayoutManager
{
public WrappingLinearLayoutManager(Context context) {
super(context);
}
private int[] mMeasuredDimension = new int[2];
@Override
public boolean canScrollVertically() {
return false;
}
@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(0, View.MeasureSpec.UNSPECIFIED),
heightSpec,
mMeasuredDimension);
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
measureScrapChild(recycler, i,
widthSpec,
View.MeasureSpec.makeMeasureSpec(0, 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);
if (view.getVisibility() == View.GONE) {
measuredDimension[0] = 0;
measuredDimension[1] = 0;
return;
}
// For adding Item Decor Insets to view
super.measureChildWithMargins(view, 0, 0);
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(
widthSpec,
getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view),
p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(
heightSpec,
getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view),
p.height);
view.measure(childWidthSpec, childHeightSpec);
// Get decorated measurements
measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin;
measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
}
之后使用此LayoutManager
作为RecyclerView
recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));
但是你也应该调用这两种方法:
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
此处setNestedScrollingEnabled(false)
禁用RecyclerView
的滚动,因此它不会拦截来自NestedScrollView
的滚动事件。 setHasFixedSize(false)
确定适配器内容的更改可以更改RecyclerView
重要提示:此解决方案在某些情况下很小,并且在性能方面存在问题,因此如果您RecyclerView
中有很多项目,我建议使用自定义{基于{1}}的列表视图实现,为其创建Adapter的模拟,并使其行为类似于LinearLayout
或ListView
答案 2 :(得分:88)
1)您需要使用上面的支持库23.2.0(或)
2)和RecyclerView
高度为wrap_content
。
3)recyclerView.setNestedScrollingEnabled(false)
但通过这样做,回收模式不起作用。 (即所有视图都会立即加载,因为wrap_content
需要完整RecyclerView
的高度,因此它会立即绘制所有子View
。没有视图会被回收)。除非确实需要,否则尽量不要使用此模式util。尝试使用viewType
并添加需要滚动到RecyclerView
的所有其他视图,而不是在RecyclerView
中使用Scrollview
。性能影响将非常高。
为了简单起见,它只是作为LinearLayout
充当所有子视图&#34;
答案 3 :(得分:34)
您可以使用android:fillViewport="true"
来NestedScrollView
衡量RecyclerView
。 RecyclerView
将填充剩余的高度。因此,如果您要滚动NestScrollView
,可以设置RecyclerView
的{{1}}。
答案 4 :(得分:25)
在recyclerView.setNestedScrollingEnabled(false);
本身为我工作之前简单地添加setAdapter
。我没有在任何地方添加app:layout_behavior="@string/appbar_scrolling_view_behavior"
和没有设置任何自定义布局管理器
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:text="Some Text..."
android:padding="15dp" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:padding="15dp"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Quick Links"
android:textColor="@color/black"
android:textStyle="bold"
android:textAllCaps="true"
android:paddingLeft="20dp"
android:drawableLeft="@drawable/ic_trending_up_black_24dp"
android:drawablePadding="10dp"
android:layout_marginBottom="10dp"
android:textSize="16sp"/>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#efefef"/>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
答案 5 :(得分:19)
这对我有用
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.v4.widget.NestedScrollView>
答案 6 :(得分:7)
尝试使用此库 - https://github.com/serso/android-linear-layout-manager。
库的LayoutManager使RecyclerView包装其内容。在这种情况下,RecyclerView将与内部视图一样大#34;因此它不会有滚动条,用户将使用NestedScrollView的滚动功能。因此,它不会像'#34;可滚动内部滚动&#34;。
那样含糊不清答案 7 :(得分:7)
有一个简单的测试代码可以检查
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.NestedScrollView>
答案 8 :(得分:6)
我在 NestedScrollView 中使用了 RecyclerView ,它对我有用。我必须记住的唯一问题是NestedScrollView只接受一个子视图。所以在我的情况下,我使用了LienearLayout viewgroup,它包含了我的RecyclerView以及我需要的其他一些视图。
我遇到一个问题,将我的RecyclerView放在NestedScrollView中。我意识到滚动我的RecyclerView的内容松了一口气。
我后来意识到我的RecyclerView正在接收滚动事件,因此与NestedScrollView的滚动行为相冲突。
所以要解决这个问题,我必须使用这种方法movieListNewRecyclerView.setNestedScrollingEnabled(false);
你可以在我的Instagram上查看我实际做过的简短视频。这是我的Instagram句柄ofelix03
答案 9 :(得分:6)
以下是我用来避免滚动问题的代码:
mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.getLayoutManager().setAutoMeasureEnabled(true);
mRecyclerView.setNestedScrollingEnabled(false);
mRecyclerView.setHasFixedSize(false);
答案 10 :(得分:4)
我在NestedScrollView中有Viewpager和RecyclerView。添加以下行后
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
我解决了慢滚动和滚动滞后问题。
答案 11 :(得分:3)
您无法在嵌套滚动视图中使用回收站视图。它并不打算包含进一步的可滚动视图,但这是因为它是滚动布局本身的子项,您需要嵌套的滚动视图。我有同样的问题,但最后我将textview移动到recyclelerview中的headerview,使recyclerview成为协调器布局的直接子项,并删除了嵌套的滚动视图。然后我的所有问题都消失了。
答案 12 :(得分:3)
如果您使用RecyclerView-23.2.1
或更高版本。以下解决方案将正常工作:
在您的布局中添加RecyclerView,如下所示:
<android.support.v7.widget.RecyclerView
android:id="@+id/review_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
在你的java文件中:
RecyclerView mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager=new LinearLayoutManager(getContext());
layoutManager.setAutoMeasureEnabled(true);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(new YourListAdapter(getContext()));
这里layoutManager.setAutoMeasureEnabled(true);
可以解决问题。
查看this issue和this developer blog了解详情。
答案 13 :(得分:2)
如果要在 NestedScrollView 中使用 RecyclerView ,这很简单,只需设置:
RecyclerView
recyclerView.setHasFixedSize(false)(java / kt)
android:nestedScrollingEnabled =“ false”
android:layout_height =“ wrap_content”
android:overScrollMode =“ never”
NestedScrollView
这对我来说很有效,您也可以在NestedScrollView中使用许多RecyclerView。
答案 14 :(得分:1)
我必须使用工具栏滚动来实现CoordinatorLayout,它让我整天都在忙着解决这个问题。我完全删除了NestedScrollView。所以我只是在根处使用RelativeLayout。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.support.v7.widget.RecyclerView
android:id="@+id/rv_nearby"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</RelativeLayout>
答案 15 :(得分:1)
有很多好的答案。关键是必须将java.lang.NoSuchMethodError: org.apache.http.conn.ssl.SSLConnectionSocketFactory.(Ljavax/net/ssl/SSLContext;Ljavax/net/ssl/HostnameVerifier;)V
设置为nestedScrollingEnabled
。如上所述,您可以使用Java代码来完成此操作:
false
但是您也有机会在xml代码(mRecyclerView.setNestedScrollingEnabled(false);
)中设置相同的属性:
android:nestedScrollingEnabled="false"
答案 16 :(得分:1)
对于androidx
,它被称为androidx.core.widget.NestedScrollView
-它也滚动了黄油,并且启用了属性isScrollContainer
和measureAllChildren
:
<!-- Scrolling Content -->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isScrollContainer="true"
android:measureAllChildren="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fastScrollEnabled="true"
android:scrollbarStyle="insideInset"
android:scrollbars="vertical"
android:splitMotionEvents="false"
android:verticalScrollbarPosition="right"/>
</androidx.core.widget.NestedScrollView>
答案 17 :(得分:1)
nestedScrollView.setNestedScrollingEnabled(true);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//...
}
});
<androidx.core.widget.NestedScrollView
android:id="@+id/nested"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:layout_below="@id/appBarLayout_orders"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout ...
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
答案 18 :(得分:0)
一种保留recyclerview的回收功能并避免recyclerview加载所有数据的解决方案是在recyclerview本身中设置固定高度。通过这样做,recyclerview仅限于加载,只要它的高度可以显示给用户,就可以在滚动到底部/顶部时回收其元素。
答案 19 :(得分:0)
如果您在 NestedScrollView 中使用 RecyclerView ScrollListener ,则同时使用addOnScrollListener侦听器将无法正常工作。
使用此代码。
<div class="sbp-item12">
<a href="#">
<div class="bottom-left">
<h3>Here is a headline</h3>
</div>
<figure>
<img src="https://placehold.it/380x250" alt="Here is a headline" />
</figure>
</a>
</div>
此代码在 NestedScrollView 内的 RecyclerView ScrollListener 正常工作。
谢谢
答案 20 :(得分:0)
请勿在NestedScrollView中使用recyclerView。可能会导致级联问题! 我建议在RecyclerView中使用ItemViewTypes处理多种视图。 只需添加一个具有match_parent宽度和高度的RecyclerView。然后在您的recyclerViewAdapter中重写getItemViewType并使用position来处理要放大的布局。之后,您可以使用onBindViewHolder方法处理视图持有人。
答案 21 :(得分:0)
我使用了这个很棒的扩展(用kotlin编写,但也可以用Java编写)
https://github.com/Widgetlabs/expedition-nestedscrollview
基本上,您可以在任何包中放入NestedRecyclerView
,让您在项目中说出utils,然后像这样创建recyclerview
<com.your_package.utils.NestedRecyclerView
android:id="@+id/rv_test"
android:layout_width="match_parent"
android:layout_height="match_parent" />
查看Marc Knaup的这篇很棒的文章
答案 22 :(得分:0)
就我而言,NestedScrollview的子级是ConstraintLayout。它没有按预期工作,我将其替换为LinearLayout。也许对某人有帮助。
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false"
app:layout_constraintBottom_toTopOf="@+id/divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tinTitle"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
答案 23 :(得分:0)
就我而言,这就是对我有用的
将android:fillViewport="true"
放在NestedScrollView内。
将RecyclerView的高度设置为wrap_content,即android:layout_height="wrap_content"
在RecyclerView android:nestedScrollingEnabled="false"
OR
以编程方式,在您的Kotlin课堂中
recyclerView.isNestedScrollingEnabled = false
mRecyclerView.setHasFixedSize(false)
答案 24 :(得分:0)
至少早在Material Components 1.3.0-alpha03之前,是否嵌套了RecyclerView(在ScrollView或NestedScrollView之外的其他形式)都没有关系。只需将app:layout_behavior="@string/appbar_scrolling_view_behavior"
放在其顶层父级中即可,它是CoordinatorLayout中AppBarLayout的同级。
当我将单个Activity架构与Jetpack Naviagation一起使用时,这对我一直有效,其中所有Fragment都从Activity的布局共享相同的AppBar。我将FragmentContainer设为CoordinatorLayout的直接子级,其中也包含AppBarLayout,如下所示。各个片段中的RecyclerViews正常滚动,并且AppBar可以折叠并重新出现。
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:defaultNavHost="true"
app:navGraph="@navigation/mobile_navigation"/>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_scrollFlags="scroll|enterAlways|snap" />
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
如果每个片段将其RecyclerView的ID传递给{{1}中的liftOnScroll
,则 AppBarLayout.liftOnScrollTargetViewId
(用于使应用栏在页面顶部看起来高度为零)起作用}。如果片段不滚动,则传递0。
答案 25 :(得分:-5)
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />