Лично мне не нравится создавать подкласс RecyclerView для этого, потому что мне кажется, что GridLayoutManager несет ответственность за определение количества промежутков. Итак, после некоторого поиска исходного кода Android для 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, я написал этот класс некоторое время назад. Но дело в том, что мы должны сделать это после того, как будет измерена точка зрения. так что мы можем получить его высоту и ширину.
РЕДАКТИРОВАТЬ 1: Исправить ошибку в коде, вызвавшую неправильную установку счетчика диапазона. Благодарим пользователя @Elyees Abouda за сообщение и предложение решения .
РЕДАКТИРОВАТЬ 2: Небольшой рефакторинг и исправление краевого случая с ручной обработкой изменений ориентации. Спасибо пользователю @tatarize за сообщение и предложение решения .
LayoutManager
«s работа закладывать детей вне , а неRecyclerView
» s