Compose rounded Button with transparent background - android

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.

Related

Surface contentColor does not apply transparency to contentColor

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?

How to change the color of ripple effect of a Button

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
}
}

Jetpack compose button with elevation and disable state weird behaviour

I created custom button and when I apply elevation with disable state it has because of shadow some small box in middle and it looks like this. Here is also my code:
#Composable
fun PrimaryButton(
modifier: Modifier = Modifier,
enabled: Boolean = false,
text: String,
onClick: () -> Unit,
) {
Button(
onClick = onClick,
Modifier
.height(44.dp)
.shadow(
elevation = 4.dp,
shape = RoundedCornerShape(22.dp),
)
.then(modifier),
colors = ButtonDefaults.buttonColors(
backgroundColor = Style.colors.buttonPrimary,
disabledBackgroundColor = Style.colors.buttonPrimary.copy(0.4f),
),
shape = RoundedCornerShape(22.dp),
enabled = enabled,
) {
Text(
text = text,
style = Style.typography.phoenixTitle,
color = Color.White
)
}
}
fun ButtonSelectedCount(
modifier: Modifier = Modifier,
text: String,
enable: Boolean,
onClick: () -> Unit
) {
Surface(
shape = RoundedCornerShape(8.dp),
modifier = modifier,
elevation = if (enable) 9.dp else 0.dp
) {
Text(
modifier = Modifier
.fillMaxSize()
.background(color = if (enable) Color.Red else Color.Red.copy(alpha = 0.1f))
.clickable(enable) {
onClick()
}
.wrapContentHeight(),
text = text,
style = Typography.button.copy(color = Color.White),
textAlign = TextAlign.Center
)
}
}
I Think, This is what you are looking for. Wish you early success

Transparent background in Outlined Button in Jetpack Compose

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
)
}

Gradient backround for FAB in Jetpack compose

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.

Categories

Resources