Android GridLayoutManager 是 RecyclerView.LayoutManager 的實作,用於在網格中排列項目。在這個教程中,我們將創建一個應用程序,以 CardViews 的形式顯示在 RecyclerView 中,使用 GridLayout 進行佈局。同時,我們還將實現一個接口,使得 RecyclerView 項目點擊類似於 ListView 的 itemClickListener
。
Android GridLayoutManager
我們已經使用 LinearLayoutManager 實現了一個 RecyclerView,在這裡。現在,讓我們使用 GridLayoutManager
將 RecyclerView 佈局為網格。以下是 GridLayoutManager 的構造函數。
GridLayoutManager (Context context,
int spanCount,
int orientation,
boolean reverseLayout)
如果將 reverseLayout 設置為 true,則從末尾開始佈局項目。要為每個項目設置 span size,我們在 GridLayoutManager 上調用方法 setSpanSizeLookup
。讓我們在新的 Android Studio 項目中使用 GridLayoutManager 實現 RecyclerView。
Android GridLayoutManager 示例项目结构
该项目包含一个单一的活动:
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.journaldev.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.journaldev.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.journaldev.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.journaldev.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點擊監聽器,而不是在適配器類中(與ListView為其定義的標準onItemClickListener類似) - A DataModel class holds the details for each RecyclerView item
- RecyclerView的LayoutManager可以通過實例化AutoFitGridLayoutManager類並將列寬設置為500來定義,也可以通過調用GridLayoutManager類對象並將列數設置為2來定義
讓我們看一下使用標準GridLayoutManager代碼的應用程序輸出。如您所見,每行都有兩個項目,它們跨越了兩個方向上的列寬。現在將簡單GridLayoutManager的代碼註釋掉,運行AutoFitGridLayoutManager的代碼。
AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500);
recyclerView.setLayoutManager(layoutManager);
應用程式在執行中的輸出如下所示。 如上所述,當方向更改為橫向時,每行有三個項目,因此動態調整項目大小以自動適應列寬。這結束了本教程。您可以從下面的鏈接下載最終的Android GridLayoutManager項目。
Source:
https://www.digitalocean.com/community/tutorials/android-gridlayoutmanager-example