0

I have a LazyColumn with items as Row containing LinearProgressIndicator and Text.

Sample Screenshot

Given conditions,

  1. All text is aligned to the end.
  2. I am using LazyColumn as there are many items and the list will be scrollable.

Requirement
How to make the LinearProgressIndicator as wide as possible BUT it should have the same width across Rows.

i.e. In the given screenshot, I want all the LinearProgressIndicator to be as wide as the LinearProgressIndicator in the Row containing text "Text 2 with lot more content".

Constraints,

  1. Can not have hardcoded width for the progress or the text.
  2. I have data for all the items. (No pagination)

Code

@Composable
fun LazyColumnProgress() {
    val data = listOf(
        Pair("Text 1", 0.30F),
        Pair("Text 1 with more", 0.25F),
        Pair("Text 2 with lot more content", 0.20F),
        Pair("Text 3", 0.14F),
        Pair("Text 4", 0.5F),
        Pair("Text 5", 0.3F),
        Pair("Text 6", 0.1F),
        Pair("Text 7", 0.1F),
        Pair("Text 8", 0.09F),
        Pair("Text 9", 0.01F),
    )

    LazyColumn(
        modifier = Modifier.fillMaxWidth(),
    ) {
        items(data) {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                modifier = Modifier
                    .padding(8.dp)
                    .fillMaxWidth(),
            ) {
                LinearProgressIndicator(
                    progress = it.second,
                    strokeCap = StrokeCap.Round,
                    modifier = Modifier
                        .fillMaxWidth()
                        .weight(1F),
                )
                Text(
                    text = it.first,
                    style = TextStyle(
                        textAlign = TextAlign.End,
                    ),
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier
                        .padding(8.dp)
                        .wrapContentWidth(align = Alignment.End),
                )
            }
        }
    }
}
Abhimanyu
  • 11,351
  • 7
  • 51
  • 121

1 Answers1

1

You can measure texts with TextMeasurer to get longest text width. minus horizontal paddings which are 8.dp twice for both sides. To get width of the total width you can use BoxWithConstraints and get the width for LinearProgressIndicator.

enter image description here

@OptIn(ExperimentalTextApi::class)
@Preview
@Composable
fun LazyColumnProgress() {
    val data = listOf(
        Pair("Text 1", 0.30F),
        Pair("Text 1 with more", 0.25F),
        Pair("Text 2 with lot more content", 0.20F),
        Pair("Text 3", 0.14F),
        Pair("Text 4", 0.5F),
        Pair("Text 5", 0.3F),
        Pair("Text 6", 0.1F),
        Pair("Text 7", 0.1F),
        Pair("Text 8", 0.09F),
        Pair("Text 9", 0.01F),
    )

    val textMeasurer = rememberTextMeasurer()

    val maxTextWidth = data.maxOf {
        textMeasurer.measure(it.first).size.width
    }


    BoxWithConstraints {

        val density = LocalDensity.current
        val maxWidth = constraints.maxWidth

        val indicatorWidth = with(density) {
            (maxWidth - maxTextWidth).toDp() -32.dp
        }
        
        LazyColumn(
            modifier = Modifier.fillMaxWidth(),
        ) {
            items(items = data) {
                Row(
                    verticalAlignment = Alignment.CenterVertically,
                    modifier = Modifier
                        .padding(8.dp)
                        .fillMaxWidth(),
                ) {
                    LinearProgressIndicator(
                        progress = it.second,
                        strokeCap = StrokeCap.Round,
                        modifier = Modifier
                            .width(indicatorWidth),
                    )

                    Spacer(modifier = Modifier.weight(1f))
                    Text(
                        text = it.first,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                        modifier = Modifier
                            .padding(8.dp),
                    )
                }
            }
        }
    }
}
Thracian
  • 43,021
  • 16
  • 133
  • 222