All CategoriesAndroid App Development

Introduction to Expandable RecyclerView in Android

Expandable RecyclerView

Expandable RecyclerView is one of the most important feature in Android which can be easily created for our application using Big Nerd Ranch’s Expandable RecyclerView Library
It contains two views one is parent view and other is child view. Parent is visible by default but the child view has to be expanded and collapsed. It will expand when we click on parent view.
This feature is quite similar to the ExpandableListView in Android. Since it is an old one, it does not perform well according to our requirement.
We have to create two view holders to hold the view of parent and child i.e. ParentViewHolder and ChildViewHolder.
So, by using these we shall create it in our application to make it better.

build.gradle:

Add this dependency in your build.gradle file.

dependencies {
compile 'com.android.support:recyclerview-v7:23.2.1'
}

After adding the library, we have to add some Java classes with the help of this library like Adapter, Model, and View holders.

Example with Code:

Now, it’s time to do it programmatically. So here in this example we will show Movie category as a parent and movies according to the category are a child.
Create an Application Expandable RecyclerView ExampleAndroid.

Requirements:

MainActivity.java, MovieCategory.java, MovieCategoryAdapter.java, MovieCategoryViewHolder.java, Movies.java, MoviesViewHolder.java, activity_main.xml, movie_category_view.xml, movies_view.xml.
After adding a library and some Java classes let’s do it one by one in our project.

MovieCategory.java:

Create this parent class, implements ParentListItem and override its method

Add the code here

