Skip to content

Instantly share code, notes, and snippets.

@aitsuki
Last active October 5, 2021 22:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aitsuki/0dd87c0f661e1e85c2af6a6d09333ba5 to your computer and use it in GitHub Desktop.
Save aitsuki/0dd87c0f661e1e85c2af6a6d09333ba5 to your computer and use it in GitHub Desktop.
Android Jetpack Compose 标题居中的 TopAppBar
package com.aitsuki.wanandroid.widget
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.aitsuki.wanandroid.ui.theme.WanandroidTheme
private val AppBarHeight = 56.dp
private val AppBarHorizontalPadding = 4.dp
private val ContentPadding = PaddingValues(
start = AppBarHorizontalPadding,
end = AppBarHorizontalPadding
)
@Composable
fun CenterTopAppBar(
modifier: Modifier = Modifier,
backgroundColor: Color = MaterialTheme.colors.primarySurface,
contentColor: Color = contentColorFor(backgroundColor),
elevation: Dp = AppBarDefaults.TopAppBarElevation,
contentPadding: PaddingValues = ContentPadding,
navController: NavController? = null,
leading: @Composable (RowScope.() -> Unit)? = null,
trailing: @Composable (RowScope.() -> Unit)? = null,
title: @Composable () -> Unit,
) {
Surface(
color = backgroundColor,
contentColor = contentColor,
elevation = elevation,
modifier = modifier
) {
var leftSectionWidth = 0.dp
var rightSectionWidth = 0.dp
var titlePadding by remember { mutableStateOf(PaddingValues()) }
val calculateTitlePadding = fun() {
val dx = leftSectionWidth - rightSectionWidth
var start = 0.dp
var end = 0.dp
if (dx < 0.dp) start += dx else end += dx
titlePadding = PaddingValues(start = start, end = end)
}
Row(
Modifier
.fillMaxWidth()
.padding(contentPadding)
.height(AppBarHeight),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
// leading
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
with(LocalDensity.current) {
Row(
Modifier
.fillMaxHeight()
.onGloballyPositioned { coordinates ->
val width = coordinates.size.width.toDp()
if (width != leftSectionWidth) {
leftSectionWidth = width
calculateTitlePadding()
}
},
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically,
content = leading ?: {
val previous = navController?.previousBackStackEntry
if (previous != null) {
IconButton(onClick = { navController.popBackStack() }) {
Icon(Icons.Filled.ArrowBack, null)
}
}
}
)
}
}
// title
Row(
Modifier
.fillMaxHeight()
.weight(1f)
.padding(titlePadding),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
ProvideTextStyle(value = MaterialTheme.typography.h6) {
CompositionLocalProvider(
LocalContentAlpha provides ContentAlpha.high,
content = title
)
}
}
// trailing
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
with(LocalDensity.current) {
Row(
Modifier
.fillMaxHeight()
.onGloballyPositioned { coordinates ->
val width = coordinates.size.width.toDp()
if (width != rightSectionWidth) {
rightSectionWidth = width
calculateTitlePadding()
}
},
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
content = trailing ?: {}
)
}
}
}
}
}
@Preview
@Composable
private fun DefaultPreview() {
WanandroidTheme {
CenterTopAppBar(
leading = {
IconButton(onClick = { }) {
Icon(Icons.Filled.ArrowBack, null)
}
}
) {
Text("TitleBar Center")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment