如何在 TopAppBar 的布局中心对齐标题?
How to align title at layout center in TopAppBar?
TopAppBar(
backgroundColor = Color.Transparent,
elevation = 0.dp,
modifier= Modifier.fillMaxWidth(),
navigationIcon = {
IconButton(
onClick = { TODO },
enabled = true,
) {
Icon(
painter = painterResource(id = R.drawable.icon_back_arrow),
contentDescription = "Back",
)
}
}
},
title = {
Text(
modifier = if (action == null) Modifier.fillMaxWidth() else Modifier,
textAlign = if (action == null) TextAlign.Center else TextAlign.Start,
maxLines = 1,
text = "Hello"
)
},
actions = {
action?.run {
Text(
modifier = Modifier
.padding(horizontal = 16.dp)
.clickable(onClick = TODO),
color = Color.Green,
text ="Cancel",
)
}
}
我是 Jetpack 的新手,如果 action 为 null,我想将 TopAppBar 的标题居中对齐。标题未对齐布局中心。当没有 navigationIcon 时它工作但添加 navigationIcon 它显示稍微正确。我怎样才能使标题文本位于布局中心。
对于 Material2,您必须使用 TopAppBar
的另一个构造函数,它没有预定义的内容插槽,允许您自定义内容的布局。
您可以这样做:
val appBarHorizontalPadding = 4.dp
val titleIconModifier = Modifier.fillMaxHeight()
.width(72.dp - appBarHorizontalPadding)
TopAppBar(
backgroundColor = Color.Transparent,
elevation = 0.dp,
modifier= Modifier.fillMaxWidth()) {
//TopAppBar Content
Box(Modifier.height(32.dp)) {
//Navigation Icon
Row(titleIconModifier, verticalAlignment = Alignment.CenterVertically) {
CompositionLocalProvider(
LocalContentAlpha provides ContentAlpha.high,
) {
IconButton(
onClick = { },
enabled = true,
) {
Icon(
painter = painterResource(id = R.drawable.ic_add_24px),
contentDescription = "Back",
)
}
}
}
//Title
Row(Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically) {
ProvideTextStyle(value = MaterialTheme.typography.h6) {
CompositionLocalProvider(
LocalContentAlpha provides ContentAlpha.high,
){
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
maxLines = 1,
text = "Hello"
)
}
}
}
//actions
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Row(
Modifier.fillMaxHeight(),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
content = actions
)
}
}
}
使用 Material3 你可以简单地使用 CenterAlignedTopAppBar
:
CenterAlignedTopAppBar(
title = { Text("Centered TopAppBar") },
navigationIcon = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Localized description"
)
}
}
)
@Composable
fun TopAppBarCompose(){
TopAppBar(
title = {
Box(modifier = Modifier.fillMaxWidth()) {
Text(
text = "Hello",
fontSize = 30.sp,
modifier = Modifier.align(Alignment.Center)
)
}
},
)
}
之前的解决方案太复杂了。其实很简单:
title = {
Text(
text = "title",
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
}
标题居中的核心是左右占位space相同。您只需要调整插槽的默认大小。我们给左右槽默认space个占用槽,可以很好的解决这个问题,而且代码简单
@Composable
fun TopBar(title: Int, actions: @Composable (() -> Unit)? = null, popOnClick: () -> Unit) {
val modifier = Modifier.size(width = 70.dp, height = 50.dp).background(Color.Red)
TopAppBar(
title = {
Text(text = stringResource(id = title), fontSize = 16.sp,
textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth()) },
navigationIcon = {
Box(modifier = modifier, contentAlignment = Alignment.Center) {
IconButton(onClick = { popOnClick() }) {
Icon(Icons.Filled.ArrowBack, contentDescription = "", tint = MaterialTheme.colors.primary)
}
}
},
actions = {
Box(modifier = modifier, contentAlignment = Alignment.Center) {
if (actions != null) {
actions()
}
}
},
backgroundColor = MaterialTheme.colors.surface,
elevation = 1.dp
)
}
我重做了一些本机实现。
只需要做两件事:
1.Add这个文件到你的项目中。这是 TopAppBar
class 的稍微修改的实现。
https://gist.github.com/evansgelist/aadcd633e9b160f9f634c16e99ffe163
2.Replace 在您的代码中 TopAppBar 到 CenterTopAppBar。这就是全部!
Scaffold(
topBar = {
CenterTopAppBar(
title = {
Text(
textAlign = TextAlign.Center,
text = text,
)
},
编辑
分机代码
val Number.toPx
get() = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
this.toFloat(),
Resources.getSystem().displayMetrics
)
结果
这取决于应用栏中的内容。
如果你只有标题,那么你可以这样做:
topBar = {
TopAppBar(content = {
Text(
modifier = Modifier.fillMaxWidth(),
text = "Title Text",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.h6,
)
})
},
如果你的两边都有一个图标,你应该可以做同样的事情,如果一边有两个图标,另一边有两个图标,那么可能需要调整一些东西,然后可能想要使用添加相同大小的图标来均匀地放置东西out 并将 enabled 设置为 false,使其不可点击,颜色设置为透明,因此看不到,否则您可以尝试计算大小并在文本末尾添加填充,看来您还需要添加 16.dp 填充透明图标,因为导航图标在标题之前有额外的填充,但在标题和操作之间没有填充
这是我为箭头图标和标题所做的
topBar = {
TopAppBar(
navigationIcon = {
IconButton(
onClick = {
navController.popBackStack()
}
) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "back arrow icon"
)
}
},
title = {
Text(
modifier = Modifier
.fillMaxWidth(),
text = "Basic Navigation",
textAlign = TextAlign.Center,
)
},
actions = {
IconButton(
modifier = Modifier
.padding(start = 16.dp),
enabled = false,
onClick = {}
) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "back arrow icon",
tint = Color.Transparent
)
}
}
)
}
如果您使用的是 Material3,您也可以使用 CenterAlignedTopAppBar
。
fun CenterAlignedTopAppBar(
title: @Composable () -> Unit,
modifier: Modifier = Modifier,
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(),
scrollBehavior: TopAppBarScrollBehavior? = null
) {
SingleRowTopAppBar(
modifier = modifier,
title = title,
titleTextStyle =
MaterialTheme.typography.fromToken(TopAppBarSmallTokens.HeadlineFont),
centeredTitle = true,
navigationIcon = navigationIcon,
actions = actions,
colors = colors,
scrollBehavior = scrollBehavior
)
}
我只是 Jetpack Compose 的初学者,在寻找该问题的解决方案之前,我尝试自己想办法,也许对某些人来说就足够了。我需要 TopAppBar 的居中标题,只有左侧有导航图标,或者左右有两个图标,这个解决方案对我来说没问题。后来我配置了是否在右侧包含传递的图标。
TopAppBar(
backgroundColor = Color.Green,
elevation = 5.dp,
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
// size of an icon and placeholder box on the right side
val iconSize = 32.dp
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "Arrow Back",
modifier = Modifier
.clickable {
navController.popBackStack()
}
.size(iconSize)
)
Text(text = "Centered Title", fontSize = 32.sp)
// placeholder on the right side in order to have centered title - might be replaced with icon
Box(
modifier = Modifier
.size(iconSize)
) { }
}
我无法附上截图,预览在这里:https://i.stack.imgur.com/UNQTF.png
TopAppBar(
backgroundColor = Color.Transparent,
elevation = 0.dp,
modifier= Modifier.fillMaxWidth(),
navigationIcon = {
IconButton(
onClick = { TODO },
enabled = true,
) {
Icon(
painter = painterResource(id = R.drawable.icon_back_arrow),
contentDescription = "Back",
)
}
}
},
title = {
Text(
modifier = if (action == null) Modifier.fillMaxWidth() else Modifier,
textAlign = if (action == null) TextAlign.Center else TextAlign.Start,
maxLines = 1,
text = "Hello"
)
},
actions = {
action?.run {
Text(
modifier = Modifier
.padding(horizontal = 16.dp)
.clickable(onClick = TODO),
color = Color.Green,
text ="Cancel",
)
}
}
我是 Jetpack 的新手,如果 action 为 null,我想将 TopAppBar 的标题居中对齐。标题未对齐布局中心。当没有 navigationIcon 时它工作但添加 navigationIcon 它显示稍微正确。我怎样才能使标题文本位于布局中心。
对于 Material2,您必须使用 TopAppBar
的另一个构造函数,它没有预定义的内容插槽,允许您自定义内容的布局。
您可以这样做:
val appBarHorizontalPadding = 4.dp
val titleIconModifier = Modifier.fillMaxHeight()
.width(72.dp - appBarHorizontalPadding)
TopAppBar(
backgroundColor = Color.Transparent,
elevation = 0.dp,
modifier= Modifier.fillMaxWidth()) {
//TopAppBar Content
Box(Modifier.height(32.dp)) {
//Navigation Icon
Row(titleIconModifier, verticalAlignment = Alignment.CenterVertically) {
CompositionLocalProvider(
LocalContentAlpha provides ContentAlpha.high,
) {
IconButton(
onClick = { },
enabled = true,
) {
Icon(
painter = painterResource(id = R.drawable.ic_add_24px),
contentDescription = "Back",
)
}
}
}
//Title
Row(Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically) {
ProvideTextStyle(value = MaterialTheme.typography.h6) {
CompositionLocalProvider(
LocalContentAlpha provides ContentAlpha.high,
){
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
maxLines = 1,
text = "Hello"
)
}
}
}
//actions
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Row(
Modifier.fillMaxHeight(),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
content = actions
)
}
}
}
使用 Material3 你可以简单地使用 CenterAlignedTopAppBar
:
CenterAlignedTopAppBar(
title = { Text("Centered TopAppBar") },
navigationIcon = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Localized description"
)
}
}
)
@Composable
fun TopAppBarCompose(){
TopAppBar(
title = {
Box(modifier = Modifier.fillMaxWidth()) {
Text(
text = "Hello",
fontSize = 30.sp,
modifier = Modifier.align(Alignment.Center)
)
}
},
)
}
之前的解决方案太复杂了。其实很简单:
title = {
Text(
text = "title",
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
}
标题居中的核心是左右占位space相同。您只需要调整插槽的默认大小。我们给左右槽默认space个占用槽,可以很好的解决这个问题,而且代码简单
@Composable
fun TopBar(title: Int, actions: @Composable (() -> Unit)? = null, popOnClick: () -> Unit) {
val modifier = Modifier.size(width = 70.dp, height = 50.dp).background(Color.Red)
TopAppBar(
title = {
Text(text = stringResource(id = title), fontSize = 16.sp,
textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth()) },
navigationIcon = {
Box(modifier = modifier, contentAlignment = Alignment.Center) {
IconButton(onClick = { popOnClick() }) {
Icon(Icons.Filled.ArrowBack, contentDescription = "", tint = MaterialTheme.colors.primary)
}
}
},
actions = {
Box(modifier = modifier, contentAlignment = Alignment.Center) {
if (actions != null) {
actions()
}
}
},
backgroundColor = MaterialTheme.colors.surface,
elevation = 1.dp
)
}
我重做了一些本机实现。
只需要做两件事:
1.Add这个文件到你的项目中。这是 TopAppBar
class 的稍微修改的实现。
https://gist.github.com/evansgelist/aadcd633e9b160f9f634c16e99ffe163
2.Replace 在您的代码中 TopAppBar 到 CenterTopAppBar。这就是全部!
Scaffold(
topBar = {
CenterTopAppBar(
title = {
Text(
textAlign = TextAlign.Center,
text = text,
)
},
编辑 分机代码
val Number.toPx
get() = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
this.toFloat(),
Resources.getSystem().displayMetrics
)
结果
这取决于应用栏中的内容。
如果你只有标题,那么你可以这样做:
topBar = {
TopAppBar(content = {
Text(
modifier = Modifier.fillMaxWidth(),
text = "Title Text",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.h6,
)
})
},
如果你的两边都有一个图标,你应该可以做同样的事情,如果一边有两个图标,另一边有两个图标,那么可能需要调整一些东西,然后可能想要使用添加相同大小的图标来均匀地放置东西out 并将 enabled 设置为 false,使其不可点击,颜色设置为透明,因此看不到,否则您可以尝试计算大小并在文本末尾添加填充,看来您还需要添加 16.dp 填充透明图标,因为导航图标在标题之前有额外的填充,但在标题和操作之间没有填充
这是我为箭头图标和标题所做的
topBar = {
TopAppBar(
navigationIcon = {
IconButton(
onClick = {
navController.popBackStack()
}
) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "back arrow icon"
)
}
},
title = {
Text(
modifier = Modifier
.fillMaxWidth(),
text = "Basic Navigation",
textAlign = TextAlign.Center,
)
},
actions = {
IconButton(
modifier = Modifier
.padding(start = 16.dp),
enabled = false,
onClick = {}
) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "back arrow icon",
tint = Color.Transparent
)
}
}
)
}
如果您使用的是 Material3,您也可以使用 CenterAlignedTopAppBar
。
fun CenterAlignedTopAppBar(
title: @Composable () -> Unit,
modifier: Modifier = Modifier,
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(),
scrollBehavior: TopAppBarScrollBehavior? = null
) {
SingleRowTopAppBar(
modifier = modifier,
title = title,
titleTextStyle =
MaterialTheme.typography.fromToken(TopAppBarSmallTokens.HeadlineFont),
centeredTitle = true,
navigationIcon = navigationIcon,
actions = actions,
colors = colors,
scrollBehavior = scrollBehavior
)
}
我只是 Jetpack Compose 的初学者,在寻找该问题的解决方案之前,我尝试自己想办法,也许对某些人来说就足够了。我需要 TopAppBar 的居中标题,只有左侧有导航图标,或者左右有两个图标,这个解决方案对我来说没问题。后来我配置了是否在右侧包含传递的图标。
TopAppBar(
backgroundColor = Color.Green,
elevation = 5.dp,
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
// size of an icon and placeholder box on the right side
val iconSize = 32.dp
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "Arrow Back",
modifier = Modifier
.clickable {
navController.popBackStack()
}
.size(iconSize)
)
Text(text = "Centered Title", fontSize = 32.sp)
// placeholder on the right side in order to have centered title - might be replaced with icon
Box(
modifier = Modifier
.size(iconSize)
) { }
}
我无法附上截图,预览在这里:https://i.stack.imgur.com/UNQTF.png