---
title: Introducing ExpandableRecyclerView
teaser: 'Introducing Expandable RecyclerView: an open source library for expanding
  and collapsing groups using `RecyclerView.Adapter`.

  '
tags: android,design,news
author: Amanda Hill
published_on: 2016-08-31
---

Introducing [Expandable RecyclerView](https://github.com/thoughtbot/expandable-recycler-view):
an open source library for expanding and collapsing groups using `RecyclerView.Adapter`.

![](https://images.thoughtbot.com/blog-vellum-image-uploads/jCk8uQOXTk2Ah6Y6xmbx_yay.gif)

## The Why

At Google IO 2014, Google introduced the `RecyclerView` widget - an entirely
updated approach to showing a collection of data. `RecyclerView` was designed
to be more flexible and extendable than its predecessor, `ListView`. While
most of what `RecyclerView` offers is an improvement over the existing
functionality of `ListView`, there are a few notable features missing from the
`RecyclerView` API. For example, we lost our dear friend `OnItemClickListener`
and our lesser, but still kinda close friend, `ChoiceModes`. And if all that
lost functionality wasn’t depressing enough, we also lost all of the
subclasses and custom implementations of `ListView`, like
`ExpandableListView`.

But as my dear (albeit fictional) friend Liz Lemon once said, [“don’t be cry, it
okay”](https://www.youtube.com/watch?v=z9HG03zHHfY) because today we are
introducing `ExpandableRecyclerView`, an open source library with custom
`RecyclerView.Adapter`s for expanding and collapsing groups to bring back some
of the former glory of `ExpandableListView`.

## The What

To understand this library is to understand `RecyclerView.Adapter`. According
to the docs:

> [RecyclerView] Adapters provide a binding from an app-specific data set to
> views that are displayed within a RecyclerView

In other words, the adapter is just the middleman: translating indexes from
some backing data structure, to views to be passed along to a `RecyclerView`
to be seen on screen. When you are showing a single dimensional list of
objects, this translation is simple. The indexes of the objects in the backing
data set directly correspond to the indexes of views displayed on screen. But
when you want to display two dimensional data, like in case of an expandable
list, this translation gets a bit more tricky. When the indexes of the views
are the same as those of the backing data set, there is only a single truth to
maintain. But when those indexes become disparate, so does the source of
truth, leaving you with two possible truths.

Confused? Me too. Let’s look at a sample app, for some clarity and see how the
`ExpandableRecyclerViewAdapter` works.

## The How

![](https://images.thoughtbot.com/blog-vellum-image-uploads/Bc7244ChSgyrDjzGyHs0_expandable.png)

Above is music app showing a list of `Genre`s with corresponding `Artist`s.

The numbers to the left of the phones represent the view indexes. As you can
see both phones contain 9 row items. But if you look at row 6, you will see
the data on each phone is different. On the left, view index 6 equals the
`Genre` object, `Classic` while on the right it equals the `Artist` object,
`Miles Davis`. Enter the double source of truth problem. The view indexes
(truth numero uno) are different from the backing data structure indexes
(truth numero dos).

If you thought this double source of truth problem was confusing, don’t worry,
you’re not alone. The `RecyclerView.Adapter` also can’t understand it. In
fact, the adapter isn’t even designed to handle two dimensional data. If you
look at all the callbacks and methods on `RecyclerView.Adapter` you’ll notice
it just passes around a single `int` called `position`.

So to make this whole thing work, all we need some way to translate the two
dimensional data to a flattened, single dimensional data set for the adapter
to use.

## The Okay, But Really How

Enter `ExpandableList` and `ExpandableListPosition`.

`ExpandableList` acts as a translator between the flat list position (i.e.
what groups and children you see on the screen) to and from the full backing
list of groups and their children - the unflattened position.

`ExpandableListPosition` is an object that can refer to either a group's
position or a child’s position. Referring to a child's position requires both
a group position (the group containing the child) and a child position (the
child's position within that group). The advantage of containing all the
information about an expandable list position item in one class is that it
saves us from having to iterate over the backing data set multiple times to
determine whether an expandable list position was a child or a group and, in
the case of a child, what that child’s position is within its containing
group.

And we can thank Google for thinking of something so clever, as
`ExpandableListPosition` is actually from the Android SDK. The only reason we
even had to include it as a separate class in this library was because it has
package local scope within the Android SDK.

## The Where

```groovy
compile 'com.thoughtbot:expandablerecyclerview:1.0'
```

See the full library and instructions for how to use it on
[Github](https://github.com/thoughtbot/expandable-recycler-view).

## The When

Now! Go forth and play!
