How could I design a multi circular progress bar in jetpack compose? - android

I'm trying to design a progress bar showing multi-progress using jetpack compose but I did not find any library or helping material. I am just able to design a single progress bar but I need to design like
.

Just use multiple CircularProgressIndicator inside a Box:
Box(contentAlignment = Alignment.Center) {
CircularProgressIndicator(
progress = 0.45f,
color = Red,
modifier = Modifier.then(Modifier.size(60.dp)))
CircularProgressIndicator(
progress = 0.55f,
color = Green,
modifier = Modifier.then(Modifier.size(80.dp)))
CircularProgressIndicator(
progress = 0.75f,
color = Blue,
modifier = Modifier.then(Modifier.size(100.dp)))
}
If you want to draw also the circular track starting from M2 1.4.0-alpha04 and M3 1.1.0-alpha04 you can use the trackColor parameter:
CircularProgressIndicator(
//...
trackColor = LightGray
)
Before that releases if you want to draw also the circular track you can build a custom Composable with a Canvas + CircularProgressIndicator.
Something like:
val stroke = with(LocalDensity.current) {
Stroke(width = ProgressIndicatorDefaults.StrokeWidth.toPx(), cap = StrokeCap.Butt)
}
Canvas(modifier = Modifier.size(60.dp)){
val diameterOffset = stroke.width / 2
drawCircle(
radius = size.minDimension / 2.0f-diameterOffset,
color= LightGray,style = stroke)
}
CircularProgressIndicator(
progress = 0.45f,
color = Red,
modifier = Modifier.then(Modifier.size(60.dp)))

Related

compose modifiy icon set part of the color

I have an icon to indicate sequence.
My requirement is that when the order is reversed, the lower half of the icon turns blue; when the order is turned, the upper half of the icon turns blue.
I found a related question, but it conflicts with my needs in two points. First, I don't know how to write such code in compose. Second, I prefer to use code to control the color transformation.
Using BlendModes you can manipulate any pixel using another shape, png file, drawing or Path. You can refer these answers for more details
Jetpack Compose Applying PorterDuffMode to Image
How to clip or cut a Composable?
Result
Implementation
#Preview
#Composable
private fun Test() {
Image(
modifier = Modifier
.size(100.dp)
.drawWithContent {
val height = size.height
with(drawContext.canvas.nativeCanvas) {
val checkPoint = saveLayer(null, null)
// Destination
drawContent()
// Source
drawRect(
Color.Red,
topLeft = Offset(0f, height / 2),
size = Size(size.width, size.height / 2),
blendMode = BlendMode.SrcIn
)
}
},
painter = painterResource(id = R.drawable.arrows),
contentDescription = null
)
}

Creating arc inside arch with text using jetpack compose

I want to achieve like below, I have tried using the draw arc of compose and able to create one arc but not able to achieve another arch inside it with text at the ends to the arc.
Canvas(
modifier = modifier
) {
drawArc(
color = backgroundColor,
180f,
180f,
false,
style = Stroke(strokeWidth.toPx()),
size = Size(size.width, size.height),
)
drawArc(
color = fillColor,
180f,
percentage * 180f,
false,
style = Stroke(strokeWidth.toPx()),
size = Size(size.width, size.height),
)

How to apply translucent gradient on an Image in Android Jetpack Compose?

In Android Jetpack Compose, does anyone knows how to make an Image's left side slowly fading to transparent towards right side? Thanks!
Edit:
Sorry, I mean making an image fading like this in Compose, probably with blend mode? But not sure how to do that..
Expected outcome:
Just found an answer from How to add fading edge effect to Android Jetpack Compose Column or Row?
"Color.Black" means area that reveal the image.
Thanks guys!
Image(
painterResource(R.drawable.cat),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
// Workaround to enable alpha compositing
.graphicsLayer { alpha = 0.99f }
.drawWithContent {
val colors = listOf(
Color.Black,
Color.Transparent
)
drawContent()
drawRect(
brush = Brush.horizontalGradient(colors),
blendMode = BlendMode.DstIn
)
}
)
You could place a Box over the image and add a background gradient to the Box. You will have to set the size of the Box though to be the same as the image. In this example I don't bother setting the Box size correctly. I'll leave that up to you:
Here's the image I used:
https://adelaidevet.com.au/sites/default/files/archive/files/images/cat-ginger-eyes-closed_0.jpg
val screenWidth = LocalConfiguration.current.screenWidthDp
Box(modifier = Modifier.fillMaxWidth().wrapContentHeight()) {
Image(
painterResource(R.drawable.cat),
contentDescription = "",
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth()
)
Box(
modifier = Modifier
.requiredWidth(screenWidth.dp)
.requiredHeight(310.dp)
.background(
brush = Brush.horizontalGradient(
startX = 0f,
endX = 700f,
colors = listOf(
Color.Transparent,
Color(0xD7525252),
)
)
)
) {
}
}

How can I draw a shadow for a path in canvas in jetpack compose

I am drawing a custom shape for a topbar in jetpack compose. I want to draw a shadow for the path.
val topBarShapePath = Path().apply {
moveTo(dpToPixels(leftPadding), 0f)
lineTo(dpToPixels(leftPadding), dpToPixels(dpValue = 110.dp))
arcTo(
Rect(
dpToPixels(leftPadding),
dpToPixels(dpValue = 110.dp),
dpToPixels(dpValue = 32.dp),
dpToPixels(dpValue = 135.dp)
), -180f, -90f, true)
lineTo(
dpToPixels(dpValue = triangleStartX),
dpToPixels(dpValue = rectHeight))
lineTo(
dpToPixels(dpValue = screenWidth),
dpToPixels(dpValue = triangleEndY)
)
lineTo(dpToPixels(dpValue = screenWidth), 0f)
lineTo(dpToPixels(dpValue = leftPadding), 0f)
}
Column(
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
.drawBehind {
val finalWidth = 40.dp.toPx()
drawPath(
topBarShapePath,
color = topbarcolor)
drawOutline(
outline = Outline.Generic(
topBarShapePath),
brush = Brush.horizontalGradient(),
style = Stroke(
width = 1.dp.toPx(),
)
)
}
)
This is the code I am using to draw the shape, the "drawOutline" was to try and draw a shadow for the path, but I can't figure out how to blur the line.
Any help appreciated.
Here is a screenshot of the result I am looking for:
It's impossible to draw shadow in Canvas at the moment, but you can do it with Modifier.shadow, specifying the needed custom shape, like this:
class TopBarShape(/*some parameters*/): Shape {
override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density,
) = Outline.Generic(Path().apply {
// your path code
})
}
Modifier.shadow(elevation = 10.dp, shape = TopBarShape(/*your parameters*/))
Sadly this modifier doesn't allow much modifications, it's one of the most starred Compose issues, so hopefully it'll change in future, but as it's not in the latest 1.1-beta I wouldn't expect it at least until 1.2.
If you still think that drawing shadow manually is a needed feature, you can create a feature request.

