简体   繁体   中英

How to show vertical text with proper size/layout in jetpack compose

How does one properly rotate text in jetpack compose and get it to do a correct layout? When I use the rotate modifier on a Text object the text is rotated but the size taken up in the layout seems to be using the pre-rotated text width.

Here is a simple example of what I am trying to accomplish - the vertical text should be along the left side in a narrow space:

@Composable
fun MainBox() {
    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            modifier = Modifier.padding(4.dp).background(Color.Gray),
            text = "This is at the top"
        )

        Row(
            modifier = Modifier.fillMaxWidth().weight(1f),
            verticalAlignment = Alignment.CenterVertically
        ) {

            Text(
                modifier = Modifier.padding(4.dp).rotate(-90f),
                text = "This should be vertical text on the left side"
            )

            Text(
                modifier = Modifier.fillMaxSize().background(Color.Yellow),
                textAlign = TextAlign.Center,
                text = "This is a big yellow box that should take up most of the space"
            )
        }
    }
}

However, what this shows is this.

长的垂直文本

If I shorten the text in the vertical text it only takes up a narrow space, which looks more like the layout I want.

短垂直文本

Is there a way to intercept the layout process or some other setting to use to fix the sizes so that the vertical text takes up only one text row's width of horizontal space, but still adapts to user font size changes (so no fixed sizes)?

Answers to similar questions here and here do not solve this problem or no longer work.

My version. After a few tests it seems to work pretty well

class ComposeActivity7 : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            ComposeTutorialTheme {

                Column(
                    modifier = Modifier.fillMaxSize(),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(
                        modifier = Modifier
                            .padding(4.dp)
                            .background(Color.Gray),
                        text = "This is at the top"
                    )

                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .weight(1f),
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        Text(
                            modifier = Modifier
                                .vertical()
                                .rotate(-90f)
                                .background(Color.Gray)
                                .padding(4.dp),
                            text = "This should be vertical text on the left side"
                        )
                        Text(
                            modifier = Modifier
                                .fillMaxSize()
                                .background(Color.Yellow),
                            textAlign = TextAlign.Center,
                            text = "This is a big yellow box that should take up most of the space"
                        )
                    }
                }
            }
        }
    }
}

fun Modifier.vertical() =
    layout { measurable, constraints ->
        val placeable = measurable.measure(constraints)
        layout(placeable.height, placeable.width) {
            placeable.place(
                x = -(placeable.width / 2 - placeable.height / 2),
                y = -(placeable.height / 2 - placeable.width / 2)
            )
        }
    }

Result

在此处输入图像描述

Slightly improved variant of Sergei S, which works within parents which have Modifier.high(Intrinsic.X) :

fun Modifier.rotateVertically(rotation: VerticalRotation) = then(
    object : LayoutModifier {
        override fun MeasureScope.measure(measurable: Measurable, constraints: Constraints): MeasureResult {
            val placeable = measurable.measure(constraints)
            return layout(placeable.height, placeable.width) {
                placeable.place(
                    x = -(placeable.width / 2 - placeable.height / 2),
                    y = -(placeable.height / 2 - placeable.width / 2)
                )
            }
        }

        override fun IntrinsicMeasureScope.minIntrinsicHeight(measurable: IntrinsicMeasurable, width: Int): Int {
            return measurable.maxIntrinsicWidth(width)
        }

        override fun IntrinsicMeasureScope.maxIntrinsicHeight(measurable: IntrinsicMeasurable, width: Int): Int {
            return measurable.maxIntrinsicWidth(width)
        }

        override fun IntrinsicMeasureScope.minIntrinsicWidth(measurable: IntrinsicMeasurable, height: Int): Int {
            return measurable.minIntrinsicHeight(height)
        }

        override fun IntrinsicMeasureScope.maxIntrinsicWidth(measurable: IntrinsicMeasurable, height: Int): Int {
            return measurable.maxIntrinsicHeight(height)
        }
    })
    .then(rotate(rotation.value))

enum class VerticalRotation(val value: Float) {
    CLOCKWISE(90f), COUNTER_CLOCKWISE(270f)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM