Android GridLayoutManager – это реализация RecyclerView.LayoutManager
для размещения элементов в сетке. В этом уроке мы создадим приложение, отображающее CardViews внутри RecyclerView в виде GridLayout. Также мы реализуем интерфейс, делающий клик по элементу RecyclerView подобным ListView с использованием itemClickListener
.
Android GridLayoutManager
Мы реализовали RecyclerView с использованием LinearLayoutManager здесь. Теперь давайте используем GridLayoutManager
, чтобы разместить RecyclerView в виде сетки. Вот конструктор для GridLayoutManager.
GridLayoutManager (Context context,
int spanCount,
int orientation,
boolean reverseLayout)
Если reverseLayout установлен в true, то элементы размещаются с конца к началу. Чтобы установить размер ячейки для каждого элемента, мы вызываем метод setSpanSizeLookup
на GridLayoutManager. Давайте реализуем RecyclerView с использованием GridLayoutManager в новом проекте Android Studio.
Пример структуры проекта Android GridLayoutManager
Проект состоит из одной активности:
MainActivity.java
, класса адаптера: RecyclerViewAdapter.java
, класса DataModel.java
и пользовательского класса GridLayoutManager AutoFitGridLayoutManager.java
. Макет XML для класса MainActivity.java определен в файле 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>
Примечание: Не забудьте добавить следующие зависимости для виджетов Material Design и CardView
в файл build.gradle.
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 будет содержать текст, значок drawable и цвет фона каждой ячейки элемента. Класс 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. Макет XML для каждого элемента RecyclerView приведен ниже. 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);
}
}
Количество элементов span рассчитывается динамически на основе ориентации, доступной ширины и высоты. Класс 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
, определенный в классе адаптера. Таким образом, мы реализовали слушатель кликов RecyclerView внутри нашей активности, а не в классе адаптера (аналогично стандартному onItemClickListener, определенному для ListView) - A DataModel class holds the details for each RecyclerView item
- LayoutManager RecyclerView можно определить либо, создав экземпляр класса 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