如何自动确定 RecyclerView 网格的项目适合计数

Posted

技术标签:

【中文标题】如何自动确定 RecyclerView 网格的项目适合计数【英文标题】:How to automatically determine item fit count for RecyclerView grid 【发布时间】:2018-09-16 22:28:16 【问题描述】:

是否可以为 RecyclerView 使用指定的宽度 (100dp) 来平均分隔 Grid 中的项目(尽可能多),而不是使用精确的列数? int numberOfColumns = 3;int numberOfColumns = 4; 等将无法完成这项工作,因为这会导致大屏幕上出现大量空白空间。

纵向方向

横向

Fragment中与RecyclerView相关的代码

                static final String[] frenchVowels = new String[]
                    "a", "e", "i", "o", "u", "y"
                ;

                RecyclerViewAdapter rvAdapterGL;
                final RecyclerView rvGL = viewHolder.itemView.findViewById(R.id.rv);
                int numberOfColumns = 2;
                rvGL.setLayoutManager(new GridLayoutManager(getActivity(), numberOfColumns));
                rvAdapterGL = new RecyclerViewAdapter(getActivity(), frenchVowels);
                rvGL.setAdapter(rvAdapterGL);

RecyclerView 适配器类

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> 

    private String[] mData;
    private LayoutInflater mInflater;

    // data is passed into the constructor
    public RecyclerViewAdapter(Context context, String[] data) 
        this.mInflater = LayoutInflater.from(context);
        this.mData = data;
    

    // inflates the cell layout from xml when needed
    @Override
    @NonNull
    public RecyclerViewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 
        View view = mInflater.inflate(R.layout.gridview_item, parent, false);
        return new RecyclerViewAdapter.ViewHolder(view);
    

    // binds the data to the TextView in each cell
    @Override
    public void onBindViewHolder(@NonNull RecyclerViewAdapter.ViewHolder holder, int position) 
        holder.myTextView.setText(mData[position]);
    

    // total number of cells
    @Override
    public int getItemCount() 
        return mData.length;
    


    // stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder 
        TextView myTextView;

        ViewHolder(View itemView) 
            super(itemView);
            myTextView = itemView.findViewById(R.id.item_gridview);
        
    

XML

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:clickable="true"
    android:focusable="true"
    android:id="@+id/cv_gv"
    android:layout_marginBottom="20dp"
    >

    <LinearLayout
        android:id="@+id/cardview_gv_main"
        android:layout_
        android:layout_
        android:orientation="vertical"
        android:padding="10dp"
        android:animateLayoutChanges="true">

        <LinearLayout
            android:id="@+id/cardview_gv_titlerow"
            android:layout_
            android:layout_
            android:orientation="horizontal"
            android:layout_marginBottom="2dp"
            android:weightSum="100">

            <TextView
                android:id="@+id/tv_gv_A"
                android:layout_weight="90"
                android:layout_
                android:layout_
                android:textColor="?android:attr/textColorPrimary"
                style="@android:style/TextAppearance.Medium" />

            <TextView
                android:id="@+id/tv_gv_expandcollapse"
                android:importantForAccessibility="no"
                android:clickable="true"
                android:focusable="true"
                android:layout_weight="10"
                android:layout_
                android:layout_
                android:layout_marginStart="10dp"
                android:textColor="?android:attr/textColorPrimary"
                style="@android:style/TextAppearance.Large" />
        </LinearLayout>

        <RelativeLayout
            android:id="@+id/relativelayout_gv"
            android:animateLayoutChanges="true"
            android:layout_
            android:layout_>

            <GridView
                android:id="@+id/gv"
                android:layout_
                android:layout_
                android:columnWidth="100dp"
                android:numColumns="auto_fit"
                android:layout_marginBottom="20dp"
                android:stretchMode="columnWidth" />
        </RelativeLayout>

    </LinearLayout>
</android.support.v7.widget.CardView>

【问题讨论】:

【参考方案1】:

如果你使用 GridView 布局,这个问题回答here。

或者,如果您想使用 GridLayoutManager,请这样做

if(getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 2));

else
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 4));

【讨论】:

【参考方案2】:

有几种不同的方法来处理这个问题。您可以做的一件事是获取屏幕宽度并将其除以所需的单元格宽度以获得列数。

您还可以使用资源框架为不同的屏幕尺寸设置不同的列数。例如,您可以有一个 res/values/integers.xml 将列数设置为 3,还有一个 res/values-sw400dp/integers.xml 将列数设置为 5,依此类推。

res/values/integers.xml

<resources>
    <integer name=“column_count”>3</integer>
</resources>

res/values-sw400dp/integers.xml

<resources>
    <integer name=“column_count”>5</integer>
</resources>

现在你可以替换

int numberOfColumns = 2;

int numberOfColumns = getResources().getInteger(R.integer.column_count);

您可以使用任意数量的values-swXXXdp/integers.xml 文件,为XXX 提供许多不同的值,以便为许多不同的屏幕尺寸提供许多不同的列数。

【讨论】:

您的第一个建议将如何发挥作用(这听起来更有效率)? (屏幕宽度/所需单元格宽度(100dp)) 如果有的话,效率会降低,因为它需要实际计算而不是加载资源(框架已经疯狂优化)。不过,我会在今晚晚些时候尝试更新更多信息。 好吧,酷。仅仅使用 GridView 怎么样?我已经添加了我的 XML 布局文件。 ***.com/a/1016941/8298909 有关于以像素为单位获取屏幕宽度的信息。然后,您可以将所需的宽度(以 dp 为单位)乘以屏幕密度 getResources().getDisplayMetrics().density,以获得以像素为单位的列宽。然后将一个除以另一个以获得所需的列数。尽管如此,我个人还是会使用 &lt;integer&gt; 资源策略(好吧,我真的会使用 RecyclerView + FlexboxLayoutManager 但你说你不想要任何其他库)。【参考方案3】:

您应该使用flexbox-layout 库。它是由谷歌设计的开源库,它会根据行宽自动设置列数,您不需要指定列数。

而且它的用法也很简单:

RecyclerView recyclerView = (RecyclerView) context.findViewById(R.id.recyclerview);
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);

分级:

dependencies 
    implementation 'com.google.android:flexbox:1.0.0'

【讨论】:

尽量避免使用外部库,因为它们对应用程序来说很庞大。使用 GridView 怎么样?我已经添加了我的 XML 布局文件。

以上是关于如何自动确定 RecyclerView 网格的项目适合计数的主要内容,如果未能解决你的问题,请参考以下文章

Android - 网格中项目之间的 RecyclerView 间距

java 自动为RecyclerView项添加相等的间距。可以处理水平,垂直和网格显示模式

java 自动为RecyclerView项添加相等的间距。可以处理水平,垂直和网格显示模式

从自动完成中选择项目后如何填充 Ext.js 4 网格面板单元格?

RecyclerView更新时如何自动向下滚动

RecyclerView - 水平,两行网格,第二行偏移