Autofit grid layout Recyclerview

Android RecyclerView with Autofit GridView

Autofit grid layout Recyclerview

Recycler view is the powerfull android tool to create a list as well as a grid in android. Nowadays, the Autofit grid layout RecyclerView is trending just because different types of screens are in the market.

Everyone is now familiar with the Grid view with the help of GridLayoutManager. But, there is something silly in this layout manager. This layout manager is not working properly on all types of screens.

So now, this example will give you an amazing trick to creating an autofit grid layout RecyclerView.

What is Recyclerview?

RecyclerView is the powerful tool to draw a list or grid in your android application When RecyclerView is not there then the user needs ListView for the list and GridView for the grid, But now android provides a great tool RecyclerView to draw both with one single view. Android RecyclerView is a more advanced, powerful and flexible version of the ListView. Android RecyclerView is similar to ListView.

You can visit this URL to know more about Recyclerview.

What is Cardview?

As with material design, a new view was introduced through the support v7 library, called CardView. We will show you how Android CardView can be implemented in a RecyclerView list. Android CardView provides a more advanced and flexible way of implementing complex and custom listview with more functionality that is required for your apps.

AutoFit Gridview

Autofit Recyclerview is used to show the number of a column which can be auto adjust with screen size. We extend RecyclerView to get access to its width. As for the width of each item, when GridView has android:numColumns="auto_fit", it uses android: column width to compute the number of columns. You can see it in this tutorial.

AutoFitGridRecyclerView

package com.codingissue.legendblogsexample;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

public class AutoFitGridRecyclerView extends RecyclerView {
    private GridLayoutManager manager;
    private int columnWidth = -1;

    public AutoFitGridRecyclerView(Context context) {
        super(context);
        initialization(context, null);
    }

