使用带有 GridLayoutManager 的 RecyclerView 的简单 Android 网格示例(如旧的 GridView)
Posted
技术标签:
【中文标题】使用带有 GridLayoutManager 的 RecyclerView 的简单 Android 网格示例(如旧的 GridView)【英文标题】:Simple Android grid example using RecyclerView with GridLayoutManager (like the old GridView) 【发布时间】:2017-03-27 23:56:05 【问题描述】:我知道RecyclerView
已经取代了旧的ListView
和GridView
的功能。我正在寻找一个非常基本的示例,该示例显示使用RecyclerView
的最小网格设置。我不是在寻找长篇教程风格的解释,只是一个最小的例子。我想模仿旧 GridView 的最简单的网格将包含以下功能:
【问题讨论】:
【参考方案1】:简答
对于那些已经熟悉setting up a RecyclerView
to make a list 的人来说,好消息是制作网格大致相同。当您设置RecyclerView
时,您只需使用GridLayoutManager
而不是LinearLayoutManager
。
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
如果您需要更多帮助,请查看以下示例。
完整示例
以下是一个类似于下图的最小示例。
从一个空的活动开始。您将执行以下任务来添加RecyclerView
网格。您需要做的就是复制并粘贴每个部分的代码。稍后您可以对其进行自定义以满足您的需求。
更新 Gradle 依赖项
确保您的应用程序gradle.build
文件中有以下依赖项:
compile 'com.android.support:appcompat-v7:27.1.1'
compile 'com.android.support:recyclerview-v7:27.1.1'
您可以将版本号更新为the most current。
创建活动布局
将RecyclerView
添加到您的 xml 布局中。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_>
<android.support.v7.widget.RecyclerView
android:id="@+id/rvNumbers"
android:layout_
android:layout_/>
</RelativeLayout>
创建网格单元布局
RecyclerView
网格中的每个单元格将只有一个 TextView
。创建一个新的布局资源文件。
recyclerview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:padding="5dp"
android:layout_
android:layout_>
<TextView
android:id="@+id/info_text"
android:layout_
android:layout_
android:gravity="center"
android:background="@color/colorAccent"/>
</LinearLayout>
创建适配器
RecyclerView
需要一个适配器来用您的数据填充每个单元格中的视图。创建一个新的 java 文件。
MyRecyclerViewAdapter.java
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder>
private String[] mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
MyRecyclerViewAdapter(Context context, String[] data)
this.mInflater = LayoutInflater.from(context);
this.mData = data;
// inflates the cell layout from xml when needed
@Override
@NonNull
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
return new ViewHolder(view);
// binds the data to the TextView in each cell
@Override
public void onBindViewHolder(@NonNull 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 implements View.OnClickListener
TextView myTextView;
ViewHolder(View itemView)
super(itemView);
myTextView = itemView.findViewById(R.id.info_text);
itemView.setOnClickListener(this);
@Override
public void onClick(View view)
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
// convenience method for getting data at click position
String getItem(int id)
return mData[id];
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener)
this.mClickListener = itemClickListener;
// parent activity will implement this method to respond to click events
public interface ItemClickListener
void onItemClick(View view, int position);
注意事项
虽然不是绝对必要的,但我包含了用于侦听单元格上的单击事件的功能。这在旧的GridView
中可用,是一种常见的需求。如果不需要,可以删除此代码。
在Activity中初始化RecyclerView
将以下代码添加到您的主要活动中。
MainActivity.java
public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener
MyRecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// data to populate the RecyclerView with
String[] data = "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48";
// set up the RecyclerView
RecyclerView recyclerView = findViewById(R.id.rvNumbers);
int numberOfColumns = 6;
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
adapter = new MyRecyclerViewAdapter(this, data);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
@Override
public void onItemClick(View view, int position)
Log.i("TAG", "You clicked number " + adapter.getItem(position) + ", which is at cell position " + position);
注意事项
请注意,该活动实现了我们在适配器中定义的ItemClickListener
。这使我们能够处理onItemClick
中的单元格点击事件。
完成
就是这样。您现在应该能够运行您的项目并获得类似于顶部图像的内容。
进行中
圆角
Use a CardView自动调整列
GridLayoutManager - how to auto fit columns?进一步研究
Android RecyclerView with GridView GridLayoutManager example tutorial Android RecyclerView Grid Layout Example Learn RecyclerView With an Example in Android RecyclerView: Grid with header Android GridLayoutManager with RecyclerView in Material Design Getting Started With RecyclerView and CardView on Android【讨论】:
@MarianPaździoch,是的,我只是把它作为一个最小的例子。它绝对可以使用一些美化工作。我会在以后的某个时间尝试更新这个答案。 我登录只是为了指出像你这样的人一直保持这个门户网站的活力和踢球。我在看到这个解决方案之前被困在这个问题上两天。非常感谢 @androiddeveloper,网格项目从左到右、从上到下排列。当项目多于屏幕无法容纳时,滚动是垂直的。 未来的读者,让我为您节省一些时间,关键是recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
@daka,说得好。我编辑了我的答案,将其包含在开头。【参考方案2】:
虽然我喜欢并欣赏Suragch's answer,但我想留下一个说明,因为我发现编写Adapter (MyRecyclerViewAdapter
) 来定义和公开Listener 方法onItemClick
是由于没有正确使用类封装,这不是最好的方法。所以我的建议是让 Adapter 单独处理 Listening 操作(这是他的目的!)并将这些操作与使用 Adapter 的 Activity 分开(MainActivity
)。所以这就是我设置适配器类的方式:
MyRecyclerViewAdapter.java
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder>
private String[] mData = new String[0];
private LayoutInflater mInflater;
// Data is passed into the constructor
public MyRecyclerViewAdapter(Context context, String[] data)
this.mInflater = LayoutInflater.from(context);
this.mData = data;
// Inflates the cell layout from xml when needed
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
// Binds the data to the textview in each cell
@Override
public void onBindViewHolder(ViewHolder holder, int position)
String animal = mData[position];
holder.myTextView.setText(animal);
// 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 implements View.OnClickListener
public TextView myTextView;
public ViewHolder(View itemView)
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.info_text);
itemView.setOnClickListener(this);
@Override
public void onClick(View view)
onItemClick(view, getAdapterPosition());
// Convenience method for getting data at click position
public String getItem(int id)
return mData[id];
// Method that executes your code for the action received
public void onItemClick(View view, int position)
Log.i("TAG", "You clicked number " + getItem(position).toString() + ", which is at cell position " + position);
请注意现在在MyRecyclerViewAdapter
中定义的onItemClick
方法,这是您希望为收到的事件/操作编写任务的地方。
为了完成这个转换,只需要做一个小改动:Activity 不再需要实现 MyRecyclerViewAdapter.ItemClickListener
,因为现在这完全由 适配器。这将是最后的修改:
MainActivity.java
public class MainActivity extends AppCompatActivity
MyRecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// data to populate the RecyclerView with
String[] data = "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48";
// set up the RecyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rvNumbers);
int numberOfColumns = 6;
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
adapter = new MyRecyclerViewAdapter(this, data);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
【讨论】:
如果activity确实需要监听点击事件怎么办?例如将数据传递给演示者,根据单击的项目、跟踪等执行一些逻辑。 我同意 Adapter 应该处理点击事件,因为它有包含数据的项目。 @AhmadFadli 如果您需要在适配器的主机(片段或活动)中做一些工作,您应该使用您需要的方法创建一个回调接口。你的主机实现了这个接口。然后将主机实例传递给适配器的构造函数。拥有主机实例,您可以在需要时从适配器调用它的方法。您的主机我们会收到回调。这通常在您需要使用 ActionMode 时使用。当您长按选择项目并使用 ActionBar 按钮时。 我不同意,认为点击事件应该在托管Activity
中处理。因为只有点击监听器才能知道Activity
视图和其他Fragments
、Activities
等。适配器只能向上层发送点击事件。它应该有接口ItemClickListener
有这么多事件,因为许多事件适配器的视图可以产生。这个解决方案写得更早:***.com/a/40563598/2914140.【参考方案3】:
您应该将 RecyclerView
LayoutManager
设置为 Gridlayout 模式。当您想设置RecyclerView
LayoutManager
时,只需更改您的代码:
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), numberOfColumns));
【讨论】:
【参考方案4】:这是一种仅来自 XML 的简单方法
spanCount 表示列数
layoutManager 用于使其成为网格或线性(垂直或水平)
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/personListRecyclerView"
android:layout_
android:layout_
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
【讨论】:
【参考方案5】:在RecyclerView
初始化中设置
recyclerView.setLayoutManager(new GridLayoutManager(this, 4));
【讨论】:
它与其他答案有何不同?【参考方案6】:在您分配回收站视图的 MainActivity 中,只需使用此代码即可。
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
//recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
【讨论】:
【参考方案7】:如果你想在 xml 文件中的 reyclerview 中设置网格布局,那么你可以将这两个放在 recyclerview xml 中。
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount=numberOfItemsInSignleRow
如果你想通过 java 代码设置网格布局,你可以这样写。
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), numberOfItemsInSignleRow));
【讨论】:
【参考方案8】: There are 2 ways to achieve this
- In Xml
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list_amenities"
android:layout_
android:layout_
android:layout_marginTop="@dimen/_8sdp"
android:nestedScrollingEnabled="false"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
app:layout_constraintEnd_toEndOf="@+id/text_parking_lot_amenities" app:layout_constraintStart_toStartOf="@+id/text_parking_lot_amenities" app:layout_constraintTop_toBottomOf="@id/text_parking_lot_amenities" />
跨度计数用于网格列 - 在活动中
listAmenities.layoutManager = GridLayoutManager(this, TWO)
here TWO indicates number of grid columns
【讨论】:
以上是关于使用带有 GridLayoutManager 的 RecyclerView 的简单 Android 网格示例(如旧的 GridView)的主要内容,如果未能解决你的问题,请参考以下文章
带有 Gridlayoutmanager 的 RecyclerView 加载和响应速度极慢
如何在recyclerview的gridLayoutManager中从cardview中删除右边距
在 recyclerview Gridlayoutmanager 中创建总线布局时的间距问题
使用 GridLayoutManager 实现 RecyclerView 时将项目居中