When I trying to rotate Column
with Text
with fillMaxWidth()
, all my long text fits to the screen:
@Composable
private fun Content() {
Column(
Modifier
.fillMaxWidth() // VARIANT 1
.fillMaxHeight()
.background(Color.White)
) {
BoxWithConstraints(
modifier = Modifier
.fillMaxSize()
) {
val W = this.maxWidth
val H = this.maxHeight
Column(
Modifier
.rotate(-90f)
.height(W)
.width(H),
verticalArrangement = Arrangement.Center
) {
Text(
text = "Long Long Long Long Long Long Long Long Text",
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(end = 10.dp),
maxLines = 1,
textAlign = TextAlign.End
)
}
}
}
}
But when I trying to limit root Column
width with 200.dp
, my text line seems to be cut to same width, 200.dp
:
@Composable
private fun Content() {
Column(
Modifier
.width(200.dp) // VARIANT 2
.fillMaxHeight()
.background(Color.White)
) {
BoxWithConstraints(
modifier = Modifier
.fillMaxSize()
) {
val W = this.maxWidth
val H = this.maxHeight
Column(
Modifier
.rotate(-90f)
.height(W)
.width(H),
verticalArrangement = Arrangement.Center
) {
Text(
text = "Long Long Long Long Long Long Long Long Text",
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(end = 10.dp),
maxLines = 1,
textAlign = TextAlign.End
)
}
}
}
}
Why is it so strange, and how can I fit long rotated text line into the narrow Column?
UPD: The final result that I want to achieve is the left side AppBar like on screenshot below.
But I cannot fit title text within, it is truncated.
CodePudding user response:
Rotation always occurs around the center of the inner content AFTER the parent container has already been resized. This means that you end up with cropped text. To achieve what you want, your left column AppBar and right column content need to be placed inside a Box that fills the entire screen. You can then rotate the text as long as it is centered. You must then adjust the offset of the text AFTER rotation to place it in the correct location. The Box must also have a transparent background. The amount of offset you use for the text will depend on the length of the text. Another possible solution is to create a custom layout and use the measured placeables and relocate them in the correct position. But even that requires adding offsets. So the solution shown here is probably easier to implement.
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.TopStart) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(start = 100.dp)
.background(color = Color.Yellow)
) {
Text("Content goes here...")
}
IconButton(modifier = Modifier.offset(x = 40.dp, y = 10.dp), onClick = {}) {
Icon(
modifier = Modifier
.requiredWidth(50.dp)
.requiredHeight(50.dp)
,
imageVector = Icons.Filled.Reply,
contentDescription = ""
)
}
Box(modifier = Modifier.fillMaxSize().background(color = Color.Transparent), contentAlignment = Alignment.Center) {
Text(
"This is a very long text that should not get cut off",
modifier = Modifier.rotate(-90f).offset(x = 130.dp, y = -140.dp),
softWrap = false
)
} }
CodePudding user response:
Finally, I've found a nice solution for my problem with LazyRow
:
val APP_BAR_WIDTH = 200.dp
val TEXT_MAX_WIDTH = 1000.dp
val OFFSET = (TEXT_MAX_WIDTH - APP_BAR_WIDTH) / 2
@Composable
private fun Content() {
Column(
Modifier
.width(APP_BAR_WIDTH)
.fillMaxHeight()
.background(Color.White)
) {
val scope = rememberCoroutineScope()
val state = rememberLazyListState()
LazyRow(
modifier = Modifier
.width(APP_BAR_WIDTH)
.fillMaxHeight(),
state = state
) {
item {
Column(
modifier = Modifier
.rotate(-90f)
.height(APP_BAR_WIDTH)
.offset(x = -OFFSET, y = -OFFSET),
verticalArrangement = Arrangement.Center
) {
Text(
text = "Long Long Long Long Long Long Long Long Long Long Long Long Text",
modifier = Modifier
.width(TEXT_MAX_WIDTH),
softWrap = false,
textAlign = TextAlign.End
)
}
}
}
state.disableScrolling(scope)
}
}
fun LazyListState.disableScrolling(scope: CoroutineScope) {
scope.launch {
scroll(scrollPriority = MutatePriority.PreventUserInput) {
awaitCancellation()
}
}
}
Here is implementation of my SideAppBar
on github: