Compose -- AppBar的简单使用

512 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

概述

本篇学习笔记主要是学习Appbar组件的使用,在Compose中我们一般使用Scaffold作为页面的根可组合项,Scaffold为我们提供了很多的属性来进行一些自定义的操作,其中AppBar组件就是方面我们实现页面的顶部或者底部导航来提供的。

简单使用

下面的代码中指定了使用TopAppBarBottomAppBar,没有定义任何的属性,如下代码所示:

    Scaffold(modifier = Modifier.fillMaxSize(), topBar = {
        TopAppBar() {

        }
    }, bottomBar = {
        BottomAppBar() {

        }
    }) {
        SimpleTextContent(content = LocalContext.current.getString(R.string.app_bar)) {
        }
    }

直接运行上面的代码就可以看到如下的效果:

AppBar简单使用

可以看到,不管是AppTopBar还是AppBottomBar,本身是带有高度的,同时本身也是宽度扩展到全屏的,我们不需要指定它们的宽度和高度。

backgroundColor

如果我们需要设置AppBar的背景颜色,那么应该通过其自身的backgroundColor属性去设置,虽然AppBar也可以接收Modifier相关的参数,但是如果我们通过Modifier.background()去设置背景颜色的话,那么将无法看到任何效果。

 TopAppBar(backgroundColor = Color.Black) {

        }

设置标题title

我们可以给AppBar通过title参数指定一个标题,从方法的定义上看,title可以接收一个可组合项,因此我们设置的标题将没有限制,如下面的代码所示:

        TopAppBar(
            backgroundColor = Color.Blue,
            title = {
                Text(text = "这里是页面的标题",color = Color.White)
            },
        )

在上面的代码中我们就仅仅是指定了一个Text来作为标题,一般来说我们也只需要一个Text即可。

需要注意的是,如果我们想要标题居中显示的话,我们可以通过下面两种方式去指定:

  1. 通过给Text设置Modifier.fillMaxWidth()配合textAlign = TextAlign.Center可是显示标题居中的效果,这种效果标题只能在宽度上铺满父可组合项,高度上则是根据文字的高度自行设置的。
  2. 通过给Text设置Modifier.fillMaxSize()配合wrapContentSize(align = Alignment.Center)可以达到Text在宽度和高度均占满父可组合项并且标题是居中的。

设置导航按钮

一般情况下,如果不是在应用的首页,我们可能会给标题栏上添加一个返回按钮,这样方便用户在目的地之间导航,在TopAppBar中,我们可以向其传递navigationIcon字段的值,并设置一个可组合项作为导航按钮,可组合项可以任意设置,并不一定非得是返回按钮,下面的代码设置返回按钮作为导航按钮,点击之后可以退出当前可组合项,返回到之前的可组合项:

navigationIcon = {
    IconButton(onClick = { controller.popBackStack() }) {
        Image(
            painter = painterResource(id = R.drawable.ic_back_white),
            contentDescription = "返回"
        )
    }
}

设置上面的属性就可以设置导航,其中controller是导航组件提供的NavController,不熟悉这里的可以查看官方文档中导航组件部分。

需要注意的是:如果我们的导航图标通过Icon去设置的话,在设置了TopAppBar的背景颜色的情况下,Icon的图标颜色可能无法正确显示,我们需要指定其tint属性配置它的颜色才能正确显示,如下所示:

IconButton(onClick = { controller.popBackStack() }) {
    Icon(
        painter = painterResource(id = R.drawable.ic_back_white),
        contentDescription = "返回",
        tint = Color.White
    )
}

下面是设置了导航组件的效果:

给TopAppBar设置导航组件

设置操作列表

除了导航按钮,有时候我们也需要给标题栏设置一些常用的操作,用户可以通过设置的这些按钮执行一些快捷操作,在TopAppBar中我们可以通过向actions参数传递可组合项达到这样的效果。

下面的代码演示了在TopAppBar上添加相应的操作按钮:

            actions = {
                Icon(
                    painter = painterResource(id = R.drawable.ic_menu_white_24),
                    contentDescription = "菜单",
                )
                Icon(painterResource(id = R.drawable.ic_search_white_24), contentDescription = "搜索",)
                Icon(
                    painter = painterResource(id = R.drawable.ic_history_white_24),
                    contentDescription = "历史",
                )
            }

在上面的代码中我们添加了三个操作按钮,由于这里只是为了演示,所以就只设置了Icon,如果需要在点击之后执行相应的操作,可以设置其父组合项为Button即可。

另外需要注意的一点是:actions里面的可组合项是使用Row的方式排列的,这里源码中对actions的定义为actions: @Composable RowScope.() -> Unit = {},也就是说我们在可组合项中可以使用RowScope的相关属性,比如weight,但是问题是在设置了weight属性后,之前设置的title可组合项就不可见了。

下面是设置操作列表的效果:

设置操作列表

设置内容颜色

在设置导航按钮的时候,我们发现,不指定Icontint属性,最终显示的图标颜色会有问题,但是在设置actions的时候,我们并没有指定tint属性,最终的效果也是没有问题的,这是因为我们同时设置了contentColor属性。

源码中contentColor的默认值为contentColor: Color = contentColorFor(backgroundColor),这是根据我们设置的背景颜色到主题中去匹配一个与之对应的颜色,之前我们没有设置contentColor,只设置了backgroundColor,而匹配上的颜色和我们想要的颜色(图标本身的颜色)不一样,所以会造成显示效果上的差异。

下面的代码指定了内容的颜色为白色:

contentColor = Color.White

设置Z轴高度

为了能够明显区分屏幕中标题栏和其它部分,有时候我们需要给标题栏设置一个突起(Z轴的高度),TopAppBar向我们提供了elevation属性来设置阴影效果,如下面的代码所示:

elevation = 10.dp

实际上在之前的代码演示中,我们就已经能够看到设置了Z轴高度的效果,因为默认TopAppBar就会设置期高度,相应的代码如下:

elevation: Dp = AppBarDefaults.TopAppBarElevation
val TopAppBarElevation = 4.dp

可以看到,默认的Z轴高度是4dp.

至此,TopAppBar的相关内容就学习完了,可以看到,TopAppBar的使用还是很简单的,我们只需要向其中传递必要的参数即可快速实现一个通用的标题栏。

BottomAppBar

Scaffold可组合项中,除了提供了topBar的配置,也提供了bottomBar的配置,一般情况下,我们可以使用BottomAppBar来创建底部的标题栏,不过底部标题栏在具体的项目中使用的不多,因此这里的可配置项并不是很多,下面的代码演示了BottomAppBar的基本使用:

bottomBar = {
        BottomAppBar(
            backgroundColor = Color.Red,
            contentColor = Color.White,
            elevation = 6.dp,
            contentPadding = PaddingValues(start = 50.dp, end = 50.dp),
            cutoutShape = MaterialTheme.shapes.small.copy(CornerSize(50.dp))
        ) {
            Text(text = "这里是底部操作栏")
        }
    }

这里需要注意的是:cutoutShape用于在Scaffold中设置FloatingActionButton的时候,为了和这个可组合项配合需要使用的切口形状,这里可以接收一个Shape类型的参数,也就是说我们可以接收任意的缺口形状。除此之外,BottomAppBar的其他参数的含义和TopAppBar相同。

下面是使用BottonAppBar的效果:

使用BottomAppBar