Eugene.D
Eugene.D

Reputation: 91

Android Text is too wide when it contains long words

I want to display a text with an icon left to the text. The text and icon should be centered horizontally. Here is a composable function for this:

Column(Modifier.fillMaxSize()) {
    Row(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        // imagine this Box is an icon
        Box(
            Modifier
                .size(48.dp)
                .background(Color.Red)
        )
        Spacer(Modifier.width(8.dp))
        Text(
            text = "text ".repeat(3),
            textAlign = TextAlign.Center,
        )
    }
}

It works fine with short words:

few small words many small words

But adding long words to the text makes it too wide, and it seems that there is too much space between the icon and the text:

long words

I've tried to add Modifier.width(IntrinsicSize.Min) to the text, and it actually solves the issue with long words:

long words are fixed!

But it breaks displaying short words:

but short words are broken...

I don't know how to make work both long and short words. Hope to get help here.

UPD: The same result is for Android native views. Gist with xmls.

Upvotes: 2

Views: 554

Answers (2)

Eugene.D
Eugene.D

Reputation: 91

Solution proposed by my colleague.

@Composable
fun FlowText(text: String) {
    FlowRow(
        mainAxisSpacing = 4.dp,
        mainAxisAlignment = MainAxisAlignment.Center,
        crossAxisAlignment = FlowCrossAxisAlignment.Center,
    ) {
        text.splitToSequence(' ').filter { it.isNotEmpty() }.forEach {
            Text(text = it, textAlign = TextAlign.Center)
        }
    }
}

Demo: https://youtu.be/WXqvxlsJ3xM

Upvotes: 1

z.g.y
z.g.y

Reputation: 6257

You can consider this one, all of the codes below are copy-and-paste-able.

@Composable
fun MyScreen() {

    var text by remember { mutableStateOf("") }

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        TextField(
            modifier = Modifier.fillMaxWidth(),
            value = text,
            onValueChange = { text = it}
        )

        Spacer(modifier = Modifier.height(24.dp))

        Row(
            modifier = Modifier.wrapContentSize()
        ) {

            Spacer(modifier = Modifier.weight(.5f))

            SomeComposable(text = text, modifier = Modifier.weight(1f))

            Spacer(modifier = Modifier.weight(.5f))
        }
    }
}

@Composable
fun SomeComposable(
    text: String,
    modifier: Modifier = Modifier
) {

    Row(modifier = modifier) {

        Box(
            Modifier
                .align(Alignment.CenterVertically)
                .size(48.dp)
                .background(Color.Red)
        )

        Spacer(Modifier.width(8.dp))

        Text(
            modifier = Modifier.width(IntrinsicSize.Min),
            text = text,
            textAlign = TextAlign.Center,
        )
    }
}

I just put a Spacer between the components and weighted them accordingly.

Output:

enter image description here

Upvotes: 1

Related Questions