我个人不喜欢为此归类RecyclerView,因为对我来说,似乎GridLayoutManager负责检测跨度计数。因此,在为RecyclerView和GridLayoutManager挖掘了一些Android源代码之后,我编写了自己的扩展类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
的工作奠定了孩子出去,而不是RecyclerView
的