    public AutoFitGridRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialization(context, attrs);
    }

    public AutoFitGridRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initialization(context, attrs);
    }

    private void initialization(Context context, AttributeSet attrs) {
        try{
            if (attrs != null) {
                // list the attributes we want to fetch
                int[] attrsArray = {
                        android.R.attr.columnWidth
                };
                TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
                //retrieve the value of the 0 index, which is columnWidth
                columnWidth = array.getDimensionPixelSize(0, -1);
                array.recycle();
            }
            manager = new GridLayoutManager(context, 1);
            setLayoutManager(manager);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected void onMeasure(int widthSpec, int heightSpec) {
       super.onMeasure(widthSpec, heightSpec);
       try{
           if (columnWidth > 0) {
               //The spanCount will always be at least 1
               int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
               manager.setSpanCount(spanCount);
           }
       }catch (Exception e){
           e.printStackTrace();
       }
    }
}

In the constructor, we read the value of android: column width and save it in a member variable.

Gradle dependency

All these basics dependency needs to add in the Gradle file to implement this project.

implementation 'androidx.appcompat:appcompat:1.1.0' 
implementation 'androidx.recyclerview:recyclerview:1.0.0' 
implementation 'androidx.cardview:cardview:1.0.0'

Activity Main XML

The main layout file will be like this.

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".ScrollingActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            android:background="@drawable/legend_blogs"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:toolbarId="@+id/toolbar">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <include layout="@layout/content_scrolling" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|end"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

AutoFit Grid RecyclerView with content scrolling XML

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".ScrollingActivity"
    tools:showIn="@layout/activity_scrolling">

    <com.codingissue.legendblogsexample.AutoFitGridRecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:columnWidth="180dp"
        android:listSelector="@android:color/transparent"
        android:numColumns="auto_fit"
        android:padding="5dp"/>

</RelativeLayout>

Adapter layout

To achieve your grid layout you can make your own style like this layout.

<?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="wrap_content"
    android:orientation="vertical"
    android:tag="cards main container">

    <androidx.cardview.widget.CardView
        xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        card_view:cardCornerRadius="5dp"
        card_view:cardElevation="10dp"
        card_view:cardUseCompatPadding="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/imageView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:src="@drawable/legend_blogs"
                android:adjustViewBounds="true"/>

            <TextView
                android:id="@+id/text_title"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:textStyle="bold"
                android:textSize="14dp"
                android:typeface="sans"
                android:paddingLeft="10dp"
                android:paddingTop="5dp"
                android:paddingRight="10dp"
                android:paddingBottom="5dp" />

            <TextView
                android:id="@+id/text_desc"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:visibility="gone"
                android:paddingBottom="5dp"
                android:typeface="sans" />

        </LinearLayout>

    </androidx.cardview.widget.CardView>

</LinearLayout>

Dataset for your list

 

package com.codingissue.legendblogsexample;

public class DataSet {

    static String[] image_Array = {
            "https://www.legendblogs.com/images/products/121805_1569483661_facebook-legebd-blogs.jpg",
            "https://www.legendblogs.com/images/products/121804_1569221499_Drawer-layout-legend-blogs.jpg",
            "https://www.legendblogs.com/images/products/121799_1562829904_top-10-wordpress-plugins.jpg",
            "https://www.legendblogs.com/images/products/121803_1567671000_in-app-update.jpg",
            "https://www.legendblogs.com/images/products/121792_1548062499_expandable-list-view-in-android-legend-blogs.jpg",
            "https://www.legendblogs.com/images/products/121787_1545997899_encryption-decryption-legendblogs.jpg",
            "https://www.legendblogs.com/images/products/121786_1545916320_android-pie-glide-issue-legend-blogs.jpg",
            "https://www.legendblogs.com/images/products/121784_1545472277_prrfix-suffix-legend-blogs.jpg",
            "https://www.legendblogs.com/images/products/121782_1544702823_background-image-from-gallery-legend-blogs.jpg",
            "https://www.legendblogs.com/images/products/121805_1569483661_facebook-legebd-blogs.jpg",
            "https://www.legendblogs.com/images/products/121804_1569221499_Drawer-layout-legend-blogs.jpg",
            "https://www.legendblogs.com/images/products/121799_1562829904_top-10-wordpress-plugins.jpg",
            "https://www.legendblogs.com/images/products/121803_1567671000_in-app-update.jpg",
            "https://www.legendblogs.com/images/products/121792_1548062499_expandable-list-view-in-android-legend-blogs.jpg",
            "https://www.legendblogs.com/images/products/121787_1545997899_encryption-decryption-legendblogs.jpg",
            "https://www.legendblogs.com/images/products/121786_1545916320_android-pie-glide-issue-legend-blogs.jpg",
            "https://www.legendblogs.com/images/products/121784_1545472277_prrfix-suffix-legend-blogs.jpg",
            "https://www.legendblogs.com/images/products/121782_1544702823_background-image-from-gallery-legend-blogs.jpg"
    };
    static String[] title_Array = {
            "Login with Facebook using PHP",
            "Navigation drawer layout with an event listener",
            "Top 10 free WordPress plugins for bloggers",
            "In apps update android example without play store",
            "Expandable list view in android example",
            "How do you Encrypt and Decrypt a PHP String",
            "Solution for Glide failed to load image in android pie 9.0",
            "How to find prefix and suffix of the word in javascript",
            "Set background image randomly from gallery in android",
            "Login with Facebook using PHP",
            "Navigation drawer layout with an event listener",
            "Top 10 free WordPress plugins for bloggers",
            "In apps update android example without play store",
            "Expandable list view in android example",
            "How do you Encrypt and Decrypt a PHP String",
            "Solution for Glide failed to load image in android pie 9.0",
            "How to find prefix and suffix of the word in javascript",
            "Set background image randomly from gallery in android"
    };
    static String[] desc_Array = {
            "Hmm, If your website has a customer base section or any kind of customer interaction activity, then you must need to add login with Facebook.",
            "Hey App creator, today I am going to discuss Drawer Layout. Means, you will get knowledge about how to add drawer layout with an event listener",
            "According to me, you have just created a new WordPress blog and wondering what are the best WordPress plugins you should need to install?",
            "If you want to update your app from internal storage then In apps update android example for you. You can update your app automatically without",
            "This is a wonderful example to show you, how to create an expandable list view in android. I have learnt already in the previous article,",
            "What is Mcrypt in PHP? Mcrypt is a replacement for the popular Unix crypt command. the crypt was a file encryption tool that used an algorithm",
            "Hello, I have seen that in the Android latest version 28.0 or I can say in Android Pie 9.0 when",
            "First of all, you have to know that how to get the currently selected text on the page by using the JavaScript. So, Javascript provided.",
            "I think you want to show the background image in your open activity view. But you want to show this one from your gallery and it should be selected",
            "Hmm, If your website has a customer base section or any kind of customer interaction activity, then you must need to add login with Facebook.",
            "Hey App creator, today I am going to discuss Drawer Layout. Means, you will get knowledge about how to add drawer layout with an event listener",
            "According to me, you have just created a new WordPress blog and wondering what are the best WordPress plugins you should need to install?",
            "If you want to update your app from internal storage then In apps update android example for you. You can update your app automatically without",
            "This is a wonderful example to show you, how to create an expandable list view in android. I have learnt already in the previous article,",
            "What is Mcrypt in PHP? Mcrypt is a replacement for the popular Unix crypt command. the crypt was a file encryption tool that used an algorithm",
            "Hello, I have seen that in the Android latest version 28.0 or I can say in Android Pie 9.0 when",
            "First of all, you have to know that how to get the currently selected text on the page by using the JavaScript. So, Javascript provided.",
            "I think you want to show the background image in your open activity view. But you want to show this one from your gallery and it should be selected"
    };
}

Data Model

 

package com.codingissue.legendblogsexample;

public class DataModel {


    private String image;
    private String title;
    private String desc;

    public DataModel(String image, String title, String desc) {

        this.image = image;
        this.title = title;
        this.desc = desc;
    }

    public String getImage() {
        return image;
    }

    public String getTitle() {
        return title;
    }

    public String getDesc() {
        return desc;
    }
}

Adapter for view

 

package com.codingissue.legendblogsexample;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;

import java.util.ArrayList;


public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> {

    private Context context;
    private ArrayList<DataModel> dataModel;

    public static class MyViewHolder extends RecyclerView.ViewHolder {

        ImageView imageView;
        TextView text_title;
        TextView text_desc;

        public MyViewHolder(View view) {
            super(view);
            this.imageView = (ImageView) view.findViewById(R.id.imageView);
            this.text_title = (TextView) view.findViewById(R.id.text_title);
            this.text_desc = (TextView) view.findViewById(R.id.text_desc);
        }
    }

    public CustomAdapter(Context _context, ArrayList<DataModel> data) {
        this.context = _context;
        this.dataModel = data;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent,
                                           int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.cards_layout, parent, false);

        // view.setOnClickListener(MainActivity.myOnClickListener);

        MyViewHolder myViewHolder = new MyViewHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {

        TextView text_title = holder.text_title;
        TextView text_desc = holder.text_desc;

        Glide.with(context)
                .load(dataModel.get(position).getImage())
                .placeholder(R.drawable.legend_blogs)
                .into(holder.imageView);

        text_title.setText(dataModel.get(position).getTitle());
        text_desc.setText(dataModel.get(position).getDesc());
    }

    @Override
    public int getItemCount() {
        return dataModel.size();
    }
}

Main Activity

 

package com.codingissue.legendblogsexample;

import android.content.Context;
import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;

import android.view.View;
import android.view.Menu;
import android.view.MenuItem;

import java.util.ArrayList;

public class ScrollingActivity extends AppCompatActivity {

    private static Context context;
    private static CustomAdapter adapter;
    private static RecyclerView recyclerView;
    private static ArrayList<DataModel> data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scrolling);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        context = this;

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        recyclerView.setHasFixedSize(true);
        recyclerView.setItemAnimator(new DefaultItemAnimator());

        data = new ArrayList<DataModel>();
        for (int i = 0; i < DataSet.title_Array.length; i++) {
            data.add(new DataModel(
                    DataSet.image_Array[i],
                    DataSet.title_Array[i],
                    DataSet.desc_Array[i]
            ));
        }

        adapter = new CustomAdapter(context, data);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_scrolling, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Conclusion

Finally, in conclusion, I can say that we can create an autofit grid layout with the help of RecyclerView. Hope that this code will help you to create your list as well as a grid for all type of screens either landscape mode or portrait mode.

Sanjay made a post.
26 day ago

Thank you so much for this example. I am facing such a problem with the autofit grid layout recyclerview. Thank you once again.

Top