foo*_*o64 101 android android-gridlayout gridlayoutmanager android-recyclerview
使用新的GridLayoutManager:https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.html
它需要一个明确的跨度计数,所以问题现在变成:你怎么知道每行有多少"跨度"?毕竟这是一个网格.根据测量的宽度,RecyclerView可以容纳多个跨距.
使用旧的GridView
,您只需设置"columnWidth"属性,它将自动检测适合的列数.这基本上是我想要为RecyclerView复制的:
RecyclerView
这似乎是很常见的行为,所以有一种我没有看到的更简单的方法吗?
s.m*_*aks 115
Personaly我不喜欢为此子类化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);
}
}
Run Code Online (Sandbox Code Playgroud)
我实际上不记得为什么我选择在onLayoutChildren中设置跨度计数,我不久前写了这个类.但重点是我们需要在观察后进行测量.所以我们可以得到它的高度和宽度.
编辑:修复导致错误设置跨度计数的代码错误.感谢用户@Elyees Abouda报告和建议解决方案.
spe*_*ads 28
我使用视图树观察器完成了这一点,一旦渲染就获得recylcerview的宽度,然后从资源中获取卡片视图的固定尺寸,然后在进行计算后设置跨度计数.只有当您显示的项目具有固定宽度时,它才真正适用.这有助于我自动填充网格,无论屏幕大小或方向如何.
mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mRecyclerView.getViewTreeObserver().removeOnGLobalLayoutListener(this);
int viewWidth = mRecyclerView.getMeasuredWidth();
float cardViewWidth = getActivity().getResources().getDimension(R.dimen.cardview_layout_width);
int newSpanCount = (int) Math.floor(viewWidth / cardViewWidth);
mLayoutManager.setSpanCount(newSpanCount);
mLayoutManager.requestLayout();
}
});
Run Code Online (Sandbox Code Playgroud)
小智 15
嗯,这是我用过的,相当基本的,但是为我完成了工作.此代码基本上以dips为单位获取屏幕宽度,然后除以300(或者适用于适配器布局的任何宽度).因此,具有300-500倾角宽度的小型手机仅显示一列,平板电脑2-3列等.据我所知,简单,无忧无虑且没有缺点.
Display display = getActivity().getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
float density = getResources().getDisplayMetrics().density;
float dpWidth = outMetrics.widthPixels / density;
int columns = Math.round(dpWidth/300);
mLayoutManager = new GridLayoutManager(getActivity(),columns);
mRecyclerView.setLayoutManager(mLayoutManager);
Run Code Online (Sandbox Code Playgroud)
小智 13
我扩展了RecyclerView并覆盖了onMeasure方法.
我尽早设置了一个项目宽度(成员变量),默认值为1.这也更新了配置更改.现在,这将有适合纵向,横向,手机/平板电脑等的行数.
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
int width = MeasureSpec.getSize(widthSpec);
if(width != 0){
int spans = width / mItemWidth;
if(spans > 0){
mLayoutManager.setSpanCount(spans);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我发布这个以防万一有人像我的情况那样得到奇怪的列宽.
由于声誉不佳,我无法对@ s-marks的答案发表评论.我应用了他的解决方案解决方案,但我得到了一些奇怪的列宽,所以我修改了checkedColumnWidth函数,如下所示:
private int checkedColumnWidth(Context context, 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());
}
else
{
columnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, columnWidth,
context.getResources().getDisplayMetrics());
}
return columnWidth;
}
Run Code Online (Sandbox Code Playgroud)
通过将给定的列宽转换为DP固定问题.
更好的方法 (imo) 是在(许多)不同values
目录中定义不同的跨度计数,并让设备自动选择要使用的跨度计数。例如,
values/integers.xml
-> span_count=3
values-w480dp/integers.xml
-> span_count=4
values-w600dp/integers.xml
-> span_count=5
归档时间: |
|
查看次数: |
78908 次 |
最近记录: |