Hi all, Today we are going to learn how to make Sectioned RecyclerView which you have seen in PlayStore App. To know about RecyclerView and basic implementations you can see my previous articles on it.
To make Sectioned RecyclerView we are going to need a RecyclerView nested into another RecyclerView.
1. Create a new project in Android Studio by navigating to File ⇒ New Android ⇒ Application Project and fill required details. By default my activity is MainActivity.java.
2. Open res ⇒ values ⇒ strings.xml and add below string values. These are some strings that we are going to use in our project.
1 2 3 4 5 6 7 |
<resources> <string name="app_name">Sectioned RecyclerView Demo</string> <string name="linear_sectioned_recyclerview_vertical">Linear Sectioned RecyclerView (Vertical)</string> <string name="linear_sectioned_recyclerview_horizontal">Linear Sectioned RecyclerView (Horizontal)</string> <string name="grid_sectioned_recyclerview">Grid Sectioned RecyclerView</string> <string name="show_all">Show All</string> </resources> |
3. Now go to activity_main.xml and add the below code to it. In this layout we are using three Button to show different types of Sectioned RecyclerView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" android:gravity="center" android:orientation="vertical" android:padding="15dp" tools:context="com.sectionedrecyclerviewdemo.MainActivity"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:background="@color/colorPrimary" android:onClick="linearSectionedRecyclerViewVertical" android:text="@string/linear_sectioned_recyclerview_vertical" android:textColor="@android:color/white" android:textSize="14sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:background="@color/colorPrimary" android:padding="10dp" android:onClick="linearSectionedRecyclerViewHorizontal" android:text="@string/linear_sectioned_recyclerview_horizontal" android:textColor="@android:color/white" android:textSize="14sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:layout_marginTop="10dp" android:background="@color/colorPrimary" android:onClick="gridSectionedRecyclerView" android:text="@string/grid_sectioned_recyclerview" android:textColor="@android:color/white" android:textSize="14sp" /> </LinearLayout> |
4. After adding three Button lets implement click event on them and open RecyclerViewActivity.java on Button click. For this add the below code to your MainActivity.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package com.sectionedrecyclerviewdemo; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void linearSectionedRecyclerViewVertical(View view) { startRecyclerViewActivity(RecyclerViewType.LINEAR_VERTICAL); } public void linearSectionedRecyclerViewHorizontal(View view) { startRecyclerViewActivity(RecyclerViewType.LINEAR_HORIZONTAL); } public void gridSectionedRecyclerView(View view) { startRecyclerViewActivity(RecyclerViewType.GRID); } /** * method to start RecyclerViewActivity * * @param recyclerViewType enum type to show recyclerview on basis if button call */ private void startRecyclerViewActivity(RecyclerViewType recyclerViewType) { Bundle bundle = new Bundle(); bundle.putSerializable(RecyclerViewActivity.RECYCLER_VIEW_TYPE, recyclerViewType); startActivity(new Intent(this, RecyclerViewActivity.class).putExtras(bundle)); } } |
5. For RecyclerViewActivity.java create new xml layout naming recycler_view_activity.xml and add RecyclerView to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?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:background="@android:color/white" android:padding="10dp"> <android.support.v7.widget.RecyclerView android:id="@+id/sectioned_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> |
6. After creating recycler_view_activity.xml create RecyclerViewActivity.java class and put the below code to it. In this class we are populating RecyclerView with Sections and Items using SectionModel.java pojo class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
package com.sectionedrecyclerviewdemo; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.MenuItem; import java.util.ArrayList; /** * Created by sonu on 24/07/17. */ public class RecyclerViewActivity extends AppCompatActivity { protected static final String RECYCLER_VIEW_TYPE = "recycler_view_type"; private RecyclerViewType recyclerViewType; private RecyclerView recyclerView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.recycler_view_activity); //get enum type passed from MainActivity recyclerViewType = (RecyclerViewType) getIntent().getSerializableExtra(RECYCLER_VIEW_TYPE); setUpToolbarTitle(); setUpRecyclerView(); populateRecyclerView(); } //set toolbar title and set back button private void setUpToolbarTitle() { getSupportActionBar().setDisplayHomeAsUpEnabled(true); switch (recyclerViewType) { case LINEAR_HORIZONTAL: getSupportActionBar().setTitle(getResources().getString(R.string.linear_sectioned_recyclerview_horizontal)); break; case LINEAR_VERTICAL: getSupportActionBar().setTitle(getResources().getString(R.string.linear_sectioned_recyclerview_vertical)); break; case GRID: getSupportActionBar().setTitle(getResources().getString(R.string.grid_sectioned_recyclerview)); break; } } //setup recycler view private void setUpRecyclerView() { recyclerView = (RecyclerView) findViewById(R.id.sectioned_recycler_view); recyclerView.setHasFixedSize(true); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(linearLayoutManager); } //populate recycler view private void populateRecyclerView() { ArrayList<SectionModel> sectionModelArrayList = new ArrayList<>(); //for loop for sections for (int i = 1; i <= 5; i++) { ArrayList<String> itemArrayList = new ArrayList<>(); //for loop for items for (int j = 1; j <= 10; j++) { itemArrayList.add("Item " + j); } //add the section and items to array list sectionModelArrayList.add(new SectionModel("Section " + i, itemArrayList)); } SectionRecyclerViewAdapter adapter = new SectionRecyclerViewAdapter(this, recyclerViewType, sectionModelArrayList); recyclerView.setAdapter(adapter); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); break; } return super.onOptionsItemSelected(item); } } |
7. To identify the type of Sectioned RecyclerView we will create an ENUM java class naming RecyclerViewType.java and add the three enums to it.
1 2 3 4 5 6 7 8 9 |
package com.sectionedrecyclerviewdemo; /** * Created by sonu on 24/07/17. */ public enum RecyclerViewType { LINEAR_VERTICAL,LINEAR_HORIZONTAL,GRID; } |
8. Now create pojo class naming SectionModel.java for RecyclerView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.sectionedrecyclerviewdemo; import java.util.ArrayList; /** * Created by sonu on 24/07/17. */ public class SectionModel { private String sectionLabel; private ArrayList<String> itemArrayList; public SectionModel(String sectionLabel, ArrayList<String> itemArrayList) { this.sectionLabel = sectionLabel; this.itemArrayList = itemArrayList; } public String getSectionLabel() { return sectionLabel; } public ArrayList<String> getItemArrayList() { return itemArrayList; } } |
9. Now lets create adapter class for RecyclerView naming SectionRecyclerViewAdapter.java and put the below code to it. In this class we are setting different LayoutManager on basis of enum type inside onBindViewHolder method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
package com.sectionedrecyclerviewdemo; import android.content.Context; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; 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.ArrayList; /** * Created by sonu on 24/07/17. */ public class SectionRecyclerViewAdapter extends RecyclerView.Adapter<SectionRecyclerViewAdapter.SectionViewHolder> { class SectionViewHolder extends RecyclerView.ViewHolder { private TextView sectionLabel, showAllButton; private RecyclerView itemRecyclerView; public SectionViewHolder(View itemView) { super(itemView); sectionLabel = (TextView) itemView.findViewById(R.id.section_label); showAllButton = (TextView) itemView.findViewById(R.id.section_show_all_button); itemRecyclerView = (RecyclerView) itemView.findViewById(R.id.item_recycler_view); } } private Context context; private RecyclerViewType recyclerViewType; private ArrayList<SectionModel> sectionModelArrayList; public SectionRecyclerViewAdapter(Context context, RecyclerViewType recyclerViewType, ArrayList<SectionModel> sectionModelArrayList) { this.context = context; this.recyclerViewType = recyclerViewType; this.sectionModelArrayList = sectionModelArrayList; } @Override public SectionViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.section_custom_row_layout, parent, false); return new SectionViewHolder(view); } @Override public void onBindViewHolder(SectionViewHolder holder, int position) { final SectionModel sectionModel = sectionModelArrayList.get(position); holder.sectionLabel.setText(sectionModel.getSectionLabel()); //recycler view for items holder.itemRecyclerView.setHasFixedSize(true); holder.itemRecyclerView.setNestedScrollingEnabled(false); /* set layout manager on basis of recyclerview enum type */ switch (recyclerViewType) { case LINEAR_VERTICAL: LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false); holder.itemRecyclerView.setLayoutManager(linearLayoutManager); break; case LINEAR_HORIZONTAL: LinearLayoutManager linearLayoutManager1 = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false); holder.itemRecyclerView.setLayoutManager(linearLayoutManager1); break; case GRID: GridLayoutManager gridLayoutManager = new GridLayoutManager(context, 3); holder.itemRecyclerView.setLayoutManager(gridLayoutManager); break; } ItemRecyclerViewAdapter adapter = new ItemRecyclerViewAdapter(context, sectionModel.getItemArrayList()); holder.itemRecyclerView.setAdapter(adapter); //show toast on click of show all button holder.showAllButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context, "You clicked on Show All of : " + sectionModel.getSectionLabel(), Toast.LENGTH_SHORT).show(); } }); } @Override public int getItemCount() { return sectionModelArrayList.size(); } } |
10. For RecyclerView sections we are going to create xml layout naming section_custom_row_layout.xml. This layout contains one section label, one show all button and one RecyclerView for displaying Section Items.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?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="wrap_content" android:orientation="vertical" android:padding="5dp"> <TextView android:id="@+id/section_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/section_show_all_button" android:layout_alignParentLeft="true" android:textColor="@android:color/darker_gray" android:textSize="14sp" /> <TextView android:id="@+id/section_show_all_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:background="@color/colorPrimary" android:paddingBottom="8dp" android:paddingLeft="15dp" android:paddingRight="15dp" android:paddingTop="8dp" android:text="@string/show_all" android:textAllCaps="true" android:textColor="@android:color/white" android:textSize="12sp" /> <!-- recycler view for items --> <android.support.v7.widget.RecyclerView android:id="@+id/item_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/section_show_all_button" android:layout_marginTop="7dp" /> </RelativeLayout> |
11. To display section items we need to create one more adapter for Items naming ItemRecyclerViewAdapter.java and put the below code to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
package com.sectionedrecyclerviewdemo; 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 java.util.ArrayList; /** * Created by sonu on 24/07/17. */ public class ItemRecyclerViewAdapter extends RecyclerView.Adapter<ItemRecyclerViewAdapter.ItemViewHolder> { class ItemViewHolder extends RecyclerView.ViewHolder { private TextView itemLabel; public ItemViewHolder(View itemView) { super(itemView); itemLabel = (TextView) itemView.findViewById(R.id.item_label); } } private Context context; private ArrayList<String> arrayList; public ItemRecyclerViewAdapter(Context context, ArrayList<String> arrayList) { this.context = context; this.arrayList = arrayList; } @Override public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_custom_row_layout, parent, false); return new ItemViewHolder(view); } @Override public void onBindViewHolder(ItemViewHolder holder, int position) { holder.itemLabel.setText(arrayList.get(position)); } @Override public int getItemCount() { return arrayList.size(); } } |
12. For items adapter we need to create an xml layout naming item_custom_row_layout.xml. In this layout we are taking a CardView with ImageView and TextView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?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" android:layout_marginBottom="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" app:cardBackgroundColor="@android:color/white" app:cardCornerRadius="4dp" app:cardElevation="5dp" app:contentPadding="10dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="vertical"> <ImageView android:layout_width="wrap_content" android:layout_height="50dp" android:src="@mipmap/ic_launcher_round" /> <TextView android:id="@+id/item_label" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:paddingTop="5dp" android:textColor="@android:color/black" android:textSize="15sp" /> </LinearLayout> </android.support.v7.widget.CardView> |
13. Finally all done, now you can also make Sectioned RecyclerView.
Thanks.
Subscribe to us and get the latest news.
18 Comments
Htoo Aung Hlaing
Thursday, February 8th, 2018When I test with inner recyclerview item with 20, scroll not work well.Try to test and change inner recyclerview with many items
Dr. Droid
Thursday, February 8th, 2018Hi Htoo Aung Hlaing,
Do one thing use below code for both RecyclerView :
recyclerView.setNestedScrollingEnabled(false);
Use this with both recyclerview and check.
Thanks
Pedro
Friday, February 23rd, 2018notifydatasetchanged does not work in this example, how can i make it work?
Thanks
Dr. Droid
Wednesday, February 28th, 2018Hi Pedro
Can you tell me what code you are using to notify adapter?
Thanks
snomen
Saturday, May 19th, 2018How can I update a single row in the sectioned recycler view?
Dr. Droid
Saturday, May 19th, 2018Hi Snomen,
To update single row item in Sectioned Recycler View you need to update that item pojo class and after that you have to notify its adapter.
Thanks
snomen
Sunday, May 20th, 2018From ItemRecyclerViewAdapter, on clicking a row I’m starting a new Activity. After putting in few values in the activity I’m passing an object back to RecyclerViewActivity in onActivityResult()
if (resultCode == RESULT_OK) {
Person person = data.getParcelableExtra(“person”);
}
How can I pass this object so that only the clicked row is updated?
Shrikant
Wednesday, July 18th, 2018Nice tutorial.. Keep it up bud 🙂
Amila
Tuesday, December 11th, 2018i put this code into tab view fragment.then some time stuck the tab pane on load this.
Dr. Droid
Wednesday, December 12th, 2018Hi Amila,
Are you doing any kind of api calls there?
Thanks
Amila
Thursday, December 13th, 2018Hi Droid,
no any api calling. just loading in CARD view layout.
Mohsen
Monday, March 4th, 2019It was very helpful for me
Thanks
shyam
Thursday, March 21st, 2019Hi,thank you for this superb tutorial.
But in my implemenation,i am getting only one child in my sections.
The other childs are not visible.
So Please help me
Dr. Droid
Saturday, March 23rd, 2019Hi Shyam,
Can you check your child width and height are wrap_content or not?
And also put logs to check size of the child array.
Thanks
Laxmikant
Saturday, July 20th, 2019Is is possible to achieve this without using the second RecyclerView?
Dr. Droid
Monday, July 22nd, 2019Hi Laxmikant,
Yes you can do it.
Thanks
Viral gohil
Thursday, March 19th, 2020how to load json data on sectioned Recyclerview using volley library
Rus
Monday, October 5th, 2020any idea how can i change the image from gallery on one item ?