Collapsing AppBarLayout on Android TV

Posted by

CoordinatorLayout has really made it easy to perform animations for elements that are dependent on one another, but not all of the behaviours work out of the box for Android TV.

There are some compelling use cases for CoordinatorLayout — Behaviors are a neat (as in “neat-o”) way to encapsulate view logic that involves multiple elements — like the simple app bar collapsing behaviour:

Animated gif showing a collapsing app bar as user scrolls down

Excellent, and took less than ten minutes to implement. Let’s test it works for keyboard users, :shipit: and lunchtime!

But… not so fast. Here’s what it looks like on a Nexus Player (or any device with non-touch input):

Animated gif showing a listview with the last item obscured as the user scrolls down with d-pad input
  • the app bar doesn’t actually collapse
  • The last item in the list isn’t fully visible

We could live with the first one, but the second actually degrades the user’s experience (compared to not using this Behavior).

The app bar doesn’t react to scrolling of the RecyclerView as you navigate down with a directional pad so the scrolling view is still the same size of the viewport, but its offset isn’t adjusted. We can fix this. We have the technology.

Beginning with version 23 of the design support library, AppBarLayout includes a new show/hide API: setExpanded(boolean expand, boolean animate).

When a d-pad is used to scroll the view, we can trigger that behaviour ourselves:

https://gist.github.com/ataulm/d65059e914d1b1de8e8e6243c8fcb737

The scrollVerticallyBy(int dy, …) method in RecyclerView.LayoutManager is called whenever the RecyclerView is scrolled — in both touch and non-touch mode.

We can override this method, and if we’re in non-touch mode (i.e. using a d-pad), then we can notify our AppBarExpander:

https://gist.github.com/ataulm/7d9fb5ef6f085a205c96b3a58bf1f2b0

And here’s the end result (or as I like to call it, lunchtime):

Animated gif showing a listview with the last item fully visible and the app bar hiding as user scrolls down with d-pad input

2 September 2015: you can also use this technique by adding a RecyclerView.OnScrollListener to the RecyclerView directly, which should be more robust (at least in terms of switching LayoutManagers).

This was originally posted on the Novoda blog on 22 August 2015