如何让 WRAP_CONTENT 在 RecyclerView 上工作 [英] How do I make WRAP_CONTENT work on a RecyclerView

查看:20
本文介绍了如何让 WRAP_CONTENT 在 RecyclerView 上工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 DialogFragment,其中包含一个 RecyclerView(卡片列表).

I have a DialogFragment that contains a RecyclerView (a list of cards).

在这个 RecyclerView 中有一个或多个可以有任何高度的 CardViews.

Within this RecyclerView are one or more CardViews that can have any height.

我想根据其中包含的 CardViews 给这个 DialogFragment 正确的高度.

I want to give this DialogFragment the correct height based on the CardViews that are contained within.

通常这很简单,我会像这样在 RecyclerView 上设置 wrap_content.

Normally this would be simple, I would set wrap_content on the RecyclerView like this.

<android.support.v7.widget.RecyclerView ...
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"   
    android:clickable="true"   
    android:scrollbars="vertical" >

</android.support.v7.widget.RecyclerView>

因为我使用的是 RecyclerView 这不起作用:

Because I am using a RecyclerView this does not work:

https://issuetracker.google.com/issues/37001674

嵌套的 Recycler 视图高度不包裹其内容

在这两个页面上,人们建议扩展 LinearLayoutManager 并覆盖 onMeasure()

On both of these pages people suggest to extend LinearLayoutManager and to override onMeasure()

我首先使用了某人在第一个链接中提供的 LayoutManager:

I first used the LayoutManager that someone provided in the first link:

public static class WrappingLayoutManager extends LinearLayoutManager {

        public WrappingLayoutManager(Context context) {
            super(context);
        }

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

            measureScrapChild(recycler, 0,
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                    mMeasuredDimension);

            int width = mMeasuredDimension[0];
            int height = mMeasuredDimension[1];

            switch (widthMode) {
                case View.MeasureSpec.EXACTLY:
                case View.MeasureSpec.AT_MOST:
                    width = widthSize;
                    break;
                case View.MeasureSpec.UNSPECIFIED:
            }

            switch (heightMode) {
                case View.MeasureSpec.EXACTLY:
                case View.MeasureSpec.AT_MOST:
                    height = heightSize;
                    break;
                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 != 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();
                measuredDimension[1] = view.getMeasuredHeight();
                recycler.recycleView(view);
            }
        }
    }

但是这不起作用因为

heightSize = View.MeasureSpec.getSize(heightSpec);

返回一个看起来与match_parent相关的非常大的值.

returns a very large value that appear to be related to match_parent.

通过评论 height = heightSize;(在第二个 switch 案例中)我设法使高度起作用,但前提是 CardView<中有 TextView 子项/code> 不换行它自己的文本(一个长句子).

By commenting height = heightSize; (in the second switch case) I managed to make the height work but only if a TextView child inside the CardView does not wrap its own text (a long sentence).

一旦 TextView 包装它自己的文本,高度应该增加,但它没有.它将那个长句子的高度计算为一行,而不是一行(2 或更多).

As soon as that TextView wraps it's own text the height SHOULD increase but it doesn't. It calculated the height for that long sentence as a single line, not a wrapped line (2 or more).

关于我应该如何改进这个 LayoutManager 以便我的 RecyclerViewWRAP_CONTENT 一起工作有什么建议吗?

Any advice on how I should improve this LayoutManager so my RecyclerView works with WRAP_CONTENT?

此布局管理器可能适用于大多数人,但在滚动和计算环绕文本视图的高度方面仍然存在问题

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++) {
        measureScrapChild(recycler, i,
                View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                mMeasuredDimension);

        if (getOrientation() == HORIZONTAL) {
            width = width + mMeasuredDimension[0];
            if (i == 0) {
                height = mMeasuredDimension[1];
            }
        } else {
            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 != 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);
        }
    }
}

推荐答案

来自 Android 支持库 23.2.1 更新,所有 WRAP_CONTENT 都应该可以正常工作.

From Android Support Library 23.2.1 update, all WRAP_CONTENT should work correctly.

请更新gradle文件中的库版本OR以进一步:

Please update version of a library in gradle file OR to further :

compile 'com.android.support:recyclerview-v7:23.2.1'

解决了一些问题,例如修复了与各种测量规范方法相关的错误

检查 http://developer.android.com/tools/support-library/features.html#v7-recyclerview

您可以查看支持库修订历史

这篇关于如何让 WRAP_CONTENT 在 RecyclerView 上工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