Now you can Subscribe using RSS

Submit your Email

Sunday

StaggeredGridLayoutManager with RecyclerView in Android - Tutorial | Pinterest like UI

Vishal Shrestha
We have previously seen how we can create Grids in RecyclerView using GridLayoutManager. You can check out that tutorial/example here: GridLayoutManager with RecyclerView.
In this tutorial we will learn how we can use the StaggeredGridLayoutManager with RecyclerView in Android to create Grids of unequal size.

Staggered-Grid-Layout-in-RecyclerView
Staggered Grid Layout in Pinterest


We are trying to achieve a layout design like Pinterest which you might be familiar with. By using the StaggeredGridLayoutManager with RecyclerView in Android, we can easily achieve the desired layout. Our RecyclerView will look like this at the end:

Here are the prerequisites for successfully creating the app described in this tutorial:
0. An internet connection. Duh! :D
1. Android Studio, get it here:
Android Developer website.


We will go over the following things in this tutorial:


1. Set up Gradle Dependencies for using RecyclerView and CardView.

2. Create an Activity Layout with RecyclerView as a ChildView.

3. Create a Layout that will be used as a Grid in the RecyclerView.

4. Create an Activity class where we will have majority of our code.

5. Create and Adapter and ViewHolder for our RecyclerView.

6. Select the Images to show in the Grids of RecyclerView.

7. Set up the RecyclerView.

Okay, so lets begin with creating the Staggered Grids in RecyclerView. You can also check out the video tutorial:

1. Set Up Gradle Dependencies


First thing that we need to do is to set up dependencies. This allows us to use RecylerView. If we don't use this dependency then we won't be able to use RecyclerView. Open your App level Gradle file(build.gradle(Module: app)), it is inside the App folder in Project view of Android Studio and listed inside Gradle Scripts in Android View. Include the dependencies to use CardView and RecyclerView, copy the following lines inside the dependencies section:

compile 'com.android.support:recyclerview-v7:26.+'
compile 'com.android.support:cardview-v7:26+'

You can check out the latest versions of support library packages here: Support Library Packages

2. Create a Layout with RecyclerView

For this tutorial, we will name this file: activity_staggered_view.xml. The layout is very simple, we will create a LinearLayout as Root layout and then have a RecyclerView inside it. Here's the code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rvMain"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

3. Create a Layout to be used as a Grid

Now that we have created our layout, we well create the layout out of a single grid. The Grids in out RecyclerView will look like how we define it now. For this project, we will create a simple layout with an ImageView at the top and textView below it. We will just show pictures with captions below them as the grids in our layout. The layout is very simple and self explanatory, here's the code:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="4dp"
    app:cardUseCompatPadding="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/ivImage"
            android:scaleType="fitXY"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/tvCaption"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</android.support.v7.widget.CardView>


We've used cardView as the root because we want our images and text inside curved cards similar to that of Pinterest layout. The parameters cardCornerRadius is used to define how much we want our cards to be rounded at the corners. CardUseCompatPadding defines is for the backward compatibility for deviecs lower than Lollipop.
In the LinearLayout we have defined orientation to be vertical. In the ImageView, we have ScaleType set to FitXY in the ImageView as it allows the image stretch and occupy all the available space. Finally, we have a TextView below the ImageView. We will display the caption in this TextView.

4. Create a Java Class to handle RecyclerView.

This is the class where we make it all work. Lets name the java class ActivityStaggered and in the onCreate set the content view to our activity_staggered_view.xml and create reference to the RecyclerView. Here what the code in ActivityStaggered method upto now:

RecyclerView recyclerView;

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_staggered_view);

        recyclerView = (RecyclerView) findViewById(R.id.rvMain);
    }


In the next steps we will an Adapter and ViewHolder for the RecyclerView that defines what to display in the RecyclerView.

5. Create a RecyclerView Adapter and ViewHolder.

Create a nested class called GridHolder. It should extend RecyclerView.ViewHolder. Create a default constructor and create references to ImageView and Text that will be populated as the Grid or our RecyclerView. Here's the code for GridHolder Class:

private class GridHolder extends RecyclerView.ViewHolder {

        ImageView imageView;
        TextView textView;

        public GridHolder(View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.ivImage);
            textView = itemView.findViewById(R.id.tvCaption);
        }
    }


