I want to create button where I have only text and icon and all background and borders are transparent. I create something like that:
OutlinedButton(
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Transparent),
border = BorderStroke(0.dp, Color.Transparent),
modifier = modifier,
onClick = onClick
) {
icon?.invoke()
Text(
text = value,
fontSize = 12.sp
)
}
and everything is ok, but I lost default colors(should be blue, and I have black icon and text). How can I remove all background and borders from button but still have theme colors?
Could you try this?
#Composable
fun TiledButton(
onClick: () -> Unit,
#DrawableRes backgroundDrawableId: Int,
modifier: Modifier = Modifier,
enabled: Boolean = true,
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
contentColor: Color = MaterialTheme.colors.primary,
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: #Composable RowScope.() -> Unit
) {
Button(
onClick = onClick,
contentPadding = PaddingValues(0.dp),
enabled = enabled,
shape = shape,
border = border,
elevation = null,
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Transparent,
contentColor = contentColor,
disabledBackgroundColor = Color.Transparent,
disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
),
modifier = modifier
) {
Box(
contentAlignment = Alignment.Center,
) {
TileAndroidImage(
drawableId = backgroundDrawableId,
contentDescription = "...",
modifier = Modifier.matchParentSize()
)
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(contentPadding),
content = content,
)
}
}
}
TiledButton(
onClick = { },
backgroundDrawableId = R.drawable.tile,
border = BorderStroke(1.dp, Color.Blue),
) {
Text("Button")
}
Just use a TextButton instead of a OutlinedButton:
TextButton(
onClick = { }
) {
Icon(Icons.Default.Add,"")
Text(
text = value,
fontSize = 12.sp
)
}
If you want to use a OutlinedButton just use ButtonDefaults.outlinedButtonColors instead of ButtonDefaults.buttonColors:
OutlinedButton(
colors = ButtonDefaults.outlinedButtonColors(backgroundColor = Color.Transparent),
border = BorderStroke(0.dp, Color.Transparent),
modifier = modifier,
onClick = onClick
) {
Icon(Icons.Default.Add,"")
Text(
text = value,
fontSize = 12.sp
)
}
Related
I've created similarly to Material Button, custom Button, but the problem is that I cannot get the colors with their transparency.
CustomButton
#OptIn(ExperimentalMaterialApi::class)
#Composable
fun CustomButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = Theme.shapes.rectangle,
border: BorderStroke? = null,
enabled: Boolean = true,
contentColor: Color = Theme.colors.foregroundOpacityMax,
backgroundColor: Color = Theme.colors.background00,
contentPadding: PaddingValues = PaddingValues(all = Theme.spacing.default),
textStyle: TextStyle = Theme.typography.button,
minWidth: Dp = 200.dp,
minHeight: Dp = 30.dp,
content: #Composable RowScope.() -> Unit,
) {
Surface(
onClick = onClick,
modifier = modifier,
shape = shape,
enabled = enabled,
color = backgroundColor,
contentColor = contentColor,
border = border,
interactionSource = interactionSource,
) {
ProvideTextStyle(
value = textStyle
) {
Row(
modifier = Modifier
.defaultMinSize(
minWidth = minWidth,
minHeight = minHeight
)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
}
}
}
The colors are displayed correctly, but they are not transparent. How to achieve the transparency?
For some reason, I'm unable to change the color of the ripple effect of a Button. What am I doing wrong here?
androidx.compose.material.Button(
onClick = onClick,
modifier = modifier
.indication(
interactionSource = interactionSource,
indication = rememberRipple(color = Color.Red)
)
.navigationBarsPadding(),
enabled = enabled,
interactionSource = interactionSource,
elevation = elevation,
shape = RectangleShape,
colors = ButtonDefaults.bottomColors(),
contentPadding = PaddingValues(vertical = 4.dp),
content = { Text(text) },
)
Button is derived from this Surface which has its own indication with rememberRipple(). Since Button is as Surface, you can implement clickable with any other Composable that resembles Button
#Composable
fun Button(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
elevation: ButtonElevation? = ButtonDefaults.elevation(),
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
colors: ButtonColors = ButtonDefaults.buttonColors(),
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: #Composable RowScope.() -> Unit
) {
val contentColor by colors.contentColor(enabled)
Surface(
onClick = onClick,
modifier = modifier,
enabled = enabled,
shape = shape,
color = colors.backgroundColor(enabled).value,
contentColor = contentColor.copy(alpha = 1f),
border = border,
elevation = elevation?.elevation(enabled, interactionSource)?.value ?: 0.dp,
interactionSource = interactionSource,
) {
CompositionLocalProvider(LocalContentAlpha provides contentColor.alpha) {
ProvideTextStyle(
value = MaterialTheme.typography.button
) {
Row(
Modifier
.defaultMinSize(
minWidth = ButtonDefaults.MinWidth,
minHeight = ButtonDefaults.MinHeight
)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
}
}
}
}
#Composable
fun Surface(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
shape: Shape = RectangleShape,
color: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(color),
border: BorderStroke? = null,
elevation: Dp = 0.dp,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: #Composable () -> Unit
) {
val absoluteElevation = LocalAbsoluteElevation.current + elevation
CompositionLocalProvider(
LocalContentColor provides contentColor,
LocalAbsoluteElevation provides absoluteElevation
) {
Box(
modifier = modifier
.minimumTouchTargetSize()
.surface(
shape = shape,
backgroundColor = surfaceColorAtElevation(
color = color,
elevationOverlay = LocalElevationOverlay.current,
absoluteElevation = absoluteElevation
),
border = border,
elevation = elevation
)
.clickable(
interactionSource = interactionSource,
indication = rememberRipple(),
enabled = enabled,
role = Role.Button,
onClick = onClick
),
propagateMinConstraints = true
) {
content()
}
}
}
Your code doesn't work because the ripple is implemented in the clickable modifier defined inside the Button.
However you can change the appearance of the ripple defining a custom RippleTheme and applying it to your composable with the LocalRippleTheme.
Something like:
private object RedRippleTheme: RippleTheme {
#Composable
override fun defaultColor() =
RippleTheme.defaultRippleColor(
Color.Red,
lightTheme = true
)
#Composable
override fun rippleAlpha(): RippleAlpha =
RippleTheme.defaultRippleAlpha(
Color.Black,
lightTheme = true
)
}
and:
CompositionLocalProvider(LocalRippleTheme provides RedRippleTheme) {
Button(
//....
){
//Button content
}
}
I am trying to make a navigation bar but with the same look and color as my activity, using Jetpack Compose.
Below is the UI I want
I tried using TopAppBar but I am unable to get the same look and field, it looks like as below
Below is the code
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Surface(
modifier = Modifier
.fillMaxSize()
) {
MainView(logOut = signOut)
}
}
}
#Composable
fun NavigationBar(onIconClicked : () -> Unit,text: String){
TopAppBar(
title = {
Text(
text = text,
color = Color.Black,
fontSize = 48.sp
)
},
navigationIcon = {
Icon(
imageVector = Icons.Default.Close,
contentDescription = "Close",
modifier = Modifier.clickable(onClick = onIconClicked),
tint = Color.Black
)
},
// backgroundColor = /*...*/
)
}
#Composable
fun MainView(logOut: (doLogout: Boolean) -> Unit) {
Column(
Modifier
.background(colorResource(id = R.color.theme_light_blue))
.padding(40.dp, 0.dp)
.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(45.dp)
) {
NavigationBar(onIconClicked = { /*TODO*/ }, text = "settings")
Box(
Modifier
.fillMaxWidth()
) {
Text(
modifier = Modifier.align(Alignment.CenterStart),
text = "current user",
style = TextStyle(
colorResource(id = R.color.black),
fontSize = 32.sp
)
)
ClickableText(
modifier = Modifier.align(Alignment.CenterEnd),
style = TextStyle(
colorResource(id = R.color.black),
fontSize = 32.sp,
textAlign = TextAlign.End,
fontWeight = FontWeight.Bold
),
text = AnnotatedString("SIGN OUT"),
onClick = { logOut(true) }
)
}
var text by rememberSaveable { mutableStateOf("Text") }
Column(
Modifier
.fillMaxWidth()
.background(colorResource(id = R.color.theme_dark_blue))
) {
TextField(
value = text,
onValueChange = {
text = it
},
textStyle = TextStyle(
fontSize = 20.sp,
),
modifier = Modifier.fillMaxWidth(),
maxLines = 1,
singleLine = true,
colors = TextFieldDefaults.textFieldColors(
textColor = Color.Black,
backgroundColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
),
)
}
}
I know I can simply add a Row above the MainView which contains the icon and a text field but is that a right way to achieve it or can we do something with TopAppBar
The following changes would get you the desired result.
In TopAppBar add the following attributes
backgroundColor = colorResource(id = R.color.theme_light_blue),
elevation = 0.dp,
modifier = Modifier.fillMaxWidth(),
As answered by #Abhimanyu adding backgroundColor worked but it was showing a darker shade which did not match the UI.
Below is a little tweak that worked.
In TopAppBar
backgroundColor = colorResource(id = R.color.theme_light_blue).copy(alpha = 0f),
elevation = 0.dp,
modifier = Modifier.fillMaxWidth()
I am trying to display a Button with rounded corners and a 50% transparent background. My current attempt looks like this:
MaterialTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.Yellow
) {
Column(modifier = Modifier.padding(10.dp)) {
Button(
modifier = Modifier
.clip(CircleShape),
onClick = { },
colors = ButtonDefaults.buttonColors(backgroundColor = Color.White.copy(alpha = 0.5f))
) {
Text(
text = "My Button",
textAlign = TextAlign.Center
)
}
}
}
}
The result is not very pretty:
It looks like the issue is with with the shading, but I'm not sure how to remove it and just show the same color within the whole shape.
Turns out the shadow will disappear when the elevation is removed.
Button(
modifier = Modifier
.clip(CircleShape),
onClick = { },
elevation = null,
colors = ButtonDefaults.buttonColors(backgroundColor = Color.White.copy(alpha = 0.5f))
) { ... }
Button is just a Surface wrapping the content that you provide. You could check the source. So, I just tweaked it a little
#Composable
fun HollowButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
elevation: ButtonElevation? = ButtonDefaults.elevation(),
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
colors: ButtonColors = ButtonDefaults.buttonColors(),
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: #Composable RowScope.() -> Unit
) {
val contentColor by colors.contentColor(enabled)
Surface(
modifier = modifier,
shape = shape,
color = colors.backgroundColor(enabled).value.copy(0.5f), //Basically I refactored the alpha modification to here
contentColor = contentColor.copy(alpha = 1f),
border = border,
elevation = elevation?.elevation(enabled, interactionSource)?.value ?: 0.dp,
onClick = onClick,
enabled = enabled,
role = Role.Button,
interactionSource = interactionSource,
indication = rememberRipple()
) {
CompositionLocalProvider(LocalContentAlpha provides contentColor.alpha) {
ProvideTextStyle(
value = MaterialTheme.typography.button
) {
Row(
Modifier
.defaultMinSize(
minWidth = ButtonDefaults.MinWidth,
minHeight = ButtonDefaults.MinHeight
)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
}
}
}
}
Works like a charm.
I want to add a Floating Action Button with a gradient background in Jetpack Compose. I have the following snippet to do so:
FloatingActionButton(
onClick = {
coroutineScope.safeLaunch {
navController.navigate("AddTodoPage") {
launchSingleTop = true
}
}
},
shape = RoundedCornerShape(14.dp),
backgroundColor = Color.Transparent,
modifier = Modifier
.constrainAs(addFab) {
bottom.linkTo(parent.bottom)
end.linkTo(parent.end)
}
.offset(x = (-16).dp, y = (-24).dp)
.background(
brush = Brush.verticalGradient(
colors = BluePinkGradient()
),
shape = RoundedCornerShape(14.dp)
)
) {
Icon(
painter = painterResource(id = R.drawable.ic_add),
contentDescription = "Add icon",
tint = Color.White
)
}
fun BluePinkGradient(inverse: Boolean = false) = when (inverse) {
true -> listOf(
MutedBlue,
MutedPink
)
false -> listOf(
MutedPink,
MutedBlue
)
}
val MutedBlue = Color(0xFF26A69A)
val MutedPink = Color(0xFFEC407A)
But from the image below, the button has a "Whitish" shade on the plus icon. How can I remove that shade or a better way to set the FAB background to a gradient?
Fab Image
'"Whitish" shade on the plus icon' is the result of elevation parameter. You can zero it, but it doesn't looks like you need FAB in the first place.
As you need to custom the button that much, you can use IconButton instead:
IconButton(
onClick = {
},
modifier = Modifier
.background(
brush = Brush.verticalGradient(
colors = BluePinkGradient()
),
shape = RoundedCornerShape(14.dp)
)
) {
Icon(
painter = painterResource(id = R.drawable.ic_undo),
contentDescription = "Add icon",
tint = Color.White
)
}
FloatingActionButton is only applying some Material defaults to the content, it doesn't make it really floating, it has to be done with the container.
I have developed the following solution, which I have confirmed as working:
#OptIn(ExperimentalMaterialApi::class)
#Composable
fun CrazyFloatingActionButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
gradient: List<Color>,
contentColor: Color = contentColorFor(gradient[0]),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
content: #Composable () -> Unit
) {
Surface(
modifier = modifier,
shape = shape,
contentColor = contentColor,
elevation = elevation.elevation(interactionSource).value,
onClick = onClick,
role = Role.Button,
interactionSource = interactionSource,
indication = rememberRipple()
) {
CompositionLocalProvider(LocalContentAlpha provides contentColor.alpha) {
ProvideTextStyle(MaterialTheme.typography.button) {
Box(
modifier = Modifier
.defaultMinSize(minWidth = 56.dp, minHeight = 56.dp)
.background(brush = Brush.verticalGradient(gradient)),
contentAlignment = Alignment.Center
) { content() }
}
}
}
}
Just prepend Crazy to your Composable and you should be good to go.