-2

I'm having trouble with the progress indication of the LinearProgressIndicator when its height is increased:

The progress is very small (1%), but the second LinearProgressIndicator shows a much larger progress than that.

This is my code:

val progress = .01f

Column(
    modifier = Modifier.fillMaxSize(),
    verticalArrangement = Arrangement.spacedBy(10.dp),
    horizontalAlignment = Alignment.CenterHorizontally,
) {
    Card {
        LinearProgressIndicator(
            progress = { progress },
            strokeCap = StrokeCap.Square,
        )
    }

    Card(
        modifier = Modifier.height(60.dp),
    ) {
        LinearProgressIndicator(
            modifier = Modifier.fillMaxSize(),
            progress = { progress },
            strokeCap = StrokeCap.Square,
        )
    }
}
0

1 Answer 1

8

The cause of the problem becomes more clear if you remove the strokeCap:

The circle's position in the bar represents the progress. As you can see, it is at the far left, representing a very small value (1%). It couldn't even be more to the left, otherwise the circle wouldn't fit into the bar anymore. If you set the progress to 0, then the circle isn't displayed at all, but if the progress is even a tiny bit greater than 0, then the circle will be displayed like this. In your code you use StrokeCap.Square, which only makes the circle to a square - but it doesn't change its behavior.

It is actually the center of the circle (or square) that represents the progress - not its left edge or its right edge. But the center will always be positioned in a way that the full circle can be displayed. Therefore small values will all look the same.

The same goes for very large values nearing 100%: The circle won't move any further to the right as soon as its right edge touches the end of the bar. That will already happen a little bit below 100%, because the progress is determined by the circle's center, not its right edge. This is what 90% looks like (and also everything up to 100%, of course):

And you will also have a visual effect for values in between, like 50%: Although this will position the circle dead center, the right half of it will extend even further right, giving the impression of more than 50%:

This effect is even more pronounced when you replace the circle with a square (as in your example):

The right edge of the circle and the square are both at the same position, but what actually represents the progress isn't the right edge, it is the center of the circle or square.

That this effect is so pronounced is caused by the large width of the circle/square. The width is so large because the height is so large: A circle (and square) always have the same height and width. And the height of the circle is determined by the height of the bar. If the height is smaller - as with your first LinearProgressIndicator - then this visual effect is far less pronounced. That's why the first one looks much better than the second one.


Long story short: If you need a LinearProgressIndicator with a larger height, don't use StrokeCap.Square as it is described in the documentation like this:

Begin and end contours with a half square extension. This is similar to extending each contour by half the stroke width (as given by Paint.strokeWidth).

What you want to use instead is StrokeCap.Butt:

Begin and end contours with a flat edge and no extension.

This is what 1% then looks like:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.