Osobiście nie lubię podklasy RecyclerView w tym celu, ponieważ wydaje mi się, że GridLayoutManager jest odpowiedzialny za wykrywanie liczby rozpiętości. Więc po pewnym kopaniu kodu źródłowego Androida dla RecyclerView i GridLayoutManager napisałem własną rozszerzoną klasę GridLayoutManager, która wykonuje zadanie:
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);
}
}
Właściwie nie pamiętam, dlaczego zdecydowałem się ustawić licznik rozpiętości w onLayoutChildren, napisałem tę klasę jakiś czas temu. Ale chodzi o to, że musimy to zrobić po zmierzeniu widoku. abyśmy mogli uzyskać jego wysokość i szerokość.
EDYCJA 1: Napraw błąd w kodzie, który powodował nieprawidłowe ustawienie liczby rozpiętości. Dziękuję użytkownikowi @Elyees Abouda za zgłoszenie i zasugerowanie rozwiązania .
EDYCJA 2: Trochę małych refaktoryzacji i napraw krawędziowych z ręczną obsługą zmian orientacji. Dziękuję użytkownikowi @tatarize za zgłoszenie i zasugerowanie rozwiązania .
LayoutManager
jest zadanie, aby stworzyć dzieciom out i nieRecyclerView
's