On (de)composing action bars
Tags: android, jetpackcompose
Published: 2021-02-11 16:38:43

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:

```kotlin
supportActionBar?.subtitle = "Hello"
```

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

```kotlin
class CanvasDemoActivity : AppCompatActivity() {

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

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

![Two appbars](https://dev-to-uploads.s3.amazonaws.com/i/w6ab75zyc5qad0mt76fb.png)

While this is easy to fix by adding

```xml
android:theme="@style/Theme.DrawingDemo.NoActionBar"
```

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](https://developer.android.com/training/appbar/setting-up) 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](https://dev-to-uploads.s3.amazonaws.com/i/db0jfhm2nibrffick6kg.png)

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:

```kotlin
TopAppBar(title = {
  Column() {
    Text("I am a title")
    Text("Hello", style = MaterialTheme.typography.subtitle1)
  }
})
```

![A selfmade subtitle](https://dev-to-uploads.s3.amazonaws.com/i/igyp3caxq3kstrd3u3tp.png)

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:

```xml
android:parentActivityName=".ShapesDemoActivity"
```

![Specifying a parent activity](https://dev-to-uploads.s3.amazonaws.com/i/rzwnw8zoojv3fo4hgot9.png)

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

```kotlin
navigationIcon = {
  IconButton(onClick = {
    onBackPressed()
  }) {
    Icon(Icons.Default.ArrowBack)
  }
}
```

![A composable back arrow](https://dev-to-uploads.s3.amazonaws.com/i/x7gbnj13f99tbs4kox2c.png)

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?