I am trying to remove padding from TextButton but it wont work.
TextButton(
onClick = {},
modifier = Modifier.padding(0.dp)
) {
Text(
" ${getString(R.string.terms_and_conditions)}",
color = MaterialTheme.colors.primary,
fontFamily = FontFamily(Font(R.font.poppins_regular)),
fontSize = 10.sp,
)
}
I have tried setting the height and size in Modifier property as well but the padding is still present
Wrap the TextButton with CompositionLocalProvider to override the value of LocalMinimumTouchTargetEnforcement. This will only remove the extra margin but will not modify the defaultMinSize which is hardcoded.
CompositionLocalProvider(
LocalMinimumTouchTargetEnforcement provides false,
) {
TextButton(
onClick = {},
contentPadding = PaddingValues(),
) {
Text(
"Button",
color = MaterialTheme.colors.primary,
fontSize = 10.sp,
)
}
}
You cannot reduce padding with the padding modifier: it always adds an extra padding on top of the existing padding. See this reply for more details about the order of modifiers.
You can reduce TextButton padding with contentPadding argument, by specifying PaddingValues(0.dp), but this will not fully remove the padding.
If you need fully remove the padding, you can use the clickable modifier instead:
Text(
"getString(R.string.terms_and_conditions",
color = MaterialTheme.colors.primary,
fontFamily = FontFamily(Font(R.font.neris_semi_bold)),
fontSize = 10.sp,
modifier = Modifier
.clickable {
// onClick()
}
)
If you want to change the color of the ripple, as is done in TextButton, you can do it as follows:
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(color = MaterialTheme.colors.primary),
) {
}
You can achieve it changing the contentPadding and applying a fixed size:
TextButton(
onClick = {},
contentPadding = PaddingValues(0.dp),
modifier = Modifier.height(20.dp).width(40.dp)
) {
Text(
"Button",
color = MaterialTheme.colors.primary,
fontSize = 10.sp,
)
}
If you come across unwanted margins. When you use onclick in any Button function, it sets propagateMinConstraints = true inside the view's surface - this will apply to unwanted margins. Example how solve this problem:
#Composable
fun ButtonWithoutOuterPadding(
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = RectangleShape,
elevation: Dp = 0.dp,
color: Color = Color.Transparent,
border: BorderStroke? = null,
contentAlignment: Alignment = Alignment.Center,
content: #Composable () -> Unit
) {
Box(
modifier
.shadow(elevation, shape, clip = false)
.then(if (border != null) Modifier.border(border, shape) else Modifier)
.background(
color = color,
shape = shape
)
.clip(shape)
.then(
Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = LocalIndication.current,
enabled = true,
onClickLabel = null,
role = null,
onClick = onClick
)
),
contentAlignment = contentAlignment,
propagateMinConstraints = false
) {
content()
}
}
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?
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
)
}
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.
Unable to reduce the huge padding in OutlinedButton. Tried contentPadding, modifier padding, etc. Cannot reduce padding for text "apple". Any idea? Should I use any other type of compose component for this?
OutlinedButton(
onClick = {},
border = BorderStroke(1.dp, Color.White),
shape = RoundedCornerShape(12.dp),
contentPadding = PaddingValues(0.dp),
modifier = Modifier
.background(bgColor)
.height(24.dp)
.padding(all = 0.dp),
colors = ButtonDefaults.outlinedButtonColors(backgroundColor = bgColor)) {
Text("apple",
color = Color.White,
style = MaterialTheme.typography.body2,
modifier = Modifier.height(10.dp).padding(vertical = 0.dp), //.background(bgColor),
)
}
Updated after #liveAnyway's answer (thanks!) which appeared to help. After that I removed height from OutlinedButton too - ideally I wanted it like "wrap-content". Once I made that change, I still see the padding. Bottomline I don't want any absolute height specified so that it can work with different font size from system settings.
Row(modifier = Modifier.padding(vertical = 12.dp)) {
OutlinedButton(
onClick = {},
border = BorderStroke(1.dp, Color.White),
shape = RoundedCornerShape(18.dp),
contentPadding = PaddingValues(0.dp),
modifier = Modifier
.background(bgColor)
.padding(all = 0.dp),
colors = ButtonDefaults.outlinedButtonColors(backgroundColor = bgColor)
) {
Text("apple",
color = Color.White,
style = MaterialTheme.typography.body2,
modifier = Modifier.padding(vertical = 0.dp),
)
}
}
Button has default min size modifier. This is done according to Material guidelines, so that the button is easy to hit. If the control size is too small, the user may have problems hitting it, take this into account when changing this parameter.
You can override it by applying defaultMinSize modifier. The 0.dp will be ignored, but starting from 1.dp you will get the desired result:
OutlinedButton(
onClick = { /*TODO*/ },
contentPadding = PaddingValues(),
modifier = Modifier
.defaultMinSize(minWidth = 1.dp, minHeight = 1.dp)
) {
Text(
"Apple",
)
}
Alternatively, you can design your own button without these restrictions:
Surface(
onClick = {
},
shape = MaterialTheme.shapes.small,
color = bgColor,
contentColor = MaterialTheme.colors.primary,
border = ButtonDefaults.outlinedBorder,
role = Role.Button,
) {
Text(
"Apple",
)
}
You have to change the minHeight (default size are MinWidth = 64.dp and MinHeight = 36.dp) and remove the contentPadding with contentPadding = PaddingValues(0.dp):
OutlinedButton(
onClick = {},
border = BorderStroke(1.dp, Color.White),
shape = RoundedCornerShape(12.dp),
contentPadding = PaddingValues(0.dp),
modifier = Modifier.defaultMinSize(
minWidth = ButtonDefaults.MinWidth,
minHeight = 10.dp
)
) {
Text(
"apple",
style = MaterialTheme.typography.body2
)
}