How can I render plain android ProgressBar with Compose?

My application needs a ProgressBar, and I am trying to implement it with Jetpack Compose, so either I need a builtin ProgressBar support (I didn't find it) or there should be a mechanism to display plain Android Widgets with Compose. Is anything of this possible?
Ofcourse, we have Progress Bars in Jetpack Compose:
CircularProgressIndicator: Displays progress bar as Circle. It is indeterminate. Themed to Primary color set in styles. Another variant is determinate that takes progress in argument as Float (0.0f - 1.0f)
Example:
// Indeterminate
CircularProgressIndicator()
// Determinate
CircularProgressIndicator(progress = 0.5f)
LinearProgressIndicator: Displays progress bar as line. It is indeterminate. Themed to Primary color set in styles. Another variant is determinate that takes progress in argument as Float (0.0f - 1.0f)
Example:
// Indeterminate
LinearProgressIndicator()
// Determinate
LinearProgressIndicator(progress = 0.5f)
With 1.0.x you can use the LinearProgressIndicator or CircularProgressIndicator
// Indeterminate
CircularProgressIndicator()
LinearProgressIndicator()
// Determinate
CircularProgressIndicator(progress = ..)
LinearProgressIndicator(progress = ..)
Example:
var progress by remember { mutableStateOf(0.1f) }
LinearProgressIndicator(
backgroundColor = Color.White,
progress = progress,
color = blue700
)
To update the value you can use something like:
// { if (progress < 1f) progress += 0.1f }
For rounded corners we can use this code (It's the same like LinearProgress but with one small correction - in drawLine we use param StrokeCap.Round for rounding)
#Composable
fun LinearRoundedProgressIndicator(
/*#FloatRange(from = 0.0, to = 1.0)*/
progress: Float,
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colors.primary,
backgroundColor: Color = color.copy(alpha = ProgressIndicatorDefaults.IndicatorBackgroundOpacity)
) {
val linearIndicatorHeight = ProgressIndicatorDefaults.StrokeWidth
val linearIndicatorWidth = 240.dp
Canvas(
modifier
.progressSemantics(progress)
.size(linearIndicatorWidth, linearIndicatorHeight)
.focusable()
) {
val strokeWidth = size.height
drawRoundedLinearIndicatorBackground(backgroundColor, strokeWidth)
drawRoundedLinearIndicator(0f, progress, color, strokeWidth)
}
}
private fun DrawScope.drawRoundedLinearIndicatorBackground(
color: Color,
strokeWidth: Float
) = drawRoundedLinearIndicator(0f, 1f, color, strokeWidth)
private fun DrawScope.drawRoundedLinearIndicator(
startFraction: Float,
endFraction: Float,
color: Color,
strokeWidth: Float
) {
val width = size.width
val height = size.height
// Start drawing from the vertical center of the stroke
val yOffset = height / 2
val isLtr = layoutDirection == LayoutDirection.Ltr
val barStart = (if (isLtr) startFraction else 1f - endFraction) * width
val barEnd = (if (isLtr) endFraction else 1f - startFraction) * width
// Progress line
drawLine(color, Offset(barStart, yOffset), Offset(barEnd, yOffset), strokeWidth, StrokeCap.Round)
}
custom linear progress indicator
#Composable
fun CustomLinearProgressIndicator(
modifier: Modifier = Modifier,
progress: Float,
progressColor: Color = orangeColor,
backgroundColor: Color = orangeColor.copy(0.24f),
clipShape: Shape = RoundedCornerShape(16.dp)
) {
Box(
modifier = modifier
.clip(clipShape)
.background(backgroundColor)
.height(8.dp)
) {
Box(
modifier = Modifier
.background(progressColor)
.fillMaxHeight()
.fillMaxWidth(progress)
)
}
}
you can use this library which supports thumb, round corners, and animations.
https://github.com/KevinnZou/compose-progressIndicator
For someone who is looking for a rounded corner linear progress bar,
you can use the Modifier's clip function.
LinearProgressIndicator(
progress = 0.5f,
modifier = Modifier.height(10.dp).clip(RoundedCornerShape(10.dp))
)

Categories

Resources