Now, let us create the Adapter for our RecyclerView. The Job of adapter is to create and bind data to view that correspond to each item in our Data-set.
Create a nested class again. I've called it GridLayoutAdapter. It should extend RecycerView.Adapter.
Here's what the Adapter Class look like at the moment:

private class GridLayoutAdapter extends RecyclerView.Adapter<GridHolder> {

        @Override
        public GridHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return null;
        }

        @Override
        public void onBindViewHolder(GridHolder holder, int position) {
        }

        @Override
        public int getItemCount() {
            return 0;
        }
    }
    }

This is not doing anything at the moment, to this adapter we need to pass the data that we will be displaying in the Grids of our RecyclerView. We will just show Images and then display the item count as the caption. So create a bitmap array and a constructor. We will populate the Bitmap array in the constructor. Include the following inside the GridLayoutAdapter:

  Bitmap[] bitmaps;

        public GridLayoutAdapter(Bitmap[] bitmaps) {
            this.bitmaps = bitmaps;
        } 


Now, we need to display the layout that we had created with CardView and TextView in Step 3 as the Grid of the recyclerView. We do it inside the onCreateViewHolder method of the Adatper. Here's the updated onCreateViewHolder method.

@Override
        public GridHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(ActivityStaggered.this).inflate(R.layout.staggered_row, parent, false);
            return new GridHolder(view);
        }

Finally, we will need to figure out what data to display in which Grid. This is the Data Binding part. It is done inside the onBindView Holder method. The GirdHolder and current position is passed as the parameter to this method. We will set the ImageView and TextView of the holder in this method. Here's the updated Code:

 @Override
        public void onBindViewHolder(GridHolder holder, int position) {
            holder.imageView.requestLayout();
            holder.imageView.setImageBitmap(bitmaps[position]);
            holder.textView.setText("Caption: " + position);
        }
Finally, we have the getItemCount method, it return the number of items to be displayed in the RecyclerView. In our case it's bitmaps.length. Here's the updated of getItemCount:

@Override
        public int getItemCount() {
            return bitmaps.length;
        }

6. Setting up the Images we need to display.

We are almost done now! we just need the images we need to display and set the adapter to recyclerView. In the drawable folders inside res folder, I have added some images that will be displayed in the Grids of RecyclerView. Let's create a method called setUpBitmaps() that return an array of Bitmaps.

private Bitmap[] setUpBitmaps() {
        Bitmap[] bitmaps = new Bitmap[10];
        bitmaps[0] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_1);
        bitmaps[1] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_2);
        bitmaps[2] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_3);
        bitmaps[3] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_4);
        bitmaps[4] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_5);
        bitmaps[5] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_6);
        bitmaps[6] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_7);
        bitmaps[7] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_8);
        bitmaps[8] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_9);
        bitmaps[9] = BitmapFactory.decodeResource(getResources(), R.drawable.icon_10);
        return bitmaps;
    }

Now we have everything we need, The RecyclerView, The ViewHolder, The Adapter and The Data that needs to be display. On to the next step!

7. Setting Adapter to RecyclerView.

We are one step from our StaggeredView in RecyclerView. We just need to put everything that we have coded together. First or all, In our onCreate we will call the setUpBitmaps method that we had just created in the previous step. Then we need to set the StaggeredLayoutManager to RecyclerView. Then finally create the Instance of our GridLayoutAdapter and the bitmaps to Adapter and Set the adapter to our RecyclerView. Here's the updated onCreate method:

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_staggered_view);

        recyclerView = (RecyclerView) findViewById(R.id.rvMain);

        Bitmap[] bitmaps = setUpBitmaps();
        recyclerView.setAdapter(new GridLayoutAdapter(bitmaps));
        StaggeredGridLayoutManager mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(mLayoutManager);
    }


We are now done, just add the Activity to Manager and set it's category as launcher. Include the following code inside the application tags:
 <activity android:name=".ActivityStaggered">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

We are now done. You can build and run the project and you will see a Staggered Grid Layout, just like pinterest. Enjoy! Drop any question you have in the comment section below. Happy Coding.

Vishal Shrestha / Author & Founder

A developer by profession, a born Adventurer. I mainly do Android but like to get my hands dirty with web development and a little bit of Python. I would't rather go on a Trek than a party and you can find me having a few rounds with the heavy bag to let out the steam ;)

For Business info : My Portfolio Site.

0 comments:

Post a Comment

Coprights @ 2017 | The Code City by Vishal Shrestha Vishal Shrestha