Jetpack ComposeでTopAppBarとBottomAppBarを使うには

Jetpack Composeを使って画面上部または下部にアプリバーを表示する方法です。

TopAppBar関数とBottomAppBar関数

画面上部のアプリバーは、TopAppBar関数を使います。
画面下部のアプリバーは、BottomAppBar関数を使います。

@Composable
fun TopBar() {
    TopAppBar(
        title = { Text(text = "TopAppBar") },
        backgroundColor = MaterialTheme.colors.primary
    )
}

@Composable
fun BottomBar() {
    BottomAppBar(backgroundColor = MaterialTheme.colors.primary) {
        Text(text = "BottomAppBar")
    }
}

Scaffold関数を使うと、TopBar、BottomBar、FAB、Drawerなどの基本的なレイアウト構造を実現できます。

@Composable
fun MainContent() {
    val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Open))
    Scaffold(
        scaffoldState = scaffoldState,
        topBar = { TopBar() },
        bottomBar = { BottomBar()},
        content = { Text(text = "Content")}
    )
}

TopAppBar関数の引数

TopAppBarは以下の引数を取ります。

title … タイトルのCompose関数
navigationIcon … アイコンのCompose関数
backgroundColor … 背景色
contentColor … 文字色
elevation … dpでの標高値

@Composable
fun TopBar() {
    TopAppBar(
        title = { Text(text = "TopAppBar") },
        backgroundColor = MaterialTheme.colors.primary,
        navigationIcon = {
            IconButton(onClick = { /*TODO*/ }) {
                Icon(
                    imageVector = Icons.Default.Home,
                    contentDescription = "Home"
                )
            }
        },
        elevation = 10.dp
    )
}

titleは複数のCompose関数を受け入れます。

@Composable
fun TopBar() {
    TopAppBar(
        title = {
            Text(text = "Main Title")
            Text(text = "Sub Title", fontSize = 16.sp)
        },
        backgroundColor = MaterialTheme.colors.primary,
        navigationIcon = {
            IconButton(onClick = { /*TODO*/ }) {
                Icon(
                    imageVector = Icons.Default.Home,
                    contentDescription = "Home"
                )
            }
        },
        elevation = 10.dp
    )
}

BottomNavigatin関数

画面下部にメニュー項目を表示するには、BottomNavigatinを使用します。

BottomNavigation関数の中でBottomNavigationItem()関数を呼びます。

@Composable
fun BottomBar() {
    var selectedIndex by remember { mutableStateOf(0) }
    BottomNavigation(elevation = 10.dp) {
        BottomNavigationItem(
            selected = selectedIndex == 0,
            onClick = { selectedIndex = 0 },
            icon = { Icon(imageVector = Icons.Default.Home, contentDescription = "Home")},
            label = { Text(text = "Home")}
        )
        BottomNavigationItem(
            selected = selectedIndex == 1,
            onClick = { selectedIndex = 1 },
            icon = { Icon(imageVector = Icons.Default.Favorite, contentDescription = "Favorite")},
            label = { Text(text = "Favorite")}
        )
        BottomNavigationItem(
            selected = selectedIndex == 2,
            onClick = { selectedIndex = 2 },
            icon = { Icon(imageVector = Icons.Default.Person, contentDescription = "Person")},
            label = { Text(text = "Person")}
        )
    }
}

NavHostController

さらに、NavHostControllerを使ってページを切り替えます。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TopBottomAppBarSampleTheme {
                Surface(color = MaterialTheme.colors.background) {
                    MainContent()
                }
            }
        }
    }
}

@Composable
fun MainContent() {
    val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Open))
    val navController = rememberNavController()
    Scaffold(
        scaffoldState = scaffoldState,
        topBar = { TopBar() },
        bottomBar = { BottomBar(navController)},
    ) {
        NavHost(navController = navController, startDestination = "Home") {
            composable("Home") { HomeScreen() }
            composable("Favorite") { FavoriteScreen() }
            composable("Person") { PersonScreen() }
        }
    }
}

@Composable
fun HomeScreen() = Text(text = "Home")

@Composable
fun FavoriteScreen() = Text(text = "Favorite")

@Composable
fun PersonScreen() = Text(text = "Person")

@Composable
fun TopBar() {
    TopAppBar(
        title = { Text(text = "TopAppBar") },
        backgroundColor = MaterialTheme.colors.primary,
        navigationIcon = {
            IconButton(onClick = { /*TODO*/ }) {
                Icon(
                    imageVector = Icons.Default.Home,
                    contentDescription = "Home"
                )
            }
        },
        elevation = 10.dp
    )
}

@Composable
fun BottomBar(navController: NavHostController) {
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentDestination = navBackStackEntry?.destination

    BottomNavigation(elevation = 10.dp) {
        BottomNavigationItem(
            selected = currentDestination?.hierarchy?.any { it.route == "Home" } == true,
            onClick = { navController.navigate("Home") },
            icon = { Icon(imageVector = Icons.Default.Home, contentDescription = "Home")},
            label = { Text(text = "Home")}
        )
        BottomNavigationItem(
            selected = currentDestination?.hierarchy?.any { it.route == "Favorite" } == true,
            onClick = { navController.navigate("Favorite") },
            icon = { Icon(imageVector = Icons.Default.Favorite, contentDescription = "Favorite")},
            label = { Text(text = "Favorite")}
        )
        BottomNavigationItem(
            selected = currentDestination?.hierarchy?.any { it.route == "Person" } == true,
            onClick = { navController.navigate("Person") },
            icon = { Icon(imageVector = Icons.Default.Person, contentDescription = "Person")},
            label = { Text(text = "Person")}
        )
    }
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    TopBottomAppBarSampleTheme {
        MainContent()
    }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください