I can't understand how I can make this shape with short bottom angle:
I tried searching information about shapes and only found about rounded corners.
Find this solution:
#Composable
fun ButtonWithCutCornerShape() {
Button(onClick = {}, shape = CutCornerShape(bottomStart = 50.dp)) {
Text(text = "Cut corner shape")
}
}
You can use CutCornerShape like this:
Button(
onClick = { /*TODO*/ },
shape = CutCornerShape(
topStart = 0f,
topEnd = 0f,
bottomEnd = 0f,
bottomStart = 100f
),
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Green.copy(alpha = 0.25f)),
border = BorderStroke(width = 1.dp, Color.Green),
contentPadding = PaddingValues(horizontal = 64.dp)
) {
Text(
text = "Button",
color = Color.Green
)
}
The effect:
Related
I am currently trying to make it so that when the user has clicked the chip it still retains it's initial form/shape, in this case round. How can I achieve this?
This is how it operates currently: https://gyazo.com/bdbe867adb5c9e75381f7ac923134709
The Chip code:
#Composable
fun TextChip(
isSelected: Boolean,
text: String,
onChecked: (Boolean) -> Unit,
selectedColor: Color = DarkGray,
shape: Shapes,
) {
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.wrapContentSize()
.border(
width = 1.dp,
color = if (isSelected) selectedColor else LightGray,
shape = RoundedCornerShape(20.dp)
)
.background(
color = if (isSelected) selectedColor else Transparent,
)
.clickable {
onChecked(!isSelected)
}
.padding(top = 3.dp, bottom = 3.dp, start = 17.dp, end = 17.dp)
) {
Text(
text = text,
fontSize = 21.sp,
fontWeight = FontWeight.Bold,
color = if (isSelected) Color.White else Unspecified, // Text inside, when clicked, gives color to the text!
)
}
}
#Composable
fun FirstChip() {
// Chip View
val textChipRememberOneState = remember { mutableStateOf(false) }
TextChip(
isSelected = textChipRememberOneState.value,
shape = Shapes(medium = RoundedCornerShape(15.dp)),
text = "Action",
selectedColor = LightGreen,
onChecked = {
textChipRememberOneState.value = it
},
)
}
You should set the shape for your Modifier.background(color, shape) but it won't clip your click ripple and it will be as in gif with a Rectangle shape. You can use Modifier.clip() to clip background and ripple as
modifier = Modifier
.wrapContentSize()
.border(
width = 1.dp,
color = if (isSelected) selectedColor else LightGray,
shape = RoundedCornerShape(20.dp)
)
.clip(RoundedCornerShape(20.dp))
.background(
color = if (isSelected) selectedColor else Transparent,
)
.clickable {
onChecked(!isSelected)
}
.padding(top = 3.dp, bottom = 3.dp, start = 17.dp, end = 17.dp)
You should use existing chip #Composable function. There are 4 chip types - Assist chip, filter chip, input chip, suggestion chip. FilterChip is best for you to use. You can simply call FilterChip function:
#Composable
fun FirstChip() {
// Chip View
val textChipRememberOneState = remember { mutableStateOf(false) }
FilterChip(
selected = textChipRememberOneState.value,
onClick = { textChipRememberOneState.value = ! textChipRememberOneState.value},
label = { Text("Action") }
)
}
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.
I am learning Jetpack Compose and would like to build something like this
I have tried using Box layout by stacking CircularProgressIndicator but requires hardcoding the circle sizes. I want the rings to be size agnostic.
How do I achieve this using Compose?
You can try to do with Canvas. I did this and could give you a start point to achieve what you want...
#Composable
fun DrawGradientCircles() {
Canvas(
modifier = Modifier
.size(300.dp)
.background(Color.Gray)
) {
drawCircle(
brush = Brush.sweepGradient(listOf(Color.Magenta, Color.Red)),
radius = 300f,
style = Stroke(90f)
)
drawCircle(
brush = Brush.sweepGradient(listOf(Color.Green, Color.Yellow)),
radius = 200f,
style = Stroke(90f)
)
drawCircle(
brush = Brush.sweepGradient(listOf(Color.Cyan, Color.Blue)),
radius = 100f,
style = Stroke(90f)
)
}
}
This is the result:
EDIT: I posted an updated version here:
https://gist.github.com/nglauber/e947dacf50155fb72408e83f6595e430
Hope it helps.
I was able to accomplish it using CircularProgressIndicator
#Composable
fun ringView(){
var sz by remember { mutableStateOf(Size.Zero)}
Box(
Modifier
.aspectRatio(1f)
.fillMaxSize()
.background(Color.Blue)
.onGloballyPositioned { coordinates ->
sz = coordinates.size.toSize()
}
, contentAlignment = Alignment.Center){
Box(Modifier.aspectRatio(1f), contentAlignment = Alignment.Center){
Text(text = pxToDp(sz.height.toInt()).toString())
CircularProgressIndicator(progress = 0.9F, Modifier.size(pxToDp(sz.width.toInt()).dp), strokeWidth = (pxToDp(sz.width.toInt())/15).dp,color = Color.Green)
CircularProgressIndicator(progress = 0.9F, Modifier.size((pxToDp(sz.width.toInt())-(2*(pxToDp(sz.width.toInt())/15))).dp), strokeWidth = (pxToDp(sz.width.toInt())/15).dp, color = Color.Black )
CircularProgressIndicator(progress = 0.9F, Modifier.size((pxToDp(sz.width.toInt())-(4*(pxToDp(sz.width.toInt())/15))).dp), strokeWidth = (pxToDp(sz.width.toInt())/15).dp, color = Color.Gray )
CircularProgressIndicator(progress = 0.9F, Modifier.size((pxToDp(sz.width.toInt())-(6*(pxToDp(sz.width.toInt())/15))).dp), strokeWidth = (pxToDp(sz.width.toInt())/15).dp, color = Color.Cyan )
CircularProgressIndicator(progress = 0.9F, Modifier.size((pxToDp(sz.width.toInt())-(8*(pxToDp(sz.width.toInt())/15))).dp), strokeWidth = (pxToDp(sz.width.toInt())/15).dp, color = Color.Magenta )
}
}
}
fun pxToDp(px: Int): Int {
return (px / Resources.getSystem().displayMetrics.density).toInt()
}
I want to implement the MaterialButtonToggleGroup in Jetpack Compose. This component looks like this (image taken from here):
So far, I got the following result:
Note, that the vertical grey border next to the vertical blue border are present. In the original, either the colored border or the grey color are present at a time. To make it more clear, have a look at this image with extra thick borders:
How can I achieve that the vertical borders between two buttons are not present? My current code looks like this:
val cornerRadius = 8.dp
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Spacer(modifier = Modifier.weight(1f))
items.forEachIndexed { index, item ->
OutlinedButton(
onClick = { indexChanged(index) },
shape = when (index) {
// left outer button
0 -> RoundedCornerShape(topStart = cornerRadius, topEnd = 0.dp, bottomStart = cornerRadius, bottomEnd = 0.dp)
// right outer button
items.size - 1 -> RoundedCornerShape(topStart = 0.dp, topEnd = cornerRadius, bottomStart = 0.dp, bottomEnd = cornerRadius)
// middle button
else -> RoundedCornerShape(topStart = 0.dp, topEnd = 0.dp, bottomStart = 0.dp, bottomEnd = 0.dp)
},
border = BorderStroke(1.dp, if(selectedIndex == index) { MaterialTheme.colors.primary } else { Color.DarkGray.copy(alpha = 0.75f)}),
colors = if(selectedIndex == index) {
// selected colors
ButtonDefaults.outlinedButtonColors(backgroundColor = MaterialTheme.colors.primary.copy(alpha = 0.1f), contentColor = MaterialTheme.colors.primary)
} else {
// not selected colors
ButtonDefaults.outlinedButtonColors(backgroundColor = MaterialTheme.colors.surface, contentColor = MaterialTheme.colors.primary)
},
) {
Text(
text = "Some text",
color = if(selectedIndex == index) { MaterialTheme.colors.primary } else { Color.DarkGray.copy(alpha = 0.9f) },
modifier = Modifier.padding(horizontal = 8.dp)
)
}
}
Spacer(modifier = Modifier.weight(1f))
}
In the MaterialButtonToggleGroup to prevent a double-width stroke there is a negative marginStart on all except the first child drawing the adjacent strokes directly on top of each other.
Using the same solution:
OutlinedButton(
modifier = when (index) {
0 ->
Modifier
.offset(0.dp, 0.dp)
.zIndex(if (selectedIndex == index) 1f else 0f)
else ->
Modifier
.offset((-1 * index).dp, 0.dp)
.zIndex(if (selectedIndex == index) 1f else 0f)
},
// Your code here
I'm new to Jetpack compose, I have create a composable like this.
Column(
Modifier.clickable(onClick = onclick)
.fillMaxWidth().background(pastelGray)
.padding(16.dp)
) {
Card(backgroundColor = Color.Cyan) {
// Image(asset = vectorResource(id = R.drawable.ic_coupon_back), modifier = Modifier.fillMaxWidth())
Column(modifier = Modifier.padding(8.dp)) {
Text(text = coupon.couponTitle, color = Color.Red, fontSize = 20.sp)
Text(text = coupon.couponSubTitle, color = Color.Black, fontSize = 13.sp)
Text(text = coupon.couponDateTitle, color = Color.Gray, fontSize = 11.sp)
}
}
}
When I add that commented image I got this error:
Surface can have only one direct measurable child!
I could not find the reason till now.
Because Card() composable used in your code uses Surface under the hood:
#Composable
fun Card(
modifier: Modifier = Modifier,
shape: Shape = MaterialTheme.shapes.medium,
backgroundColor: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(backgroundColor),
border: BorderStroke? = null,
elevation: Dp = 1.dp,
content: #Composable () -> Unit
) {
Surface(
modifier = modifier,
shape = shape,
color = backgroundColor,
contentColor = contentColor,
elevation = elevation,
border = border,
content = content
)
}
source: Official Card Implementation code
And Surface is a kind like ScrollView doesn't accept more than one direct child. So you need to wrap your code inside Card() into a single parent that is a direct child of Card or in other words direct child of Surface, example:
Card(backgroundColor = Color.Cyan) {
CardContent()
}
private fun CardContent() {
Column() {
// Image(asset = vectorResource(id = R.drawable.ic_coupon_back), modifier = Modifier.fillMaxWidth())
Column(modifier = Modifier.padding(8.dp)) {
Text(text = coupon.couponTitle, color = Color.Red, fontSize = 20.sp)
Text(text = coupon.couponSubTitle, color = Color.Black, fontSize = 13.sp)
Text(text = coupon.couponDateTitle, color = Color.Gray, fontSize = 11.sp)
}
}
}
}