public class MovieCategory implements ParentListItem {
private List<Movies> mMovies;
@Override
public List<?> getChildItemList() {
return mMovies;
}

Here, it returns the list of movies.

Movies.java:

Create this child class it is used to show the data in each child of a parent.

Add the code here

public class Movies {
private String mName;
public Movies(String name) {
mName = name;
}
public String getName() {
return mName;
}
}

movie_category_view.xml:

Create this XML file for creating the view of movie category.
Add the code inside LinearLayout.

<TextView android:id="@+id/tv_movie_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="@dimen/standard_text_size"
android:textStyle="bold"/>
<ImageView android:id="@+id/iv_arrow_expand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/selector_arrow_down"/>

It shows a text view with an arrow icon.

MovieCategoryViewHolder.java:

Create this class and extend it with ParentViewHolder. It is a class which binds the view. Here we take the reference of MovieCategory view and set the properties when it is expanded and collapsed.

Add the code here

mMovieTextView = (TextView) itemView.findViewById(R.id.tv_movie_category);
mArrowExpandImageView = (ImageView) itemView.findViewById(R.id.iv_arrow_expand);

Add the code in bind(…) method

mMovieTextView.setText(movieCategory.getName());

Now, set the properties for expand and collapse of arrow image and its rotation accordingly by implementing two methods setExpanded() and onExpansionToggled().

Add the code here:

@Override
public void setExpanded(boolean expanded) {
super.setExpanded(expanded);
if (expanded) {
mArrowExpandImageView.setRotation(ROTATED_POSITION);
} else {
mArrowExpandImageView.setRotation(INITIAL_POSITION);
}
}
@Override
public void onExpansionToggled(boolean expanded) {
super.onExpansionToggled(expanded);
RotateAnimation rotateAnimation;
if (expanded) { // rotate clockwise
rotateAnimation = new RotateAnimation(ROTATED_POSITION,
INITIAL_POSITION,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
} else { // rotate counterclockwise
rotateAnimation = new RotateAnimation(-1 * ROTATED_POSITION,
INITIAL_POSITION,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
}
rotateAnimation.setDuration(200);
rotateAnimation.setFillAfter(true);
mArrowExpandImageView.startAnimation(rotateAnimation);
}

movies_view.xml:

Create this XML file. It shows the view of child items.
Add the code inside LinearLayout.

<TextView android:id="@+id/tv_movies"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/standard_text_size"/>

Here, it shows the name of movies with respect to the parent.

MoviesViewHolder.java:

Create this class and extend it with ChildHolder. Here, we take the reference of the child view.

Add the code here

mMoviesTextView = (TextView) itemView.findViewById(R.id.tv_movies);

Add the code in bind(..) method:

public void bind(Movies movies) {
mMoviesTextView.setText(movies.getName());
}

MovieCategoryAdapter.java:

Create this custom Adapter class which extends ExpandableRecyclerAdapter. Here, it has two different sets of onCreateViewHolder and onBindViewHolder. One of which is for parent and the other for the child.

Add the codes here

@Override
public MovieCategoryViewHolder onCreateParentViewHolder(ViewGroup parentViewGroup) {
View movieCategoryView = mInflator.inflate(R.layout.movie_category_view, parentViewGroup, false);
return new MovieCategoryViewHolder(movieCategoryView);
}
@Override
public MoviesViewHolder onCreateChildViewHolder(ViewGroup childViewGroup) {
View moviesView = mInflator.inflate(R.layout.movies_view, childViewGroup, false);
return new MoviesViewHolder(moviesView);
}
@Override
public void onBindParentViewHolder(MovieCategoryViewHolder, int position, ParentListItem parentListItem) {
MovieCategory = (MovieCategory) parentListItem;
movieCategoryViewHolder.bind(movieCategory);
}
@Override
public void onBindChildViewHolder(MoviesViewHolder, int position, Object childListItem) {
Movies movies = (Movies) childListItem;
moviesViewHolder.bind(movies);
}

activity_main.xml:

Create this XML file for RecyclerView.
Add the code inside LinearLayout.

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

MainActivity.java:

It is in our Main Activity that we pass the data, set the adapter and take the reference of Recycler View.

Add the code here

Initialize:

private MovieCategoryAdapter mAdapter;
private RecyclerView recyclerView;
Add the code in onCreate(..){}:
Movies movie_one = new Movies("The Shawshank Redemption");
Movies movie_two = new Movies("The Godfather");
Movies movie_three = new Movies("The Dark Knight");
Movies movie_four = new Movies("Schindler's List ");
MovieCategory molvie_category_one = new MovieCategory("Drama", Arrays.asList(movie_one, movie_two, movie_three, movie_four));

Like this, we can add more movie categories.

final List<MovieCategory> movieCategories = Arrays.asList(molvie_category_one, molvie_category_two, molvie_category_three,molvie_category_four);
recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
mAdapter = new MovieCategoryAdapter(this, movieCategories);
recyclerView.setAdapter(mAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

We can also set the properties of expanding and collapse it by setExpandCollapseListener(..).

Add the code when our list item Expanded and collapsed:

mAdapter.setExpandCollapseListener(new ExpandableRecyclerAdapter.ExpandCollapseListener() {
@Override
public void onListItemExpanded(int position) {
MovieCategory expandedMovieCategory = movieCategories.get(position);
String toastMsg = getResources().getString(R.string.expanded, expandedMovieCategory.getName());
Toast.makeText(MainActivity.this,
toastMsg,
Toast.LENGTH_SHORT)
.show();
}
@Override
public void onListItemCollapsed(int position) {
MovieCategory collapsedMovieCategory = movieCategories.get(position);
String toastMsg = getResources().getString(R.string.collapsed, collapsedMovieCategory.getName());
Toast.makeText(MainActivity.this,
toastMsg,
Toast.LENGTH_SHORT)
.show();
}
});

Now, set the adapter and layout manager in our recycler view.

recyclerView.setAdapter(mAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

Here, we can do like this.

Save and Restore the state of Expand / Collapsed:

We can save the expanded and collapsed state of items in our Recycler View during our device configuration changes. Other things and also we can store the state of same.
To save Expanded / Collapsed state we can call ExpandableRecyclerAdapter.onSaveInstanceState(Bundle savedInstanceState).

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mAdapter.onSaveInstanceState(outState);
}

Like this, we can save the state.
To restore expanded / collapsed state we can call ExpandableRecyclerAdapter.onRestoreInstanceState(Bundle savedInstanceState).

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mAdapter.onRestoreInstanceState(savedInstanceState);
}

Like this, we can restore the state.

Output:

Download Code: Github

Conclusion:

This was an interesting example of how to create Expandable RecyclerView by using Big Nerd Ranch’s library in our application. This feature is mainly used in many applications. We can customize it according to the requirement. It is the same as ExapandableListView but has some new features added. An interesting functionality of Android, it is frequently used by the developers.

Related Popular Courses:

 
Android Programming
 

Tags

5 Comments

  1. HEY thats nice tutorial but can u explain me how do i get the child position in the fragments class and how to make like only one to be expandable if i have 3 views i need only one among them to be opened first please help me put

    1. You have no need of reference of Fragment view to get its components in Activity. As you can directly access layout components of a Fragment in parent Activity.
      Simply you can access any component by this
      findViewById(R.id.child_of_fragment_layout);

  2. How can we optimize the multiple lines
    Movies movie_one = new Movies(“The Shawshank Redemption”);
    Movies movie_two = new Movies(“The Godfather”);
    Movies movie_three = new Movies(“The Dark Knight”);
    Movies movie_four = new Movies(“Schindler’s List “);
    into one line. May be by using list or array. Please suggest

    1. Hi Yaka,
      Thank you for asking us and reading our blogs..!!
      In this code, We are creating objects for all four Movies, so you cannot take it into single line. Add for all to assign in different Movies objects.

  3. Hi, it was a nice tutorial. I want to show toast message when clicked on any child item, lets say Shawshank redemption. Can you tell where should i put that code.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Articles

Close