如何让 WRAP_CONTENT 在 RecyclerView 上工作 [英] How do I make WRAP_CONTENT work on a 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
和
在这两个页面上,人们建议扩展 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
以便我的 RecyclerView
与 WRAP_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屋!