Android GridLayoutManager ist die Implementierung von RecyclerView.LayoutManager
zum Anordnen von Elementen in einem Raster. In diesem Tutorial erstellen wir eine Anwendung, die CardViews innerhalb eines RecyclerViews in Form eines GridLayouts anzeigt. Außerdem implementieren wir eine Schnittstelle, die einem RecyclerView-Elementklick ähnelt, wie bei einem ListView itemClickListener
.
Android GridLayoutManager
Wir haben bereits einen RecyclerView unter Verwendung eines LinearLayoutManager hier implementiert. Jetzt verwenden wir einen GridLayoutManager
, um den RecyclerView als Raster anzuordnen. Nachfolgend finden Sie der Konstruktor für einen GridLayoutManager.
GridLayoutManager (Context context,
int spanCount,
int orientation,
boolean reverseLayout)
reverseLayout, wenn auf true gesetzt, ordnet Elemente vom Ende zum Anfang an. Um die Spannweite für jedes Element festzulegen, rufen wir die Methode setSpanSizeLookup
auf dem GridLayoutManager auf. Lassen Sie uns den RecyclerView mit einem GridLayoutManager in einem neuen Android Studio-Projekt implementieren.
Android GridLayoutManager Beispiel Projektaufbau
Das Projekt besteht aus einer einzigen Aktivität:
MainActivity.java
, einer Adapterklasse: RecyclerViewAdapter.java
, einer DataModel.java
-Klasse und einer benutzerdefinierten GridLayoutManager-Klasse AutoFitGridLayoutManager.java
. Das XML-Layout der MainActivity.java-Klasse ist in der Datei activity_main.xml
definiert als
<?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>
Hinweis: Vergessen Sie nicht, die folgenden Abhängigkeiten für Material Design-Widgets und CardView
in der build.gradle-Datei hinzuzufügen.
compile 'com.android.support:cardview-v7:25.1.1'
compile 'com.android.support:design:25.1.1'
Die DataModel.java
-Klasse ist unten angegeben: 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;
}
}
Die DataModel-Klasse wird den Text, das zeichnungsfähige Symbol und die Hintergrundfarbe jeder Zellenposition speichern. Die RecyclerViewAdapter.java-Klasse ist unten angegeben:
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);
}
}
Im obigen Code haben wir eine ItemListener-Schnittstelle definiert, die in der MainActivity.java-Klasse implementiert wird. Das XML-Layout für jedes RecyclerView-Element ist unten angegeben. 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>
Die AutoFitGridLayoutManager.java-Klasse ist unten angegeben:
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);
}
}
Die Spannenzahl wird dynamisch berechnet, basierend auf der Ausrichtung, der verfügbaren Breite und Höhe. Die `MainActivity.java` Klasse sieht wie folgt aus:
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();
}
}
- Die obige Klasse implementiert das Interface `RecyclerViewAdapter.ItemListener` und überschreibt die Methode `onItemClick`, die in der Adapterklasse definiert ist. Dadurch haben wir den RecyclerView-Click-Listener innerhalb unserer Aktivität implementiert, anstatt in der Adapterklasse (ähnlich wie der standardmäßige onItemClickListener, der für eine ListView definiert ist)
- A DataModel class holds the details for each RecyclerView item
- Der LayoutManager des RecyclerView kann entweder durch Instanziierung der Klasse `AutoFitGridLayoutManager` mit der Spaltenbreite von 500 oder durch Aufruf des Objekts der Klasse `GridLayoutManager` und Festlegen der Anzahl von Spalten als 2 definiert werden
Lassen Sie uns die Ausgabe der Anwendung mit dem standardmäßigen GridLayoutManager-Code sehen. Wie Sie sehen können, hat jede Zeile zwei Elemente, die die Spaltenbreite in beiden Ausrichtungen einnehmen. Kommentieren Sie nun den Code für den einfachen GridLayoutManager aus und führen Sie den Code für AutoFitGridLayoutManager aus.
AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500);
recyclerView.setLayoutManager(layoutManager);
Die Ausgabe der Anwendung in Aktion ist unten angegeben. Wie Sie in der obigen Ausgabe sehen können, hat jede Zeile beim Wechsel in den Querformatmodus drei Elemente, wodurch die Elemente dynamisch an die Spaltenbreite angepasst werden. Damit endet dieses Tutorial. Sie können das endgültige Android GridLayoutManager-Projekt über den unten angegebenen Link herunterladen.
Source:
https://www.digitalocean.com/community/tutorials/android-gridlayoutmanager-example