Android GridLayoutManager示例
Android GridLayoutManager是RecyclerView.LayoutManager的实现,用于对网格中的项目进行布局。
在本教程中,我们将创建一个应用程序,该应用程序以GridLayout的形式在RecyclerView内显示CardViews。
另外,我们将实现一个接口,使RecyclerView项目单击类似于ListView itemClickListener
。
Android GridLayoutManager
我们在这里使用LinearLayoutManager实现了RecyclerView。
现在,让我们使用" GridLayoutManager"将RecyclerView布局为网格。
以下是GridLayoutManager的构造函数。
GridLayoutManager (Context context, int spanCount, int orientation, boolean reverseLayout)
reverseLayout如果设置为true,则从头到尾布局项目。
要设置每个项目的跨度大小,我们在GridLayoutManager上调用方法setSpanSizeLookup
让我们在新的Android Studio项目中使用GridLayoutManager实现RecyclerView。
Android GridLayoutManager示例项目结构
该项目由单个Activity:MainActivity.java,适配器类RecyclerViewAdapter.java,DataModel.java类和自定义GridLayoutManager类AutoFitGridLayoutManager.java组成。
MainActivity.java类的xml布局在文件" activity_main.xml"中定义为
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="https://schemas.android.com/apk/res-auto" android:fitsSystemWindows="true" tools:context=".MainActivity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior" </RelativeLayout> </android.support.design.widget.CoordinatorLayout>
注意:不要忘记在build.gradle文件中为Material Design小部件和CardView添加以下依赖项。
compile 'com.android.support:cardview-v7:25.1.1' compile 'com.android.support:design:25.1.1'
下面给出了DataModel.java类:package com.theitroad.recyclerviewgridlayoutmanager;
public class DataModel { public String text; public int drawable; public String color; public DataModel(String t, int d, String c ) { text=t; drawable=d; color=c; } }
DataModel类将保存每个项目单元格的文本,可绘制图标和背景颜色。
RecyclerViewAdapter.java类如下所示:
package com.theitroad.recyclerviewgridlayoutmanager; import android.content.Context; import android.graphics.Color; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import java.util.ArrayList; public class RecyclerViewAdapter extends RecyclerView.Adapter { ArrayList mValues; Context mContext; protected ItemListener mListener; public RecyclerViewAdapter(Context context, ArrayList values, ItemListener itemListener) { mValues = values; mContext = context; mListener=itemListener; } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public TextView textView; public ImageView imageView; public RelativeLayout relativeLayout; DataModel item; public ViewHolder(View v) { super(v); v.setOnClickListener(this); textView = (TextView) v.findViewById(R.id.textView); imageView = (ImageView) v.findViewById(R.id.imageView); relativeLayout = (RelativeLayout) v.findViewById(R.id.relativeLayout); } public void setData(DataModel item) { this.item = item; textView.setText(item.text); imageView.setImageResource(item.drawable); relativeLayout.setBackgroundColor(Color.parseColor(item.color)); } @Override public void onClick(View view) { if (mListener != null) { mListener.onItemClick(item); } } } @Override public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.recycler_view_item, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder Vholder, int position) { Vholder.setData(mValues.get(position)); } @Override public int getItemCount() { return mValues.size(); } public interface ItemListener { void onItemClick(DataModel item); } }
在上面的代码中,我们定义了一个ItemListener接口,该接口将在MainActivity.java类中实现。
每个RecyclerView项的xml布局如下。recycler_view_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:card_view="https://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.v7.widget.CardView android:id="@+id/cardView" android:layout_width="match_parent" android:layout_height="150dp" card_view:cardCornerRadius="0dp" card_view:cardElevation="@dimen/margin10" card_view:cardMaxElevation="@dimen/margin10" card_view:contentPadding="@dimen/margin10"> <RelativeLayout android:id="@+id/relativeLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_gravity="center"> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:tint="@android:color/white" android:padding="5dp" <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:textColor="@android:color/white" android:layout_below="@+id/imageView" </RelativeLayout> </android.support.v7.widget.CardView> </LinearLayout>
下面给出了AutoFitGridLayoutManager.java类:
package com.theitroad.recyclerviewgridlayoutmanager; import android.content.Context; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; public class AutoFitGridLayoutManager extends GridLayoutManager { private int columnWidth; private boolean columnWidthChanged = true; public AutoFitGridLayoutManager(Context context, int columnWidth) { super(context, 1); setColumnWidth(columnWidth); } public void setColumnWidth(int newColumnWidth) { if (newColumnWidth > 0 && newColumnWidth != columnWidth) { columnWidth = newColumnWidth; columnWidthChanged = true; } } @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { if (columnWidthChanged && columnWidth > 0) { int totalSpace; if (getOrientation() == VERTICAL) { totalSpace = getWidth() - getPaddingRight() - getPaddingLeft(); } else { totalSpace = getHeight() - getPaddingTop() - getPaddingBottom(); } int spanCount = Math.max(1, totalSpace/columnWidth); setSpanCount(spanCount); columnWidthChanged = false; } super.onLayoutChildren(recycler, state); } }
跨度计数是根据可用的方向,宽度和高度动态计算的。
MainActivity.java类如下:
package com.theitroad.recyclerviewgridlayoutmanager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.widget.Toast; import java.util.ArrayList; public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.ItemListener { RecyclerView recyclerView; ArrayList arrayList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.recyclerView); arrayList = new ArrayList(); arrayList.add(new DataModel("Item 1", R.drawable.battle, "#09A9FF")); arrayList.add(new DataModel("Item 2", R.drawable.beer, "#3E51B1")); arrayList.add(new DataModel("Item 3", R.drawable.ferrari, "#673BB7")); arrayList.add(new DataModel("Item 4", R.drawable.jetpack_joyride, "#4BAA50")); arrayList.add(new DataModel("Item 5", R.drawable.three_d, "#F94336")); arrayList.add(new DataModel("Item 6", R.drawable.terraria, "#0A9B88")); RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, arrayList, this); recyclerView.setAdapter(adapter); /** AutoFitGridLayoutManager that auto fits the cells by the column width defined. **/ /*AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500); recyclerView.setLayoutManager(layoutManager);*/ /** Simple GridLayoutManager that spans two columns **/ GridLayoutManager manager = new GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false); recyclerView.setLayoutManager(manager); } @Override public void onItemClick(DataModel item) { Toast.makeText(getApplicationContext(), item.text + " is clicked", Toast.LENGTH_SHORT).show(); } }
- 上面的类实现了接口RecyclerViewAdapter.ItemListener,并覆盖了适配器类中定义的方法onItemClick。
通过这样做,我们在Activity中实现了RecyclerView Click Listener而不是Adapter类(类似于为ListView定义的标准onItemClickListener) - DataModel类保存每个RecyclerView项的详细信息
- 可以通过实例化列宽度设置为500的AutoFitGridLayoutManager类或者通过调用GridLayoutManager类对象并将列数设置为2来定义RecyclerView的LayoutManager。
让我们看看带有标准GridLayoutManager代码的应用程序的输出。
如您所见,每一行都有两个在两个方向上都跨越列宽的项目。
现在注释掉简单GridLayoutManager的代码,并运行AutoFitGridLayoutManager的代码
AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500); recyclerView.setLayoutManager(layoutManager);
实际应用程序的输出如下。
从上面的输出中可以看到,当方向更改为横向时,每行都有三项,从而动态调整项目的大小以自动适应列宽。