Tôi có một DialogFragment
cái chứa một RecyclerView
(danh sách các thẻ).
Trong phạm vi này RecyclerView
là một hoặc nhiều CardViews
có thể có bất kỳ chiều cao.
Tôi muốn cung cấp cho DialogFragment
chiều cao chính xác này dựa trên chiều cao CardViews
được chứa trong đó.
Thông thường điều này sẽ đơn giản, tôi sẽ thiết lập wrap_content
trên RecyclerView
như thế này.
<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>
Bởi vì tôi đang sử dụng cái RecyclerView
này không hoạt động, xem:
https://issuetracker.google.com/issues/37001674
và
Nested Recycler xem chiều cao không bao bọc nội dung của nó
Trên cả hai trang này, mọi người đề nghị mở rộng LinearLayoutManager
và ghi đèonMeasure()
Đầu tiên tôi sử dụng LayoutManager rằng ai đó được cung cấp trong liên kết đầu tiên:
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);
}
}
}
Tuy nhiên điều này không hiệu quả vì
heightSize = View.MeasureSpec.getSize(heightSpec);
trả về một giá trị rất lớn dường như có liên quan đến match_parent
.
Bằng cách nhận xét height = heightSize;
(trong trường hợp chuyển đổi thứ hai) tôi đã xoay sở để làm cho chiều cao hoạt động nhưng chỉ khi một TextView
đứa trẻ bên trong CardView
không bọc văn bản của chính nó (một câu dài).
Ngay sau khi TextView
kết thúc văn bản của chính nó, chiều cao NÊN tăng nhưng không. Nó tính chiều cao cho câu dài đó là một dòng đơn, không phải là một dòng được bao bọc (2 hoặc nhiều hơn).
Bất cứ lời khuyên nào về cách tôi nên cải thiện điều này LayoutManager
để RecyclerView
làm việc với WRAP_CONTENT
?
Chỉnh sửa: Trình quản lý bố cục này có thể hoạt động với hầu hết mọi người, nhưng nó vẫn có vấn đề với việc cuộn và tính toán độ cao của gói văn bản
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);
}
}
}
Jan 22, 2016: This has been merged into the internal tree, should be available with the next version of support library.