【问题标题】:RecyclerView recalculate WRAP_CONTENTRecyclerView 重新计算 WRAP_CONTENT
【发布时间】:2016-07-01 11:03:54
【问题描述】:

在 23.2 版本中,我们现在可以将 WRAP_CONTENT 用于 recyclerView 高度,这很棒。我正在这样做,但是我想在将项目添加(或删除)到适配器后重新计算高度(从而增加或减少高度)。

我特别的RecyclerView 是从 1 个项目开始,然后在用户进行选择时添加项目。所以我需要RecyclerView 布局来增加高度,直到一个点。理想情况下,当列表增加或减少时,会出现平滑的动画。

布局后我们如何使它成为WRAP_CONTENT

试过了:

recyclerview.requestLayout();

recyclerview.invalidate();

【问题讨论】:

  • 您能详细解释一下您想要实现的目标吗?添加布局xml和一些代码也会很棒......
  • 确保你没有在你的回收站视图中调用setHasFixedSize
  • 我遇到了这个问题。您将需要调用 measure,但如果您使用多个子布局,则 android M 中存在错误。为了解决这个问题,添加一个 GlobalLayoutListener 并在 onGlobalLayout 中设置高度
  • 我觉得有点不清楚你想要什么。

标签: java android android-recyclerview


【解决方案1】:

我希望它可以与 View.invalidate() 一起使用。

如果这不起作用,请尝试在父视图上调用 requestLayoutinvalidate

【讨论】:

  • 在父视图上调用无效就可以了。当然,它不会动画增长或缩小。动画是一个更困难的问题,但这是最接近我的问题的解决方案。
【解决方案2】:

RecyclerView 如何根据新的 LayoutManger 调整自身大小

RecyclerView 小部件为创建列表和网格以及支持动画提供了先进且灵活的基础。此版本为 LayoutManager API 带来了令人兴奋的新功能:自动测量!这允许 RecyclerView 根据其内容的大小来调整自己的大小。这意味着以前不可用的场景,例如将 WRAP_CONTENT 用于 RecyclerView 的维度,现在是可能的。您会发现所有内置的 LayoutManagers 现在都支持自动测量。

由于此更改,请务必仔细检查项目视图的布局参数:以前忽略的布局参数(例如滚动方向中的 MATCH_PARENT)现在将得到完全尊重。

如果您有一个不扩展内置 LayoutManager 的自定义 LayoutManager,这是一个可选 API - 您需要调用 setAutoMeasureEnabled(true) 并进行一些细微的更改,详见方法的 Javadoc。

请注意,尽管 RecyclerView 为其子项设置动画,但它不会为其自身的边界更改设置动画。如果您想在 RecyclerView 边界发生变化时为其设置动画,可以使用 Transition API。

请阅读this

【讨论】:

    【解决方案3】:

    选项一

    你看到这个answer了吗?

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

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

    选项二

    尝试在绘制视图之前设置布局参数。我没有检查是否在 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。 我不确定这在布局刷新时是否会起作用,但也许值得一试。

    【讨论】:

    • 对我有用的是每次添加项目后使用 wrap_content 重新设置布局参数。
    【解决方案4】:

    使用这个类:

    请使用 23.2.1,因为 23.2 有问题。

    您是否尝试过在recyclerview 适配器上调用notifyDataSetChanged,只要我认为如果您将wrap_content 作为recyclerview 的高度,它应该可以毫无问题地扩展

    否则你可以使用这个类:

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

    【讨论】:

    • 你应该检查循环计数器与状态的 itemCount i &lt; state.getItemCount() 在这个,否则它给出 IndexOutOfBounds
    猜你喜欢
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多