I want to set the "Account" text to the center of TopAppBar and add an icon to the right of TopAppBar, how can I do it?
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopAppBar(
title = {
Text(
text = stringResource(R.string.account),
style = AppFont.PoppinsTypography.subtitle1
)
},
navigationIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_left),
contentDescription = "back", tint = AppColor.brandColor.BLUE_DE_FRANCE
)
}, actions = {
viewModel.navigateUp()
}, backgroundColor = AppColor.neutralColor.DOCTOR
)
},
)
To align the title text to the center of TopAppbar,
Update
Using Material 3
CenterAlignedTopAppBar(
title = {
Text(
text = stringResource(R.string.account),
style = AppFont.PoppinsTypography.subtitle1
)
},
)
And actions attribute should have the compoosables to add at the end. Use that to add an icon to the right of TopAppBar.
Example,
actions = {
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = Icons.Rounded.ShoppingCart,
contentDescription = "cart",
)
}
},
The old answer, using Material 2
Change title to this,
title = {
Text(
text = stringResource(R.string.account),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(),
style = AppFont.PoppinsTypography.subtitle1
)
},
You could just implement a custom layout
#Composable
fun TopBar() {
Scaffold(
topBar = {
Layout(
modifier = Modifier.fillMaxHeight(0.1f), //Fills one-tenth of the screen
content = {
Text("Account")
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "back",
tint = Color.Blue,
)
}
) { measurables, constraints ->
val title = measurables[0].measure(constraints)
val navigationIcon = measurables[1].measure(constraints)
layout(constraints.maxWidth, constraints.maxHeight) {
title.place(
(constraints.maxWidth - title.width) / 2, //Midway
constraints.maxHeight / 2 // Usually Texts acquire maxHeight so we did not need t subtract
)
navigationIcon.place(
(constraints.maxWidth - 1.5 * navigationIcon.width).roundToInt(), //1.5 to add a bit of extra padding from the edge
(constraints.maxHeight - navigationIcon.height) / 2
)
}
}
},
) {
}
}
Related
Hi, I need help. How to make drop down menu like on photos? Is there any easy way?
You can use the standard ExposedDropdownMenuBox provided by M3.
Something like:
val options = listOf("Option 1", "Option 2", "Option 3", "Option 4", "Option 5")
var expanded by remember { mutableStateOf(false) }
var selectedOptionText by remember { mutableStateOf(options[0]) }
val shape = if (expanded) RoundedCornerShape(8.dp).copy(bottomEnd = CornerSize(0.dp), bottomStart = CornerSize(0.dp))
else RoundedCornerShape(8.dp)
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded },
) {
TextField(
modifier = Modifier.menuAnchor(),
textStyle = TextStyle.Default.copy(
fontSize = 14.sp,
fontWeight= FontWeight.Light),
readOnly = true,
value = selectedOptionText,
onValueChange = {},
label = { Text("Unit of length", fontWeight = FontWeight.Bold, ) },
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
shape = shape,
colors = ExposedDropdownMenuDefaults.textFieldColors(
focusedIndicatorColor = Transparent,
unfocusedIndicatorColor = Transparent
)
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
) {
options.forEach { selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
onClick = {
selectedOptionText = selectionOption
expanded = false
},
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
)
}
}
}
I am working with MediumTopAppBar, and i am trying to change the textStyle of the big Title without ruining the small title.
So what i am doing is:
MediumTopAppBar(
title = { HeadlineLargeBlackText(text = "pageTitle") },
navigationIcon = {
IconButton(onClick = { onBackPressed.invoke() }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.action_back)
)
}
},
scrollBehavior = scrollBehavior
)
My problem is that when i set it to "HeadlineLargeBlackText" it automatically change the textstyle of both the big and the small text so it looks like this (image taken with both big and small text visible):
What i want is for the bottom to be big, and the top to be small.
When i go into the MediumTopAppBar i do see that the textStyle of the big and the small is set in the TwoRowsTopAppBar as:
titleTextStyle = MaterialTheme.typography.fromToken(TopAppBarMediumTokens.HeadlineFont),
smallTitleTextStyle = MaterialTheme.typography.fromToken(TopAppBarSmallTokens.HeadlineFont),
But ofc that method is private :// So i wonder, is it possible to get access to these big/small texts separately somehow?
Currently the MediumTopAppBar uses the titleLarge and headlineSmall textstyles defined with the typography attribute in your theme.
You can define them in the theme with:
val customTypography = androidx.compose.material3.Typography(
titleLarge = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 22. sp,
lineHeight = 28. sp,
letterSpacing = 0. sp
),
headlineSmall = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 16. sp,
lineHeight = 24. sp,
letterSpacing = 0.15.sp
),
)
If you don't wont to apply them to the whole app, you can apply a custom theme only to the MediumTopAppBar with something like:
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
AppTheme {
MediumTopAppBar(
title = {
androidx.compose.material3.Text(
"Medium TopAppBar",
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
},
//....
)
},
//....
}
where
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: #Composable() () -> Unit
) {
//...
aMaterialTheme(
colorScheme = colors,
typography = customTypography,
content = content
)
}
How do I separate text and icon in TextButton to make it like whatsapp settings
Row(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
) {
TextButton(
onClick = { /*TODO*/ },
modifier = Modifier.fillMaxSize(),
) {
Text(text = "$name")
Icon(
imageVector = Icons.Filled.KeyboardArrowRight,
contentDescription = "",
modifier = Modifier.size(40.dp)
)
}
}
It shows
But I want to like this
I try Spacer and Padding but it didn't work because I have
fun SettingsButtons(name: String)
#Composable
fun SettingsButtons(name: String) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
) {
TextButton(
onClick = { /*TODO*/ },
modifier = Modifier.fillMaxSize(),
) {
Text(text = "$name")
Icon(
imageVector = Icons.Filled.KeyboardArrowRight,
contentDescription = "",
modifier = Modifier.size(40.dp)
)
}
}
}
And based on the parameter that I passed {name} the text will be changed
SettingsButtons(name = "Account")
SettingsButtons(name = "Order History")
SettingsButtons(name = "Favorite")
so I think that why Spacer and Padding didn't work because the text size is different or I am not using it correctly
The content of a TextButton is a RowScope.
You can apply a weight(1f) modifier to the Text
TextButton(
onClick = { /*TODO*/ },
modifier = Modifier.fillMaxWidth(),
) {
Text(text = "Name", modifier = Modifier.weight(1f))
Icon(
imageVector = Icons.Filled.KeyboardArrowRight,
contentDescription = "",
modifier = Modifier.size(40.dp)
)
}
Try RaisedButton with a Row as Child and in Row add Text and Icon widget
RaisedButton(
onPressed: () {},
child: Row(
children: <Widget>[
Text(
'Button'),
Icon(
Icons.arrow_forward,
color: Colors.white,
))
I think what you are looking for is Arrangement. You could try to use Arrangement like this:
Row(modifier = Modifier.fillMaxWidth().height(50.dp)) {
TextButton(
onClick = { /*TODO*/ },
modifier = Modifier.fillMaxWidth(),
Arrangement.SpaceBetween
) {
Text(text = "$name")
Icon(
imageVector = Icons.Filled.KeyboardArrowRight,
contentDescription = "",
modifier = Modifier.size(40.dp)
)
}
}
I found this question which is quite similiar to your problem but in a vertical direction:
Filling remaining space with Spacer on Jetpack Compose
Further I will link you the documentation where you can find more info about alignment and arrangement in jetpack compose.
https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/Arrangement
I'm trying to center the icon and trailing elements vertically using a ListItem. I'm not sure if it is possible or I need to drop the ListItem and use a combination of column/row instead.
I'm using something like:
ListItem(
Modifier.clickable(onClick = onClick),
icon = {
Box(
modifier = Modifier.fillMaxHeight(), contentAlignment = ALignment.Center
) {
Text(
text = dateUtil.formatTime(item.startTime),
style = TextStyle(
color = SnyDarkBlue,
fontSize = 14.sp,
fontFamily = oswaldFamily,
fontWeight = FontWeight.Bold,
letterSpacing = (-0.25).sp,
),
)
}
},
thanks in advance!
You can center both the icon and text sections using a Column:
ListItem(
modifier = Modifier
.fillMaxWidth()
.requiredHeight(50.dp)
.background(color = Color.Gray),
icon = {
Column(
modifier = Modifier
.fillMaxHeight(), verticalArrangement = Arrangement.Center
) {
Text(
text = "06:00 PM"
)
}
},
text = {
Column(
modifier = Modifier
.fillMaxHeight(), verticalArrangement = Arrangement.Center
) {
Text("Your item text goes here")
}
},
)
How to properly center an icon in ListItem?
Column {
ListItem(
icon = {
Icon(
imageVector = Icons.Outlined.Delete,
contentDescription = null
)
},
secondaryText = { Text("secondaryText") },
text = { Text("text") }
)
Divider()
}
gives this result
ListItem implementation uses explicit Box(contentAlignment = Alignment.TopStart) to place the icon. Mmm...why?
I can, of course, use paddings or create a custom ListItem, but there must be a standard solution.
According to M2 specs, you can add the Modifier.size(40.dp) to the Icon
Something like:
ListItem(
text = { Text("Two line list item with 40x40 icon") },
secondaryText = { Text("Secondary text") },
icon = {
Icon(
Icons.Filled.Favorite,
contentDescription = null,
modifier = Modifier.size(40.dp)
)
}
)
The ListItem follows the material guidelines:
With M3 it is not needed since the leadingContent has a default contentAlignment = Alignment.Center:
Column {
ListItem(
leadingContent = {
Icon(
imageVector = Icons.Outlined.Delete,
contentDescription = null
)
},
supportingText = { Text("Supporting Text") },
headlineText = { Text("Headline Text") }
)
Divider()
}
Specs: