CẬP NHẬT 1
Vì Thư viện hỗ trợ Android 23.2.0, đã có thêm phương thức setAutoMeasureEnabled(true)
cho Trình quản lý bố cục. Nó làm cho RecyclerView bao bọc nội dung của nó và hoạt động như một bùa mê.
http://android-developers.blogspot.ru/2016/02/android-support-l Library-232.html
Vì vậy, chỉ cần thêm một cái gì đó như thế này:
LayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setAutoMeasureEnabled(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setNestedScrollingEnabled(false);
CẬP NHẬT 2
Do 27.1.0 setAutoMeasureEnabled
không được dùng nữa, do đó bạn nên cung cấp triển khai tùy chỉnh Trình quản lý bố cục với phương thức ghi đèisAutoMeasureEnabled()
Nhưng sau nhiều trường hợp sử dụng RecyclerView, tôi thực sự khuyên bạn không nên sử dụng nó trong chế độ gói , vì đây không phải là mục đích của nó. Cố gắng cấu trúc lại toàn bộ bố cục của bạn bằng cách sử dụng RecyclerView đơn thông thường với nhiều loại mục. Hoặc sử dụng phương pháp tiếp cận với linearLayout mà tôi mô tả bên dưới như là phương sách cuối cùng
Câu trả lời cũ (không nên dùng)
Bạn có thể sử dụng RecyclerView
bên trong NestedScrollView
. Trước hết bạn nên thực hiện tùy chỉnh của riêng bạn LinearLayoutManager
, nó làm cho bạn RecyclerView
bọc nội dung của nó. Ví dụ:
public class WrappingLinearLayoutManager extends LinearLayoutManager
{
public WrappingLinearLayoutManager(Context context) {
super(context);
}
private int[] mMeasuredDimension = new int[2];
@Override
public boolean canScrollVertically() {
return false;
}
@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:
}
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
if (view.getVisibility() == View.GONE) {
measuredDimension[0] = 0;
measuredDimension[1] = 0;
return;
}
// 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);
}
}
Sau đó sử dụng cái này LayoutManager
cho bạnRecyclerView
recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));
Nhưng bạn cũng nên gọi hai phương thức đó:
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
Ở đây setNestedScrollingEnabled(false)
vô hiệu hóa cuộn cho RecyclerView
, vì vậy nó không chặn sự kiện cuộn từ NestedScrollView
. Và setHasFixedSize(false)
xác định rằng những thay đổi trong nội dung bộ điều hợp có thể thay đổi kích thước củaRecyclerView
Lưu ý quan trọng: Giải pháp này có chút lỗi trong một số trường hợp và có vấn đề với độ hoàn hảo, vì vậy nếu bạn có nhiều mục trong thì RecyclerView
tôi khuyên bạn nên sử dụng LinearLayout
triển khai danh sách dựa trên tùy chỉnh , tạo tương tự Bộ điều hợp cho nó và làm cho nó cư xử như ListView
hayRecyclerView