RecyclerView重新计算WRAP_CONTENT。

15

在版本23.2中,我们现在可以使用WRAP_CONTENTrecyclerView的高度,这很棒。我正在使用这个功能,但是当添加(或删除)适配器中的项目时(从而增加或减少高度),我想重新计算高度。

我的特定RecyclerView从1个项目开始,然后随着用户进行选择而添加项目。因此,我需要RecyclerView布局增加高度,直到一定点。理想情况下,在列表增加或减少时,这将以平滑的动画发生。

如何在已布局后使其WRAP_CONTENT

尝试过:

recyclerview.requestLayout();

recyclerview.invalidate();

你能详细解释一下你想要实现什么吗?如果能附上布局XML和一些代码就更好了... - crazyPixel
4
请勿在您的 RecyclerView 上调用 setHasFixedSize 方法。 - Wukash
我曾经遇到过这个问题。您需要调用measure,但是在使用多个子布局时,Android M存在一个错误。为了解决这个问题,请添加GlobalLayoutListener并在onGlobalLayout中设置高度。 - zafrani
我觉得有点不清楚你想要什么。 - user5703518
请查看以下链接:https://dev59.com/il4d5IYBdhLWcg3wLf_P#33542789 - Arun Antoney
4个回答

7

我预计它可以通过View.invalidate()来运行。

如果这不起作用,请尝试在父视图上调用requestLayoutinvalidate中的任一方法。


在父视图上调用invalidate就解决了问题。当然,它不会动画地增长或缩小。动画是一个更困难的问题,但这是我问题的最接近的解决方案。 - Patrick Jackson

4

如何使RecyclerView基于新的LayoutManager自动调整大小

RecyclerView小部件提供了一个高级和灵活的基础,用于创建列表和网格,并支持动画。此版本为LayoutManager API带来了一个令人兴奋的新功能:自动测量!这使得RecyclerView可以根据其内容的大小调整自身大小。这意味着先前不可用的场景,例如对RecyclerView的尺寸使用WRAP_CONTENT,现在成为可能。您会发现所有内置的LayoutManager都支持自动测量。

由于这个改变,请确保仔细检查您的项目视图的布局参数:之前被忽略的布局参数(例如在滚动方向上的MATCH_PARENT)现在将完全被尊重。

如果您有一个自定义的LayoutManager,它没有扩展内置的LayoutManager之一,则这是一个选择性的API-您需要调用setAutoMeasureEnabled(true),并进行一些详细说明在方法的Javadoc中进行的次要更改。

请注意,虽然RecyclerView会对其子项进行动画处理,但不会对其自身边界更改进行动画处理。如果您想要在更改RecyclerView边界时动画化它们,可以使用过渡API。

请阅读此文


2

选项 I

你看到了这个答案吗?

它没有使用recyclerView的WRAP_CONTENT,但是可能会起作用。

你也可以创建自己的自定义recyclerView(扩展RecyclerView),并覆盖那里的onMeasure()方法,而不是使用链接中的layoutManager。

选项 II

在绘制视图之前尝试设置布局参数。我没有检查recyclerView布局更改时是否被调用,但如果被调用,则会起作用。像这样(在Activity / Fragment的onCreate() / onCreateView()方法中:

recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() { 
                recyclerView.getViewTreeObserver().removeOnPreDrawListener(this);

                YourParentLayoutType.LayoutParams params = (YourParentLayoutType.LayoutParams) recyclerView.getLayoutParams();
                params.height = YourParentLayoutType.LayoutParams.WRAP_CONTENT;
                recyclerView.setLayoutParams(params);

                return true;
            }
        });

在代码中使用您的recyclerView的父布局类型,而不是YourParentLayoutType。我不确定当布局刷新时是否有效,但或许值得一试。


1
对我有效的方法是,在每次添加项目后,使用wrap_content重新设置布局参数。 - password

1
请使用这个类:
请使用23.2.1,因为23.2版本存在很多bug。
另外,您是否尝试在recyclerview适配器上调用notifyDataSetChanged方法?如果您将recyclerview的高度设置为wrap_content,则应该可以展开而不会出现问题。
否则,您可以使用这个类:
import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;

public class MyLinearLayoutManager extends LinearLayoutManager {

    public MyLinearLayoutManager(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(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:
        }

        int widthDesired = Math.min(widthSize,width);
        setMeasuredDimension(widthDesired, height);
    }

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                   int heightSpec, int[] measuredDimension) {
        View view = recycler.getViewForPosition(position);
        // 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);
        }
    }

1
在这种情况下,您应该检查循环计数器是否与状态的itemCount相匹配 i < state.getItemCount(),否则会导致IndexOutOfBounds错误。 - AA_PV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接