Jetpack Compose Text (with Examples)

Jetpack compose text

In this article, we’ll learn how to work with text in Android Jetpack Compose with the help of examples.

Prerequisites:

How to Display Text in Jetpack Compose?

We use the Text() composable to display any text. It provides a lot of customizations out of the box. If you know XML, this is the TextView.

For this article, create an empty Jetpack Compose project and open MainActivity. Create a MyUI() composable and call it from the onCreate() method. We’ll write our code in it.

MainActivity for Material 3 Jetpack Compose:

// add the following packages
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.DisableSelection
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourProjectNameTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Column(
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        MyUI()
                    }
                }
            }
        }
    }
}

@Composable
fun MyUI() {

}

For the Material 2 version:

// add the following packages
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.DisableSelection
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourProjectNameTheme(darkTheme = false) {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column(
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        MyUI()
                    }
                }
            }
        }
    }
}

@Composable
private fun MyUI() {

}

Note: I am using the Material 3 Jetpack Compose. If you are working with Material 2, you may see a slightly different appearance, but the code will still work as expected.

The Text() API looks like this:

@Composable
fun Text(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    onTextLayout: (TextLayoutResult) -> Unit = {},
    style: TextStyle = LocalTextStyle.current
)

Let’s play with the parameters.

Simple Text Example:

For a basic Text(), the text parameter is mandatory. We need to pass a String object.

@Composable
private fun MyUI() {
    Text(text = "SemicolonSpace")
}

Output:

jetpack compose simple text example

Displaying Text from String Resource:

First, place the following string in the res > values > strings.xml file.

<resources>
    <string name="semicolon_space">SemicolonSpace.com</string>
</resources>

We can get the resource value from the stringResource() method. It looks like this:

@Composable
@ReadOnlyComposable
fun stringResource(@StringRes id: Int): String

Here id is the string resource id.

@Composable
private fun MyUI() {
    Text(
        text = stringResource(id = R.string.semicolon_space)
    )
}

Output:

Displaying text from resource in jetpack compose

Text Color:

The color parameter is used to change the text color.

@Composable
private fun MyUI() {
    Text(
        text = "SemicolonSpace",
        color = Color.Blue
    )
}

Output:

jetpack compose text color

Read More: Colors in Jetpack Compose

Text Background Color and Shape:

The background() modifier helps us to set the background color and shape to the text.

@Composable
private fun MyUI() {
    Text(
        text = "SemicolonSpace",
        modifier = Modifier
            .background(
                color = Color.Cyan,
                shape = RoundedCornerShape(size = 26.dp)
            )
            .padding(all = 8.dp), // add inner padding
        fontSize = 22.sp
    )
}

Output:

Text Background Color Shape

Read More: Shape APIs in Jetpack Compose

Font Size:

We can change the text size using the fontSize parameter. The unit should be in sp.

@Composable
private fun MyUI() {
    Text(
        text = "SemicolonSpace",
        fontSize = 22.sp
    )
}

Output:

text font size

Text with Underline and Strikethrough:

Jetpack Compose provides TextStyle() class. It has a lot of parameters to customize the text.

constructor(
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontWeight: FontWeight? = null,
    fontStyle: FontStyle? = null,
    fontSynthesis: FontSynthesis? = null,
    fontFamily: FontFamily? = null,
    fontFeatureSettings: String? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    baselineShift: BaselineShift? = null,
    textGeometricTransform: TextGeometricTransform? = null,
    localeList: LocaleList? = null,
    background: Color = Color.Unspecified,
    textDecoration: TextDecoration? = null,
    shadow: Shadow? = null,
    textAlign: TextAlign? = null,
    textDirection: TextDirection? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    textIndent: TextIndent? = null
)

We can add underline and strikethrough using the textDecoration parameter. There are 3 values:

  1. TextDecoration.None
  2. TextDecoration.Underline
  3. TextDecoration.LineThrough (strikethrough)
@Composable
private fun MyUI() {
    Text(
        text = "SemicolonSpace",
        fontSize = 20.sp,
        style = TextStyle(textDecoration = TextDecoration.LineThrough)
    )
}

Output:

text strikethrough

We can combine underline and strikethrough using the TextDecoration.combine() method.

