DEV Community

Cover image for How to Handle the "More" Feature on Android?
Kiolk
Kiolk

Posted on

How to Handle the "More" Feature on Android?

Sometimes, we have limited space to display large amounts of text. One solution is to restrict the number of displayed lines and ellipsize the end of the last line. However, we still need to display the full content. We can use various implementations of expanded text, but here I demonstrate how to add a "Show more" button and display the full text in a BottomSheet. 

First, we need to create an appropriate container to display the text with a fixed height. The simplest implementation of it looks like this:

@Composable
fun ContentBlock() {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(160.dp)
            .background(color = Color.Yellow, shape = RoundedCornerShape(8.dp))
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(8.dp),
            verticalArrangement = Arrangement.Bottom
        ) {
            Text(
                text = mockedText,
                overflow = TextOverflow.Ellipsis
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Simple container for text
It is a very simple container for text. When the text fills all available space, it is cut off in a way defined by the overflow property. In our example, TextOverflow.Ellipsis indicates that the last line will end with three dots.

We want to give users the ability to read the full text. For this reason, we need to add a "More" button at the bottom of the block. The simplest solution is to add a button labeled "More" directly below the message block:

Text(
    text = "More",
    modifier = Modifier
        .align(Alignment.End)
)
Enter fullscreen mode Exit fullscreen mode

However, this doesn't work because the added text pushes other elements outside the block's border, rendering it invisible. After trying different approaches, I found the simplest solution: adding weight for each element to ensure both elements are visible within the same column.

@Composable
fun ContentBlock() {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(160.dp)
            .background(color = Color.Yellow, shape = RoundedCornerShape(8.dp))
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(8.dp),
            verticalArrangement = Arrangement.Bottom
        ) {
            Text(
                text = mockedText,
                modifier = Modifier
                    .weight(0.85f),
                overflow = TextOverflow.Ellipsis
            )
            Text(
                text = "More",
                modifier = Modifier
                    .weight(0.15f)
                    .align(Alignment.End)
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Block with more button
We successfully displayed the "More" button. Now, we need to implement the logic to display this button only when necessary, as displaying it when the text fully fits would be redundant. Thanks for the Text composable in Jetpack Compose, which provides the necessary API for this functionality. We can just set up a callback for onTextLayout property, which receives aTextLayoutResult object. It contains detailed information about the text layout state, but in our case, we use the hasVisualOverflow flag, which indicates whether the text exceeds its boundaries. Based on this flag, we decided whether or not to display the "More" button.

Text(
    text = mockedText,
    modifier = Modifier
        .weight(0.85f),
    overflow = TextOverflow.Ellipsis,
    onTextLayout = { result ->
        isShowMore.value = result.hasVisualOverflow
    }
)
if(isShowMore.value) {
    Text(
        text = "More",
        modifier = Modifier
            .weight(0.15f)
            .align(Alignment.End)
    )
}
Enter fullscreen mode Exit fullscreen mode

Without more button
This solution seems unnecessary for a single text block that can be resized based on its content. However, it is applicable when using a horizontal pager, and we want to prevent size jumps during swiping. We only need to implement logic to display the full content of the text block when the "More" button is pressed. One simple approach is to use a bottom sheet, but I won't cover that in this post. 

You can find the full sample for this composable element in this GitHub Gist. I welcome any thoughts or comments on this post. 

You can find more useful content on my LinkedIn page, on X, in Medium or Mastodon.

Top comments (0)