Blog Infos
Author
Published
Topics
, , ,
Published

Automatically switching from horizontal to vertical layout

Recently, I came across a requirement where I needed to display two horizontal buttons inside a box. However, if the text of any button overflows (i.e., it doesn’t fit in the available space), the layout should automatically switch to a vertical format.

So, the key question is:

How do we detect if any of the button texts are overflowing?

In this blog, I’ll walk you through the process of detecting text overflow in Jetpack Compose buttons and dynamically switching between horizontal and vertical layouts.

To solve this, I created a custom composable called OverflowAwareButton using the TextLayoutResult.hasVisualOverflow Text property. This boolean flag becomes true when the text doesn’t fit in the given constraints (e.g., a single line).

I then passed this result upward via a callback, allowing the parent composable to decide whether to render the buttons in a Row (horizontal) or a Column (vertical) format based on overflow status.

Here’s a simplified example of how the callback and layout switch work

@Composable
fun OverflowAwareButton(
text: String,
onTextOverflow: (Boolean) -> Unit
) {
Button(onClick = {}) {
Text(
text = text,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
onTextLayout = { textLayoutResult ->
onTextOverflow(textLayoutResult.hasVisualOverflow)
}
)
}
}
view raw gistfile1.txt hosted with ❤ by GitHub

Created a horizontal box with overflow-aware buttons to detect text overflow in horizontal mode and a vertical box with buttons for layout switching when overflow occurs.

@Composable
fun HorizontalBox(onTextOverflow: (Boolean) -> Unit) {
Row {
OverflowAwareButton(text = "Very long text that might overflow", onTextOverflow = onTextOverflow)
OverflowAwareButton(text = "Another Button", onTextOverflow = onTextOverflow)
}
}
@Composable
fun VerticalBox() {
Column {
Button(onClick = {}) {
Text(
text = "Very long text that might overflow",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
Button(onClick = {}) {
Text(
text = "Another Button",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
view raw gistfile1.txt hosted with ❤ by GitHub

Created a DynamicBoxWithButton layout that uses a mutable isOverflowing variable to switch between horizontal and vertical button arrangements. The variable is mutable because the UI needs to react and recompose dynamically when the overflow state changes.

@Composable
fun DynamicBoxWithButton() {
var isOverflowing by remember { mutableStateOf(false) }
if (isOverflowing) {
VerticalBox()
} else {
HorizontalBox(onTextOverflow = { isOverflowing = it })
}
}
view raw gistfile1.txt hosted with ❤ by GitHub

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

, ,

Cutting-Edge-to-Edge in Android 15: Using Previews and Testing in Jetpack Compose to Manage Insets.

With the advent of Android 15, edge-to-edge design has become the default configuration. Consequently, applications must be capable of accommodating window insets, including the system status bar and navigation bar, as well as supporting drawing…
Watch Video

Cutting-Edge-to-Edge in Android 15: Using Previews and Testing in Jetpack Compose to Manage Insets.

Timo Drick
Lead Android developer
Seven Principles Mobility GmbH

Cutting-Edge-to-Edge in Android 15: Using Previews and Testing in Jetpack Compose to Manage Insets.

Timo Drick
Lead Android develop ...
Seven Principles Mob ...

Cutting-Edge-to-Edge in Android 15: Using Previews and Testing in Jetpack Compose to Manage Insets.

Timo Drick
Lead Android developer
Seven Principles Mobility ...

Jobs

This article was previously published on proandroiddev.com.

Menu