@Composable
private fun MyUI() {
    Text(
        text = "SemicolonSpace",
        fontSize = 20.sp,
        style = TextStyle(
            textDecoration = TextDecoration.combine(
                decorations = listOf(
                    TextDecoration.LineThrough,
                    TextDecoration.Underline
                )
            )
        )
    )
}

Output:

combine underline and strikethrough

Related: Kotlin Collections (with examples)

Bold and Italic Text:

To make the text italic, use the fontStyle parameter. We can set two styles:

  • FontStyle.Normal
  • FontStyle.Italic

Coming to bold text, fontWeight can be used to set multiple weights:

  • FontWeight.Thin
  • FontWeight.ExtraLight
  • FontWeight.Light
  • FontWeight.Normal
  • FontWeight.Medium
  • FontWeight.SemiBold
  • FontWeight.Bold
  • FontWeight.ExtraBold
  • FontWeight.Black

Example:

@Composable
private fun MyUI() {
    Text(
        text = "SemicolonSpace",
        fontSize = 24.sp,
        fontStyle = FontStyle.Italic,
        fontWeight = FontWeight.Bold
    )
}

Output:

text bold italic

Clickable Text:

Jetpack Compose provides TextButton API to enable click events on the text. If you don’t want to use that, add clickable() modifier to the Text() composable.

@Composable
private fun MyUI() {
    val contextForToast = LocalContext.current.applicationContext

    Text(
        modifier = Modifier.clickable {
            Toast.makeText(contextForToast, "You Clicked!", Toast.LENGTH_SHORT).show()
        },
        text = "Click Me"
    )
}

Output:

Clickable Text Jetpack Compose

Line Height and Letter Spacing:

The lineHeight and letterSpacing parameters take the values in sp.

@Composable
private fun MyUI() {
    Text(
        text = "Once you start using the dark theme, there is no going back.",
        fontSize = 22.sp,
        lineHeight = 24.sp,
        letterSpacing = 2.sp
    )
}

Output:

Line Height and Letter Spacing

Cursive Font:

Jetpack Compose provides the Cursive family out of the box. We just need to pass it to the fontFamily parameter.

@Composable
private fun MyUI() {
    Text(
        text = "SemicolonSpace",
        fontSize = 24.sp,
        fontFamily = FontFamily.Cursive
    )
}

Output:

jetpack compose font family cursive

Read More: Fonts in Jetpack Compose

Text Ellipsis and Maximum Number of Lines:

We can limit the number of lines with the help of the maxLines parameter.

@Composable
private fun MyUI() {
    Text(
        text = "If debugging is the process of removing bugs, coding must be putting them in.",
        fontSize = 18.sp,
        maxLines = 1
    )
}

Output:

limit maximum lines

The text is truncated. We can indicate it by setting the overflow parameter.

@Composable
private fun MyUI() {
    Text(
        text = "If debugging is the process of removing bugs, coding must be putting them in.",
        fontSize = 18.sp,
        maxLines = 1,
        overflow = TextOverflow.Ellipsis
    )
}

Output:

Ellipsis

Selectable Text:

By default, users cannot select the text. To enable the selection, put the Text() in the SelectionContainer().

@Composable
private fun MyUI() {
    SelectionContainer {
        Text(
            text = "If debugging is the process of removing bugs, coding must be putting them in.",
            fontSize = 18.sp
        )
    }
}

Output:

Selectable Text

If you have multiple texts, put them in a Column layout.

@Composable
private fun MyUI() {
    SelectionContainer {
        Column(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center
        ) {
            // text 1
            Text(
                text = "If debugging is the process of removing bugs, coding must be putting them in.",
                fontSize = 18.sp
            )

            // text 2
            Text(
                text = "Never date a software developer. We have a tendency of starting new projects before finishing the previous ones.",
                fontSize = 18.sp
            )
        }
    }
}

Output:

Multiple Selectable Text Column Layout

Sometimes, you may want to disable the selection for a particular text. In such cases, we can use the DisableSelection composable.

@Composable
private fun MyUI() {
    SelectionContainer {
        Column(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center
        ) {
            // text 1
            Text(
                text = "If debugging is the process of removing bugs, coding must be putting them in.",
                fontSize = 18.sp
            )

            // text 2
            DisableSelection {
                Text(
                    text = "You cannot select me.",
                    fontSize = 18.sp
                )
            }

            // text 3
            Text(
                text = "Never date a software developer. We have a tendency of starting new projects before finishing the previous ones.",
                fontSize = 18.sp
            )
        }
    }
}

