DEV Community

Cover image for On (de)composing action bars
Thomas Künneth
Thomas Künneth

Posted on • Edited on

On (de)composing action bars

ActionBars or appbars have come a long way. In recent years we seem to have gotten used to extending AppCompatActivity and messing with supportActionBar. The docs say:

Support library version of
android.app.Activity.getActionBar.
Retrieve a reference to this activity's ActionBar.
Returns:
The Activity's ActionBar, or null if it does not have one.

So we can do something like this:

supportActionBar?.subtitle = "Hello"
Enter fullscreen mode Exit fullscreen mode

Now, what happens when we move on to the composable world? Please look at the following code snippet:

class CanvasDemoActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    supportActionBar?.subtitle = "Hello"
    setContent {
      Scaffold(topBar = {
        TopAppBar(title = {
          Text("Hello")
        })
      }) {
        CanvasContent()
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Depending on how you specify your activity you might end up with something like this:

Two appbars

While this is easy to fix by adding

android:theme="@style/Theme.DrawingDemo.NoActionBar"
Enter fullscreen mode Exit fullscreen mode

in your manifest file, this begs an interesting question:

Why do I need to bother?

Before we dig deeper, let us remind ourselves that the preferred way to Set up the app bar is:

  • Make sure the activity extends AppCompatActivity
  • In the app manifest, set the <application> element to use one of appcompat's NoActionBar themes
  • Add a Toolbar to the activity's layout

Basically, that is what my activity example is doing, in a new composable way. Scaffold acts as a skeleton for my screen. And TopAppBar is, well, an appbar that appears on top of the content. Still, by using supportActionBar?.subtitle = "Hello" I am certainly mixing concepts. Because TopAppBar is something new. It does not use the platform action bar. And it does not use androidx.appcompat.app.ActionBar, either.

Now, let's decompose the composable.

A look at the TopAppBar source code

As you can see, there are quite a few parameters we can set, for examle title or navigationIcon. But no subtitle. As title is a composable, you can pass something like this, though:

TopAppBar(title = {
  Column() {
    Text("I am a title")
    Text("Hello", style = MaterialTheme.typography.subtitle1)
  }
})
Enter fullscreen mode Exit fullscreen mode

A selfmade subtitle

Not too bad, isn't it? As you can see, the color slightly differs, but we could fix that if needed. But let's move on.

Please recall that if you add something like this to <activity>, you get a nice back arrow for free:

android:parentActivityName=".ShapesDemoActivity"
Enter fullscreen mode Exit fullscreen mode

Specifying a parent activity

Your TopAppBar does not benefit from this, though. To make something similar, do something like this:

navigationIcon = {
  IconButton(onClick = {
    onBackPressed()
  }) {
    Icon(Icons.Default.ArrowBack)
  }
}
Enter fullscreen mode Exit fullscreen mode

A composable back arrow

Invoking onBackPressed() is not necessarily the right thing to do 😂 but for a demo it works nicely. In any case please remember to pass in the action (lambda) as a parameter to your composable.

The top appbar has more goodness. What's in stock? Please stay tuned. And as always, I would love to hear your thoughts in the comments. Are we getting there in bridging two worlds? Or are we still struggling?

Top comments (0)