Compose Camp 1: Mastering Text and TextField in Jetpack Compose

Compose Camp 1: Mastering Text and TextField in Jetpack Compose

This article will discuss Text and TextField in Jetpack Compose. We will cover basic concepts like declaring Text and TextField to advanced concepts like building annotated text and styling Text and TextField.

Text

Text is the simplest UI component in Jetpack Compose. It is equivalent to TextView in XML. It displays a string of text on the screen. The Text() function takes in a string parameter and displays it on the screen.

Here’s an example of how to create a Text component:

@Composable
fun MyText() {
    Text(text = "Hello, from Compose!")
}

In the above example, we declare a Text which takes a text parameter which is the text to display. You can load text from a string resource instead of hardcoding.

Text(text = stringResource(R.string.hello_from_compose))

TextField

TextField is used to accept user input. It is equivalent to EditText in XML. It allows users to enter text, numbers, or other data types. In Jetpack Compose, you create a TextField using the TextField() function. The TextField() function takes in a value, label, and modifier parameter. The value parameter is used to store the user input.

Here’s an example of how to create a TextField component:

var name by remember { mutableStateOf("") }
TextField(
    value = name,
    label = { Text("Name") },
    onValueChange = { name = it }
)

In the above example, we create a TextField that accepts the user’s name as input. We store the user input in the name variable using the mutableStateOf() function. onValueChange parameter updates the state value whenever the user types in the text field.

TextField can take more parameters like keyboardOptions where you can apply specific keyboard type and placeholder to hold placeholder text.

TextField(
    value = name,
    onValueChange = { name = it },
    placeholder = { Text("Please Enter Name") },
    keyboardOptions = KeyboardOptions.Default.copy(
        keyboardType = KeyboardType.Text,
        imeAction = ImeAction.Done
    ),
    label = { Text("Name") }
)

Styling Text

In Jetpack Compose, you can easily style your UI components using Material Design guidelines.

You can customize the appearance of individual UI components by using modifiers. Modifiers are functions you can chain to apply different styles to your UI components. For example, you can use the padding() modifier to add padding around a Text component or the background() modifier to add a background color to a Button component.

Here’s an example of how to add padding and background color to a Text component:

Text(
    stringResource(R.string.hello_from_compose),
    modifier = Modifier
        .padding(16.dp)
        .background(Color.Blue)
)

In the above example, we add 16dp of padding and blue background color to the Text component.

In Jetpack Compose, you can apply different styles to text using Textcomposable. Here's an example of how to style text:

Text(
      text = stringResource(R.string.hello_from_compose),
       color = Color.Red,
       fontSize = 18.sp,
       fontWeight = FontWeight.Bold,
       textAlign = TextAlign.Center,
       textDecoration = TextDecoration.Underline,
       modifier = Modifier.padding(16.dp),
       style = MaterialTheme.typography.h1
    )

In the above example, we apply different styles to the text. For example, we set the color of the text to blue using the color parameter, set the font size to 18sp using the fontSize parameter, and set the font weight to bold using the fontWeight parameter.

We also set the text alignment to center using the textAlign parameter, apply an underline decoration to the text using the textDecoration parameter, and add 16dp padding around the text using the modifier parameter.

Finally, we set the text style to MaterialTheme.typography.h1 using the style parameter. This applies a predefined text style that matches the H1 heading style in the current theme. We will cover material theme in a later tutorial.

You can also create your own custom text styles using the TextStyle class, and apply them to text using the style parameter. For example:

val redItalicText = TextStyle(
    color = Color.Red,
    fontSize = 16.sp,
    fontStyle = FontStyle.Italic
)

Text(
    text = "My custom styled text",
    style = redItalicText
)

You can also build an annotated string in Compose. An annotated string is a string that has additional formatting or metadata associated with certain parts of the text. This metadata can be used to apply different styles and behaviors to different parts of the text.

Text(
     buildAnnotatedString {
       withStyle(style = SpanStyle(color = Color.Red)) {
          append("H")
            }
          append("ello ")
      withStyle(style = 
        SpanStyle(fontWeight = FontWeight.Bold, color = Color.Red)) {
                append("C")
            }
            append("ompose")
        }
    )