Output:

disable particular text selection

Scrollable Text:

The Modifier’s scroll methods are used to make the text scrollable:

  • Modifier.verticalScroll() – for vertical scrolling
  • Modifier.horizontalScroll() – for horizontal scrolling

First, add the long_text string to your string resources file.

<resources>
    <string name="long_text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
        labore et dolore magna aliqua. Faucibus a pellentesque sit amet porttitor eget dolor morbi. Sit amet nisl suscipit
        adipiscing bibendum est. Pellentesque eu tincidunt tortor aliquam nulla. Risus commodo viverra maecenas accumsan
        lacus vel. Massa sapien faucibus et molestie ac feugiat sed lectus. Risus ultricies tristique nulla aliquet enim
        tortor at auctor urna. Feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Ultrices gravida dictum fusce
        ut placerat orci nulla pellentesque dignissim. At quis risus sed vulputate. Consectetur adipiscing elit pellentesque
        habitant morbi tristique senectus. Nec nam aliquam sem et. Arcu cursus euismod quis viverra nibh cras pulvinar
        mattis nunc. Quis ipsum suspendisse ultrices gravida dictum fusce ut. Et molestie ac feugiat sed lectus vestibulum.
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
        aliqua. Faucibus a pellentesque sit amet porttitor eget dolor morbi. Sit amet nisl suscipit adipiscing bibendum est.
    </string>
</resources>

Next, set the scrolling using the Modifier.verticalScroll() method.

@Composable
private fun MyUI() {
    Text(
        modifier = Modifier.verticalScroll(state = rememberScrollState()),
        text = stringResource(id = R.string.long_text),
        fontSize = 20.sp
    )
}

Output:

Vertical Scrollable Text

If you have multiple texts, put them in a Column and set the scroll methods on the Column layout.

@Composable
private fun MyUI() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(state = rememberScrollState())
    ) {
        Text(
            text = stringResource(id = R.string.long_text),
            fontSize = 20.sp
        )

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

        Text(text = "This is another text")
    }
}

Output:

Multiple Vertical Scrollable Text

Related: Padding and Spacer in Jetpack Compose

Gradient Text:

Jetpack Compose 1.2.0 introduced Brush API to TextStyle() for adding gradient colors. Currently, it is experimental.

@OptIn(ExperimentalTextApi::class)
@Composable
private fun MyUI() {
    Text(
        text = "I am not single! My laptop and I are happily married and we have two kids called mouse and pendrive.",
        fontSize = 22.sp,
        style = TextStyle(
            brush = Brush.linearGradient(
                colors = listOf(
                    Color(0xFF7b4397), Color(0xFFdc2430)
                )
            )
        )
    )
}

Output:

jetpack compose gradient text

Text with Shadow:

We can set the shadow using the TextStyle() class.

@Composable
private fun MyUI() {
    Text(
        text = "SemicolonSpace",
        fontSize = 22.sp,
        style = TextStyle(
            shadow = Shadow(
                color = Color.Green,
                offset = Offset(x = 5f, y = 10f),
                blurRadius = 2f
            )
        )
    )
}

Output:

Text with shadow

Text with Icon:

To create a text with an icon, add a Row layout and put the Icon() and Text() in it.

Example:

First, download the camera icon from the featureicons.com and convert it to XML in the Android Studio. Next, display it using the Icon() composable.

@Composable
private fun MyUI() {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Icon(
            painter = painterResource(id = R.drawable.camera),
            tint = Color.Black,
            contentDescription = null
        )
        Text(
            modifier = Modifier.padding(start = 6.dp),
            text = "Camera"
        )
    }
}

Output:

Text with Icon

Marquee Text:

Marquee text is a scrolling text displayed horizontally. Material 3 Jetpack Compose doesn’t have any prebuilt function for marquee text. But, in Material 2, you can use basicMarquee() modifier.

@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun MyUI() {
    Text(
        modifier = Modifier.basicMarquee(),
        text = "SemicolonSpace SemicolonSpace SemicolonSpace SemicolonSpace SemicolonSpace"
    )
}

Output:

Marquee Text in Jetpack Compose

Note: Marquee text scrolls if and only if the content doesn’t fit in the maximum width of the screen.

This is all about the text in Android Jetpack Compose. I hope you have learned something new. If you have any doubts, leave a comment below.

References:

Related Articles:

Leave a Comment