首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在NestedScrollView中使用RecyclerView?

如何在NestedScrollView中使用RecyclerView?
EN

Stack Overflow用户
提问于 2015-06-23 18:18:19
回答 26查看 239.2K关注 0票数 237

如何在NestedScrollView中使用RecyclerView?设置适配器后,RecyclerView内容不可见。

已更新更新布局代码。

代码语言:javascript
复制
<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>
EN

回答 26

Stack Overflow用户

发布于 2015-09-23 17:00:15

将您的recyclerView替换为,

代码语言:javascript
复制
<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" />

这里,

代码语言:javascript
复制
app:layout_behavior="@string/appbar_scrolling_view_behavior"

将会管理剩下的事情。

还有一件事,不需要把你的recyclerView放在NestedScrollView里面

票数 237
EN

Stack Overflow用户

发布于 2015-09-23 17:42:42

更新1

从安卓支持库23.2.0开始,增加了针对LayoutManagers的方法setAutoMeasureEnabled(true)。它使得RecyclerView能够包装它的内容,工作起来就像一个护身符。

http://android-developers.blogspot.ru/2016/02/android-support-library-232.html

所以只需添加如下内容:

代码语言:javascript
复制
    LayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setAutoMeasureEnabled(true);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setNestedScrollingEnabled(false);

更新2

由于27.1.0 setAutoMeasureEnabled已被弃用,因此您应该提供具有覆盖方法isAutoMeasureEnabled()的LayoutManager的自定义实现

但在多次使用RecyclerView之后,我强烈建议不要在包装模式下使用它,因为这不是它的目的。尝试使用具有多个项目类型的普通单个RecyclerView来重构整个布局。或者使用我在下面描述为最后手段的LinearLayout方法

旧答案(不推荐)

您可以在NestedScrollView中使用RecyclerView。首先,你应该实现你自己的自定义LinearLayoutManager,它使你的RecyclerView包装它的内容。例如:

代码语言:javascript
复制
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);
    }
}

之后,为您的RecyclerView使用此LayoutManager

代码语言:javascript
复制
recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));

但您也应该调用这两个方法:

代码语言:javascript
复制
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);

这里setNestedScrollingEnabled(false)禁用了RecyclerView的滚动,所以它不会截获来自NestedScrollView的滚动事件。并且setHasFixedSize(false)确定适配器内容的改变可以改变RecyclerView的大小

重要提示:此解决方案在某些情况下存在小错误,并存在性能问题,因此,如果您的RecyclerView中有很多项,我建议您使用列表视图的自定义LinearLayout-based实现,为其创建类似适配器,并使其行为类似于ListViewRecyclerView

票数 126
EN

Stack Overflow用户

发布于 2016-05-02 15:56:55

  1. 您需要使用

上的支持库23.2.0 (或)

高度为wrap_content.的

  1. RecyclerView

  1. recyclerView.setNestedScrollingEnabled(false)

但是这样做,回收器模式就不起作用了,。(也就是说,所有的视图将被一次加载,因为wrap_content需要完整的RecyclerView的高度,所以它将一次绘制所有子Views。不会回收任何视图)。除非确实需要,否则请尽量不要使用此模式。尝试使用viewType并添加需要滚动到RecyclerView的所有其他视图,而不是在Scrollview中使用RecyclerView。这对性能的影响将非常大。

为了简单起见,“它只是充当所有子视图的LinearLayout”。

票数 125
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31000081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档