You can also build annotated string using AnnotatedString Builder as shown below

val annotatedStringExample = AnnotatedString.Builder()
    .pushStyle(SpanStyle(color = Color.Red, fontWeight =         FontWeight.Bold))
    .append("Bold and red")
    .pop()
    .append("Normal text")
    .addStringAnnotation("customStyle", "true", 0, 4)
    .pushStyle(SpanStyle(fontStyle = 
        FontStyle.Italic, textDecoration = TextDecoration.Underline))
    .append("Italic string")
    .pop()
    .toAnnotatedString()

In the above example, we create a new AnnotatedString.Builder() and use its pushStyle() method to apply a bold font weight and red color to the first part of the string. We then use the append() method to add the text to the string.

We then use the pop() method to remove the style we applied and add more regular text. We then use the addStringAnnotation() method to add metadata to the string. In this case, we add a metadata key/value pair called customStyle with a true value to the first 4 characters of the string.

We then use pushStyle() again to apply an italic font style and underline decoration to the next part of the string, and use pop() again to remove that style.

Finally, we use toAnnotatedString() to create the final AnnotatedString object.

You can then use this annotated string in a Text composable to display the text with the applied styles and metadata.

Styling TextField

You can apply a number of styling to TextField. Here is an example of how to style a TextField.

TextField(
        value = name,
        onValueChange = { name = it },
        label = { Text("Enter your name") },
        placeholder = { Text("Joseph Muasya") },
    textStyle = TextStyle(
            color = Color.Black,
            fontSize = 16.sp
        ),
    modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        keyboardOptions = KeyboardOptions(
            keyboardType = KeyboardType.Text,
            imeAction = ImeAction.Done
        ),
        backgroundColor = Color.LightGray,
        cursorColor = Color.White,
        shape = RoundedCornerShape(8.dp),
        maxLines = 1,
        singleLine = true,
        trailingIcon = {
            IconButton(
                onClick = { /* Search by name */ }
            ) {
                Icon(Icons.Filled.Search, contentDescription = "Search")
            }
        }
    )

In this example, we use the TextField composable to create a text field. We use the value and onValueChange parameters to store and update the text entered by the user.

We use the label parameter to display a label above the text field, and the placeholder parameter to display a hint text when the text field is empty.

We use the modifier parameter to set the size and position of the text field using the fillMaxWidth() and padding() modifiers.

We use the textStyle parameter to set the color and font size of the text entered by the user, and the backgroundColor parameter to set the background color of the text field.

We use the keyboardOptions parameter to set the keyboard type and the IME action that is triggered when the user presses the Enter key.

We use the cursorColor parameter to set the cursor color that appears when the user types in the text field.

We use the shape parameter to set the shape of the text field to a rounded rectangle with a corner radius of 8dp.

We use the maxLines parameter to limit the text field to a single line, and the singleLine parameter to enforce that the text field cannot have multiple lines.

Finally, we use the trailingIcon parameter to add an icon button to the text field. In this example, we use the Icon composable from the MaterialIcons icon set to display a search icon, and the IconButton composable to create a clickable button that triggers an action when clicked.

Composing UI elements

In Jetpack Compose, you can easily compose multiple UI elements to create complex layouts. You can use functions like Column() and Row() to arrange UI elements vertically and horizontally. You can also use the Box() function to create overlapping UI elements. We will cover layouts in a later tutorial.

Here’s an example of how to compose multiple UI elements to create a layout:

Column(modifier = Modifier.padding(16.dp)) {
    Text("Welcome to my app")
    Spacer(modifier = Modifier.height(8.dp))
    TextField(
        value = name,
        label = { Text("Name") },
        onValueChange = { name = it }
    )
}

In the above example, we create a layout with a Text, Textfield, and Button components. We use the Column() function to arrange the UI elements vertically and the Spacer() function to add spacing between the UI elements.

Additional resources

If you want to learn more about Jetpack Compose, here are some additional resources:

Enjoy building!