Jetpack Compose Scaffold(BottomNavigation UI)

#目次
1. Scaffoldとは
2. サンプルコード
3. まとめ

##1. Scaffoldとは

``Scaffold``‥マテリアル コンポーネントを、一般的な画面のパターンに組み合わせ、例アクトを構築することができる。**Scaffold**には、後置ラムダスロット**content**があり、``RowScope``を利用することで、UIの要素を横並びの一列に配置することができる。**TopAppBar、BottomAppBar、FloatingActionButton、Drawer**などを実装することができる。

**後置ラムダスロット**‥コンポーザブルなコンテンツを引数として受け入れ、それをUIの要素として利用することができる汎用ラムダのこと

今回は、以下のBottomNavigationを作成していきたいと思います。
![bottomScreen.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512202/16bcdd9b-200d-7827-a58f-ff2d7cda1ff7.gif)

##2. サンプルコード

では、実際に**Scaffold**を利用して、**BottomAppBar**のUIを構築していきたいと思います。

初めに、Screenの構成要素を**sealed class**を用いて、以下のように定義します。

```kotlin
sealed class Screen(val route: Stringval icon: ImageVector){
    object MailScreen: Screen("mail", Icons.Filled.Email)
    object ProfileScreen: Screen("profile", Icons.Filled.Person)
}
```

それでは、**Scaffold**を用いてUIの作成に移りたいと思います。
(Navigationに関連するキーワドの説明は、省略させていただきます。)

```kotlin
@Composable
fun BottomSheetWithFloatingButton(){

    val navController = rememberNavController()

    Scaffold(

        bottomBar = {
            BottomAppBar(
                modifier = Modifier
                    .height(70.dp)
                    .clip(RoundedCornerShape(30.dp, 30.dp, 0.dp, 0.dp)),
                cutoutShape = androidx.compose.foundation.shape.CircleShape,
                elevation = 20.dp
            ) {
                CustomBottomNavItem(navController = navController)
            }
        },
        floatingActionButtonPosition = FabPosition.Center,
        isFloatingActionButtonDocked = true,
        floatingActionButton = {
            FloatingActionButton(
                onClick = {

                },
                contentColor = Color.White
            ) {
                Icon(imageVector = Icons.Filled.Add, contentDescription = null)
            }
        }
    ) {
        ScreenNavigation(navController = navController)
    }
}
```

**Scaffold**は、上記のようにスロットがたくさんあり、それぞれのラムダに処理を記述します。

``bottomBar``‥後述するコンポーザブルを、スロットの中で呼び出します。ここで、BottomNavigationの、Icon,Labelなどを決定することのできるBottomNavigationというスロットを呼び出します。

``floatingActionButton``‥ここでは、FloatingActionButtonを呼び出し、Iconなどを決定できます。

``その他``‥FloatingActionButtonの位置を決定したり、BottomNavigation上にオーバーラップするかを決定することができます。

そして、``bottomBar``で呼び出されているコンポーザブルは以下のようになります。

```kotlin
@Composable
fun CustomBottomNav(
    navController: NavHostController
) {

    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentDestination = navBackStackEntry?.destination

    BottomNavigation(
        modifier = Modifier
            .padding(0.dp, 0.dp, 0.dp, 5.dp)
            .height(100.dp),
        elevation = 0.dp
    ) {
        screenItem.forEach { screen ->
            BottomItem(
                screen = screen,
                currentDestination = currentDestination,
                navController = navController
            )
        }
    }
}
```

また、**forEach**で振り分けているリストは以下のようになります。

```kotlin
val screenItem = listOf(
    Screen.MailScreen,
    Screen.ProfileScreen
)
```
``CustomBottomNav``では、**BottomNavigation**を呼び出しそこでリスト(構成するスクリーンを網羅したもの)の中身を、以下のコンポーザブルに渡します。

```kotlin
@Composable
fun RowScope.BottomItem(
    screen: Screen,
    currentDestination: NavDestination?,
    navController: NavHostController
){
    BottomNavigationItem(
        icon = {
               Icon(
                   imageVector = screen.icon,
                   contentDescription = ""
               )
        },
        selected = currentDestination?.hierarchy?.any {
            it.route == screen.route
        } == true,
        unselectedContentColor = LocalContentColor.current.copy(alpha = ContentAlpha.disabled),
        onClick = {
            navController.navigate(screen.route)
        }
    )
}
```
Scaffoldは、**RowScope**内で呼び出す必要があるので上記のような記述となり、``BottomNavigationItem``にオブジェクトを渡し、**上記のforEach**で受け取ります。

####Navigationに関する説明を省き、以上のコンポーザブルを実行すると

![bottomScreen.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512202/16bcdd9b-200d-7827-a58f-ff2d7cda1ff7.gif)

このように、BottomNavigationを実行することができました。

[参考URL](https://medium.com/@mumedian6/bottom-navigation-with-docked-fab-in-jetpack-compose-f1ba3cb3771b)
https://medium.com/@mumedian6/bottom-navigation-with-docked-fab-in-jetpack-compose-f1ba3cb3771b

##3. まとめ

今回は、Scaffoldを利用して、マテリアルコンポーネントを一般的な画面パターンに組み合わせてみました。このUIをもとに、[Navigation](https://qiita.com/Ryosuke-Android/items/54768e3400022611c73c)についての記事を作成しました。