Let’s say we have an expanding / collapsing toolbar, and we want to add an extra interactive element to it: the title should have an extra chevron next to it, and when you click on the title, it should rotate 180 degrees, and open a popup menu, like this:

Image for post

It seems easy, on a first glance we would probably have to retrieve the TextView used by the CollapsingToolbarLayout to retrieve the TextView, add a right compound drawable and a click listener, and that’s it, right?

Well, the problem is, that there’s no TextView at all. The relevant code is inside the CollapsingTextHelper class, and it turns out that the collapsing text is created by drawing on the View canvas directly. Instead, we will have to rely on the feature that we can put custom widgets inside the toolbar, and manipulate those so that they look as they are connected to the text.

The layout

Our layout XML code will look like this:

It is quite long and complicated, but let’s go through it from top to bottom:

First of all, you have CollapsingToolbarLayout , with its usual properties. With its app: properties we position and style the collapsed/expanded text to our taste. That was already part of our setup before.

The first widget inside the layout is a Space. The size of the largest widget inside the CollapsingToolbarLayout dictates its expanded size. That’s what I use this layout for.

The next layout in order is the Toolbar itself. It contains some extra properties to put the text at the correct place (left and right margins), this layout can also be used to put some extra widgets inside, like a cast button on the right.

The next view is a clickable layout, with the chevron in it. We will try to position this layout exactly where the text is, changing its size and height while collapsing. The chevron inside is just a regular ImageView which we will rotate on the click action.

Finally, we have a back button touch forwarder, positioned exactly above the back button. See why this is required in the following section.

The code

We tie into the AppBar offset listener to detect what the collapse status is of the  toolbar.

First we need to detect if the offset changed. Because we change the layout inside the listener, it will trigger a new call on the same listener. If we would not check for this, we will get inside an infinite loop.

Next we use the knowledge that we have all the font, text size info from the collapsed and expanded states. Using those, and the current collapse offset, we calculate the exact width an position of the clickable layout, and position it.

Now we can add a click listener, which hides or show the popup window:

binding.clickableLayout.setOnClickListener { if (!hidePopupWindow()) { displayGenreChooser() } }

Finally, the back button touch forwarder. We need to put our clickable layout above the Toolbar, because the Toolbar ‘eats’ all touch events. But when the clickable layout is on top, the back button would be mostly hard to click, because the text gets quite close.
Our solution is putting an extra View on top of our clickable layout, which is exactly the size and position as the back button, and all it does is forward its touch events to the Toolbar below it.

Disabling the collapse / expand animation

A feature we wanted to have is to disable the expand animations on the toolbar, and just have it locked in the same place. Also we would like to reuse the toolbar code for this, so we don’t have to style it again.

When we call this code, it will set the toolbar in a collapsed state immediately.
We set nested scrolling enabled on the content, so that it should not forward any scroll calls, and we also change the Coordinator behavior on the AppBar layout, so that dragging it manually does also not expand it.

Finally, we set the visibility of the extra widgets to gone, because those would suggest interactivity.

With this, we get our end result:

Image for post

You can try out the code yourself here 

Daniel - Team - Egeniq

Dániel Zolnai



Leave a comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.