Особисто мені не подобається підклас RecyclerView для цього, тому що мені здається, що GridLayoutManager несе відповідальність за виявлення кількості прольотів. Отже, після деякого копання андроїд-коду для RecyclerView та GridLayoutManager я написав власний розширений клас GridLayoutManager, який виконує цю роботу:
public class GridAutofitLayoutManager extends GridLayoutManager
{
private int columnWidth;
private boolean isColumnWidthChanged = true;
private int lastWidth;
private int lastHeight;
public GridAutofitLayoutManager(@NonNull final Context context, final int columnWidth) {
/* Initially set spanCount to 1, will be changed automatically later. */
super(context, 1);
setColumnWidth(checkedColumnWidth(context, columnWidth));
}
public GridAutofitLayoutManager(
@NonNull final Context context,
final int columnWidth,
final int orientation,
final boolean reverseLayout) {
/* Initially set spanCount to 1, will be changed automatically later. */
super(context, 1, orientation, reverseLayout);
setColumnWidth(checkedColumnWidth(context, columnWidth));
}
private int checkedColumnWidth(@NonNull final Context context, final int columnWidth) {
if (columnWidth <= 0) {
/* Set default columnWidth value (48dp here). It is better to move this constant
to static constant on top, but we need context to convert it to dp, so can't really
do so. */
columnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
context.getResources().getDisplayMetrics());
}
return columnWidth;
}
public void setColumnWidth(final int newColumnWidth) {
if (newColumnWidth > 0 && newColumnWidth != columnWidth) {
columnWidth = newColumnWidth;
isColumnWidthChanged = true;
}
}
@Override
public void onLayoutChildren(@NonNull final RecyclerView.Recycler recycler, @NonNull final RecyclerView.State state) {
final int width = getWidth();
final int height = getHeight();
if (columnWidth > 0 && width > 0 && height > 0 && (isColumnWidthChanged || lastWidth != width || lastHeight != height)) {
final int totalSpace;
if (getOrientation() == VERTICAL) {
totalSpace = width - getPaddingRight() - getPaddingLeft();
} else {
totalSpace = height - getPaddingTop() - getPaddingBottom();
}
final int spanCount = Math.max(1, totalSpace / columnWidth);
setSpanCount(spanCount);
isColumnWidthChanged = false;
}
lastWidth = width;
lastHeight = height;
super.onLayoutChildren(recycler, state);
}
}
Я насправді не пам'ятаю, чому я вирішив встановити кількість прольотів у onLayoutChildren, я писав цей клас деякий час тому. Але справа в тому, що нам потрібно це зробити після того, як огляд буде виміряний. щоб ми могли отримати його висоту і ширину.
EDIT 1: Виправлення помилки в коді, викликаної неправильним встановленням кількості прольотів. Дякуємо користувачеві @Elyees Abouda за повідомлення та пропозицію рішення .
EDIT 2: Деякі невеликі рефактори та виправлення кромки з ручною зміною орієнтації. Дякуємо користувачеві @tatarize за повідомлення та пропозицію рішення .
LayoutManager
«s робота закладати дітей поза , а неRecyclerView
" s