RecyclerView
is a flexible widget provided in Material Design technology. With it, we can build both grid and list layouts (read this post). Because of it's new structure (not based on AdapterView
), beginners may feel difficult to approach but when get used to it, Android developers will realize it is an excellent alternative for GridView
and ListView
.I also had a post about making "auto-column" grid view by
RecyclerView
here and in this tip, I will present the way to make a staggered grid layout by this widget after a few simple steps.Import dependencies
RecyclerView
and CardView
dependencies (I used CardViews
as grid view item) to your application build.gradle
:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:cardview-v7:24.0.0'
compile 'com.android.support:recyclerview-v7:24.0.0'
compile 'com.android.support:appcompat-v7:24.0.0'
}
Building RecyclerView adapter
RecyclerView.ViewHolder
is required in building a RecyclerView
adapter:
public class BookViewHolder extends RecyclerView.ViewHolder {
private TextView bookName;
private TextView author;
private View container;
public BookViewHolder(View itemView) {
super(itemView);
bookName = (TextView) itemView.findViewById(R.id.book_name);
author = (TextView) itemView.findViewById(R.id.author);
container = itemView.findViewById(R.id.card_view);
}
}
And our adapter class is extended from RecyclerView.Adapter
, we also put BookViewHolder
class as an inner class here:
BookRecyclerViewAdapter.java
And this is layout (xml file) for each grid view item:
package info.devexchanges.staggeredrecyclerview;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class BookRecyclerViewAdapter extends RecyclerView.Adapter {
private List bookList;
private Context context;
public BookRecyclerViewAdapter(Context context, List itemList) {
this.bookList = itemList;
this.context = context;
}
@Override
public BookViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_grid, null, false);
return new BookViewHolder(layoutView);
}
@Override
public void onBindViewHolder(BookViewHolder holder, final int position) {
holder.bookName.setText(bookList.get(position).getName());
holder.author.setText(bookList.get(position).getAuthor());
holder.container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(context, "You clicked at position: " + position, Toast.LENGTH_SHORT).show();
}
});
}
@Override
public int getItemCount() {
return this.bookList.size();
}
public class BookViewHolder extends RecyclerView.ViewHolder {
private TextView bookName;
private TextView author;
private View container;
public BookViewHolder(View itemView) {
super(itemView);
bookName = (TextView) itemView.findViewById(R.id.book_name);
author = (TextView) itemView.findViewById(R.id.author);
container = itemView.findViewById(R.id.card_view);
}
}
}
item_grid.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp"
card_view:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/book_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp" />
<TextView
android:id="@+id/author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="@+id/book_name"
android:background="#1976D2"
android:gravity="center_horizontal"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:text="@string/app_name"
android:textColor="#ffffff"
android:textSize="13sp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
Design staggered grid layout in activity
RecyclerView
always has a LayoutManager
and in order to build a staggered grid view, we must use StaggeredGridLayoutManager
for it.
This is code for our activity:
MainActivity.java
And the activity layout:
package info.devexchanges.staggeredrecyclerview;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private StaggeredGridLayoutManager layoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
List<Book> bookList = getListItemData();
BookRecyclerViewAdapter adapter = new BookRecyclerViewAdapter(MainActivity.this, bookList);
recyclerView.setAdapter(adapter);
}
private List<Book> getListItemData(){
List<Book> listViewItems = new ArrayList<>();
listViewItems.add(new Book("1984", "George Orwell"));
listViewItems.add(new Book("Lão Hạc", "Nam Cao"));
listViewItems.add(new Book("Kafka on the shore", "Haruki Murakami"));
listViewItems.add(new Book("Pride and Prejudice", "Jane Austen"));
listViewItems.add(new Book("Mảnh trăng cuối rừng", "Nguyễn Minh Châu"));
listViewItems.add(new Book("One Hundred Years of Solitude", "Gabriel Garcia Marquez"));
listViewItems.add(new Book("The Book Thief", "Markus Zusak"));
listViewItems.add(new Book("The Hunger Games", "Suzanne Collins"));
listViewItems.add(new Book("Số đỏ", "Vũ Trọng Phụng"));
listViewItems.add(new Book("The Hitchhiker's Guide to the Galaxy", "Douglas Adams"));
listViewItems.add(new Book("The Theory Of Everything", "Dr Stephen Hawking"));
listViewItems.add(new Book("Đàn ghi-ta của Lorca", "Thanh Thảo"));
listViewItems.add(new Book("The Trial", "Franz Kafka"));
return listViewItems;
}
}
activity_main.xml
POJO of the project:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_horizontal_margin">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
</RelativeLayout>
Book.java
package info.devexchanges.staggeredrecyclerview;
public class Book {
private String author;
private String name;
public Book(String bookName, String author) {
this.name = bookName;
this.author = author;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getName() {
return name;
}
}
Running application
When user click at any grid item:
Final thoughts
RecyclerView
. By searching on Internet, you can find out another solutions like customizing GridView
widget or using external libraries. But, you should remember to RecyclerView
as the "official widget" to dealing with this problem. Moreover, you should visit this tag link to read all post about it, source code of this project you can download from @Github.Reference: StaggeredGridLayoutManager in Google developer document.