This is a simple tutorial to develop a scrolling horizontal RecyclerView inside a vertical RecyclerView in Android.
First, we will create the main layout that shows the vertical RecyclerView:
courses_fragment.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:paddingLeft="15dp" android:paddingRight="15dp"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id=“@+id/vertical_courses_list" android:visibility="gone"/> </RelativeLayout>
It’s a simple relative layout with a RecyclerView in it.
Now let’s create the layout for each item of the vertical RecyclerView:
courses_item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="15dp" android:layout_marginBottom="15dp"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_alignParentLeft="true" android:layout_centerVertical="true"> <TextView android:id="@+id/course_item_name_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/RegularTextStyle"/> <android.support.v7.widget.RecyclerView android:id="@+id/horizontal_list" android:layout_width="match_parent" android:layout_marginTop="5dp" android:layout_height="30dp" android:visibility="visible"/> </LinearLayout> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:src="@drawable/ic_play_circle_outline_white_24dp" android:tint="@color/colorAccent"/> </RelativeLayout>
We’ve made a Relative layout with a TextView that displays a Name, an Arrow to the right, and an inside RecyclerView below the Name.
Note: it is important that the inner RecyclerView has layout_height assigned, it won’t work with match_parent or wrap_content.
The same way we created a layout for each item of the main RecyclerView, we will have to create a new layout for each item of the inner horizontal RecyclerView:
courses_horizontal_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginRight="3dp"> <TextView android:id="@+id/horizontal_item_text" android:textColor="@color/white" android:layout_width="match_parent" android:padding="5dp" android:layout_height="wrap_content" android:gravity="center_vertical"/> </LinearLayout>
Good! We are done with xml files. Now we have to create the adapters for each RecyclerView. Let’s start with inner Horizontal RecyclerView adapter:
HorizontalRVAdapter
public class HorizontalRVAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<String> mDataList; private int mRowIndex = -1; public HorizontalRVAdapter() { } public void setData(List<String> data) { if (mDataList != data) { mDataList = data; notifyDataSetChanged(); } } public void setRowIndex(int index) { mRowIndex = index; } private class ItemViewHolder extends RecyclerView.ViewHolder { private TextView text; public ItemViewHolder(View itemView) { super(itemView); text = (TextView) itemView.findViewById(R.id.horizontal_item_text); } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Context context = parent.getContext(); View itemView = LayoutInflater.from(context).inflate(R.layout.courses_horizontal_item, parent, false); ItemViewHolder holder = new ItemViewHolder(itemView); return holder; } @Override public void onBindViewHolder(RecyclerView.ViewHolder rawHolder, int position) { ItemViewHolder holder = (ItemViewHolder) rawHolder; holder.text.setText(mDataList.get(position)); holder.itemView.setTag(position); } @Override public int getItemCount() { return mDataList.size(); } }
Here we inflate the layout for each item of the horizontal RecyclerView and set data to each view. In this case we only have a TextView which is filled with a String from List<String>, but views and lists can be customized and be more complex according to each need.
Now let’s wrap it all together in the main RecyclerView adapter:
CourseRVAdapter
public class CourseRVAdapter extends RecyclerView.Adapter<CourseRVAdapter.SimpleViewHolder> { private final Context mContext; private static List<Nugget> mData; private static RecyclerView horizontalList; public static class SimpleViewHolder extends RecyclerView.ViewHolder { public final TextView title; private HorizontalRVAdapter horizontalAdapter; public SimpleViewHolder(View view) { super(view); Context context = itemView.getContext(); title = (TextView) view.findViewById(R.id.course_item_name_tv); horizontalList = (RecyclerView) itemView.findViewById(R.id.horizontal_list); horizontalList.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)); horizontalAdapter = new HorizontalRVAdapter(); horizontalList.setAdapter(horizontalAdapter); } } public CourseRVAdapter(Context context, List<Nugget> data) { mContext = context; if (data != null) mData = new ArrayList<>(data); else mData = new ArrayList<>(); } public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final View view = LayoutInflater.from(mContext).inflate(R.layout.courses_item, parent, false); return new SimpleViewHolder(view); } @Override public void onBindViewHolder(SimpleViewHolder holder, final int position) { holder.title.setText(mData.get(position).getTitle()); holder.horizontalAdapter.setData(mData.get(position).getTags()); // List of Strings holder.horizontalAdapter.setRowIndex(position); } @Override public int getItemCount() { return mData.size(); } }
And finally, we set the main RecyclerView adapter in our Activity/Fragment:
private CourseRVAdapter adapter; … // Setting RecyclerView coursesRecyclerView.setHasFixedSize(true); LinearLayoutManager llm = new LinearLayoutManager(getActivity()); coursesRecyclerView.setLayoutManager(llm); // nuggetsList is an ArrayList of Custom Objects, in this case Nugget.class adapter = new CourseRVAdapter(getActivity(), nuggetsList); coursesRecyclerView.setAdapter(adapter);
Thank you so much. Works perfectly for me.
And for inner recycler view wrap_content and match_parent works good too!
LikeLike
hello rishabh,can u please send me the whole code as when i run this am getting blank screen as output
LikeLike
Thanks for share.
I use wrap_content for inner RecyclerView, it works too.
LikeLike
can you share the whole code
LikeLike
hi…can u share total code…i didnt get inner view…
LikeLike
hi…can u share total code…i didnt get inner view…
LikeLike
Thank for this post this will very helpful for me. You save my time.
LikeLike
Thank you so much for your example. It helps a lot. I am using it to show the details of a long list of weather stations. Unfortunately after some scrolling the list starts to show wrong entries. I was debugging my data until it arrives in my inner Recyclerview and found no errors. My guess is that a recycler view within a recycler view somehow leaks data. Have you had such problems and found a way to deal with it?
Ben
LikeLike
Thank you so much!!
LikeLike
hi,nize solution,can you sent compleat project code ??
ashikazeez45@gmail.com
LikeLike
Hi, Thanks for the great tutorial.
There is a bug in when we scroll down and see some horizontal item’s are already scrolled with some random position ? What is use of mRowIndex??
LikeLike
How to perform child ite click?
LikeLike
How to add a start activity for result in verticalar recyclerview and update value based on the result
LikeLike
Hi, hopefully you still read old blog post comments. Firstly, this is article was a tremendous help, I had tried and failed to used the sectioned recyclerview for my tv programme guide app but this works and it’s far simpler to implement.
Q. How can I scroll the all the recyclerviews horizontally as one rather than individually.
Thanks!
LikeLike
Horizontal RecyclerView inside a Vertical RecyclerView
How to call JSON Array call and fetch Database
LikeLike