I have a problem with adding subtitle to the TopAppBar Composable. I am trying to implement LargeTopAppBar from Material Design 3, but with extra subtitle on it. The issue I am currently facing is that it renders twice. Below is my Composable:
#Composable
private fun HomeTopBar(
modifier: Modifier = Modifier,
title: String,
subtitle: String,
navigateToProfileScreen: () -> Unit,
navigateToAboutScreen: () -> Unit
) {
LargeTopAppBar(
modifier = modifier,
title = {
Column {
Text(
text = title,
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.onSurface
)
Text(
text = subtitle,
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
},
actions = {
NavigationDropDownMenu(
navigateToProfileScreen = navigateToProfileScreen,
navigateToAboutScreen = navigateToAboutScreen
)
},
)
}
For some reason it renders twice. I think that this problem is related to the fact that this top app bar has 2 modes (pinned and expanded).
Visual preview:
Here is preview of my composable function to highlight the problem:
Dependencies I used in the project:
implementation 'androidx.compose.material3:material3:1.0.0-beta01'
compose_version = '1.3.0-beta01'
You have to remove the color attribute inside the Text elements in the title and subtitle.
Text(
text = title,
style = MaterialTheme.typography.headlineMedium,
//color = MaterialTheme.colorScheme.onSurface
)
Currently you can only define the same color for both Text using the colors attribute in the LargeTopAppBar :
LargeTopAppBar(
colors = TopAppBarDefaults.largeTopAppBarColors(
titleContentColor=MaterialTheme.colorScheme.onSurface
),
//...
)
Finally use only M3 components (androidx.compose.material3.*) in the LargeTopAppBar, not M2 (androidx.compose.material.*) components.
.
Related
I would like to use the TabRow, but when I click the background has a ripple effect that I do not want. Is there a way to change this? I have the Tab's selectedContectColor equal to the same background color of the page, but I still see a white ripple effect.
TabRow(
modifier = Modifier.height(20.dp),
selectedTabIndex = selectedIndex,
indicator = { tabPositions ->
TabRowDefaults.Indicator(
modifier = Modifier.customTabIndicatorOffset(
currentTabPosition = tabPositions[lazyListState.firstVisibleItemIndex]
tabWidths[lazyListState.firstVisibleItemIndex]
),
color = RED
)
},
backgroundColor = BLACK
) {
tabList.forEachIndexed{ index, tab ->
val selected = (selectedIndex == index)
Tab(
modifier = Modifier
// Have tried different solutions here where there is a .clickable
// and the indication = null, and set interactionSource = remember{
//MutableInteractionSource()}
selected = selected,
selectedContentColor = BLACK,
onClick = {
animateScrollToItem(selectedIndex)
},
text = {
Text("Text Code")
}
)
}
}
You can see in these docs that the selectedContentColor affects the ripple
The ripple is implemented in a selectable modifier defined inside the Tab.
You can't disable it but you can change the appearance of the ripple that is based on a RippleTheme. You can define a custom RippleTheme and apply to your composable with the LocalRippleTheme.
CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) {
//..TabRow()
}
private object NoRippleTheme : RippleTheme {
#Composable
override fun defaultColor() = Color.Unspecified
#Composable
override fun rippleAlpha(): RippleAlpha = RippleAlpha(0.0f,0.0f,0.0f,0.0f)
}
The shimmer effect is handled by the indication property.
Put it inside the clickable section.
You can create an extension function
inline fun Modifier.noRippleClickable(crossinline onClick: ()->Unit): Modifier = composed {
clickable(indication = null,
interactionSource = remember { MutableInteractionSource() }) {
onClick()
}
}
then simply replace Modifier.clickable {} with Modifier.noRippleClickable {}
I built a composable which is basically a Row containing an address as Text and a Button alongside it. The address contains a label within it (e.g. 'Bill To: ') and to format it slightly differently I am using the buildAnnotatedString function.
This is pretty straightforward, but I am noticing an issue when during the first run, the address Text takes the colour assigned to the Button composable. I have verified this by changing the Button colour, and each time the result is the same on the first run. On subsequent runs, the composable behaves as expected, i.e. the Text is rendered as black as specified in the text-style. Can anyone please explain why this happens or let me know if this should be logged as an issue with the Jetpack Compose team?
Screenshot from the emulator of the first run (reproduced on physical Redmi devices as well):
Screenshot representing subsequent runs and the expected behaviour:
My Composable function:
#Composable
fun CheckoutAddress(
modifier: Modifier = Modifier,
addressLabel: String,
address: String?,
onChangeClick: () -> Unit
) {
val separator = ": "
val addressText = buildAnnotatedString {
appendMedium(addressLabel)
appendMedium(separator)
addStyle(
SpanStyle(
fontSize = MaterialTheme.typography.body1.fontSize
),
start = 0,
end = "$addressLabel$separator".length - 1
)
if(address.isNullOrBlank()) {
appendColored(stringResource(id = R.string.label_not_set), color = MaterialTheme.colors.error)
} else {
append(address)
}
}
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier
.weight(1f)
.padding(end = CONTENT_TO_BUTTON_PADDING.dp),
text = addressText,
style = MaterialTheme.typography.body2,
maxLines = 4,
overflow = TextOverflow.Ellipsis
)
ChangeButton(
onClick = onChangeClick
)
}
}
The ChangeButton composable (The R.colors.default_blue colour specified within this composable's scope is taken up by the annotated string Text, have changed its value and verified) :
#Composable
fun ChangeButton(
modifier: Modifier = Modifier,
onClick: () -> Unit
) {
TextButton(
modifier = modifier,
onClick = onClick,
colors = ButtonDefaults.textButtonColors(contentColor = colorResource(id = R.color.defaultBlue))
) {
Text(
text = stringResource(id = R.string.label_change_button).uppercase()
)
}
}
The Annotated String helper methods used above:
fun AnnotatedString.Builder.appendMedium(text: String) {
append(AnnotatedString(text, SpanStyle(fontWeight = FontWeight.Medium)))
}
fun AnnotatedString.Builder.appendColored(text: String, color: androidx.compose.ui.graphics.Color) {
append(AnnotatedString(
text,
SpanStyle(color = color)
))
}
Is it possible to adjust the tonalElevation (but not the shadowElevation) of Material Design 3 components?
It looks as though it's only possible to adjust both. Below is the implementation of a Floating Action Button in Material Design 3. The same problem exists with other components.
#Composable
fun FloatingActionButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = FabPrimaryTokens.ContainerShape,
containerColor: Color = FabPrimaryTokens.ContainerColor.toColor(),
contentColor: Color = contentColorFor(containerColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
content: #Composable () -> Unit,
) {
Surface(
onClick = onClick,
modifier = modifier,
shape = shape,
color = containerColor,
contentColor = contentColor,
tonalElevation = elevation.tonalElevation(interactionSource = interactionSource).value,
shadowElevation = elevation.shadowElevation(interactionSource = interactionSource).value,
interactionSource = interactionSource,
) {
CompositionLocalProvider(LocalContentColor provides contentColor) {
// Adding the text style from [ExtendedFloatingActionButton] to all FAB variations. In
// the majority of cases this will have no impact, because icons are expected, but if a
// developer decides to put some short text to emulate an icon, (like "?") then it will
// have the correct styling.
ProvideTextStyle(
MaterialTheme.typography.fromToken(ExtendedFabPrimaryTokens.LabelTextFont),
) {
Box(
modifier = Modifier
.defaultMinSize(
minWidth = FabPrimaryTokens.ContainerWidth,
minHeight = FabPrimaryTokens.ContainerHeight,
),
contentAlignment = Alignment.Center,
) { content() }
}
}
}
}
There's an extension function on a ColorScheme class, that converts an Elevation into a Color: surfaceColorAtElevation().
TextField(
...
colors = TextFieldDefaults.textFieldColors(
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)
)
)
Also, there are six different Elevation levels in Material 3 (https://m3.material.io/styles/elevation/tokens):
Level 0: 0dp
Level 1: 1dp
Level 2: 3dp
Level 3: 6dp
Level 4: 8dp
Level 5: 12dp
So i am working with an app in jetpack compose and i see this tutorial Tutorial. This tutorial builds a default snackbar within a snackbarhost and adds a text to this snackbar in the way below. Though when i try to add this parameter it tells me that it doesn't exist. Why is this is the parameter deprecated and if so what did it get exchanged with? Plus i have the question of how to clear the que in the snackbarhost quz when i click more then once i first get myh last message and then the one i should get?
Snackbar(
modifier = Modifier.padding(16.dp),
text = {
Text(
text = data.message,
style = MaterialTheme.typography.body2,
color = Color.White
)
},
action = {
data.actionLabel?.let { actionLabel ->
TextButton(
onClick = {
onDismiss()
}
) {
Text(
text = actionLabel,
style = MaterialTheme.typography.body2,
color = Color.White
)
}
}
}
)
I'm assume your talking about this line:
Snackbar(
modifier = Modifier.padding(16.dp),
text = { // <--
I found a usage example on the Compose Playground here: https://foso.github.io/Jetpack-Compose-Playground/material/snackbar/ (the page also contains a link to the reference of Snackbar)
From what I can see, they probably replaced the text arg with the content of the Snackbar, which would result in something similar to this:
Snackbar(
modifier = ... same as before ...,
action = ... same as before ...
) {
// Move the text element here
Text(...)
}
I have a simple Jetpack Compose TabRow example on Kotlin from documentation, where I just changed a text and underline color. But there is an orange background color when the tab is pressed. I want to make it transparent.
var state by remember { mutableStateOf(0) }
val titles = listOf("TOP", "NEW", "HOT")
Column {
TabRow(
contentColor = MaterialTheme.colors.primaryVariant, // This is underline's color
selectedTabIndex = state
) {
titles.forEachIndexed { index, title ->
Tab(
selectedContentColor = MaterialTheme.colors.primaryVariant,
unselectedContentColor = MaterialTheme.colors.secondary,
text = { Text(title) },
selected = state == index,
onClick = { state = index }
)
}
}
Text(
modifier = Modifier.align(Alignment.CenterHorizontally),
text = "Text tab ${state + 1} selected",
style = MaterialTheme.typography.body1
)
}
Right now, you can set backgroundColor for tabs like this:
TabRow(
selectedTabIndex = state,
...
backgroundColor = Color.White
)
If by pressed color, you are referring to this tab,
This is created by the Tab's ripple color.
This color would be affected by the selectedContentColor attribute in Tab.
But, even if you specify Transparent you would see a greyish ripple effect.
Modify the attribute to match with the closes satisfiable color as required.
The code creating the ripple effect.
// The color of the Ripple should always the selected color, as we want to show the color
// before the item is considered selected, and hence before the new contentColor is
// provided by TabTransition.
val ripple = rememberRipple(bounded = true, color = selectedContentColor)
As this is an internal implementation detail, we cannot disable it. ()