Persönlich möchte ich RecyclerView dafür nicht unterordnen, da es für mich so scheint, als ob GridLayoutManager dafür verantwortlich ist, die Anzahl der Bereiche zu ermitteln. Nachdem ich einige Android-Quellcodes für RecyclerView und GridLayoutManager ausgegraben hatte, schrieb ich meinen eigenen klassenerweiterten GridLayoutManager, der die Aufgabe erledigt:
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);
}
}
Ich erinnere mich nicht wirklich, warum ich mich entschieden habe, die Anzahl der Spannen in onLayoutChildren festzulegen. Ich habe diese Klasse vor einiger Zeit geschrieben. Der Punkt ist jedoch, dass wir dies tun müssen, nachdem die Ansicht gemessen wurde. so können wir seine Höhe und Breite erhalten.
BEARBEITEN 1: Fehler im Code behoben, der dazu führte, dass die Anzahl der Bereiche falsch eingestellt wurde. Vielen Dank an Benutzer @Elyees Abouda für die Berichterstattung und den Lösungsvorschlag .
EDIT 2: Einige kleine Refactoring- und Fixkantengehäuse mit manueller Ausrichtung ändern die Handhabung. Vielen Dank an Benutzer @tatarize für die Berichterstellung und den Lösungsvorschlag .
LayoutManager
's Aufgabe , die Kinder und nicht zu legenRecyclerView
ist