RecyclerView GridLayoutManager:如何自动检测跨度​​算什么?跨度、自动检测、RecyclerView、GridLayoutManager

2023-09-12 11:04:27 作者:呆滞与梦

使用新的GridLayoutManager:https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.html

Using the new GridLayoutManager: https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.html

这需要一个明确的跨度数,所以现在的问题就变成了:你怎么知道有多少跨越适合每行?这是一个网格,毕竟。应该有尽可能多的跨度为RecyclerView可以容纳的基础上,测量宽度。

It takes an explicit span count, so the problem now becomes: how do you know how many "spans" fit per row? This is a grid, after all. There should be as many spans as the RecyclerView can fit, based on measured width.

使用旧的GridView控件,你只需设置columnWidth中属性,它会自动检测列有多少适合。这基本上是我将复制的RecyclerView:

Using the old GridView, you would just set the "columnWidth" property and it would auto-detect how many columns fit. This is basically what I will replicate for RecyclerView:

添加OnLayoutChangeListener在RecyclerView 在此回调,夸大一个'网格项和衡量它 spanCount = recyclerViewWidth / singleItemWidth;

这似乎是pretty的共同的行为,那么有没有更简单的方式,我没有看到?

This seems like pretty common behavior, so is there a simpler way that I'm not seeing?

推荐答案

这是我一直在使用一个包装的相关部分自动检测跨度​​数。您可以通过调用初始化 setGridLayoutManager 与 R.layout.my_grid_item 的参考,并计算出有多少能适应每个行。

Here's the relevant parts of a wrapper I've been using to auto-detect the span count. You initialize it by calling setGridLayoutManager with a R.layout.my_grid_item reference, and it figures out how many of those can fit on each row.

public class AutoSpanRecyclerView extends RecyclerView {
    private int     m_gridMinSpans;
    private int     m_gridItemLayoutId;
    private LayoutRequester m_layoutRequester = new LayoutRequester();

    public void setGridLayoutManager( int orientation, int itemLayoutId, int minSpans ) {
        GridLayoutManager layoutManager = new GridLayoutManager( getContext(), 2, orientation, false );
        m_gridItemLayoutId = itemLayoutId;
        m_gridMinSpans = minSpans;

        setLayoutManager( layoutManager );
    }

    @Override
    protected void onLayout( boolean changed, int left, int top, int right, int bottom ) {
        super.onLayout( changed, left, top, right, bottom );

        if( changed ) {
            LayoutManager layoutManager = getLayoutManager();
            if( layoutManager instanceof GridLayoutManager ) {
                final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
                LayoutInflater inflater = LayoutInflater.from( getContext() );
                View item = inflater.inflate( m_gridItemLayoutId, this, false );
                int measureSpec = View.MeasureSpec.makeMeasureSpec( 0, View.MeasureSpec.UNSPECIFIED );
                item.measure( measureSpec, measureSpec );
                int itemWidth = item.getMeasuredWidth();
                int recyclerViewWidth = getMeasuredWidth();
                int spanCount = Math.max( m_gridMinSpans, recyclerViewWidth / itemWidth );

                gridLayoutManager.setSpanCount( spanCount );

                // if you call requestLayout() right here, you'll get ArrayIndexOutOfBoundsException when scrolling
                post( m_layoutRequester );
            }
        }
    }

    private class LayoutRequester implements Runnable {
        @Override
        public void run() {
            requestLayout();
        }
    }
}