Implementing Fixed Suffix in Jetpack Compose TextField

Jetpack Compose has revolutionized Android development by providing a declarative UI framework that simplifies and accelerates the development process. Among its many features, TextField is one of the most commonly used components, enabling developers to implement user-friendly input fields. A frequent requirement in modern apps is to include a fixed suffix in a TextField, such as units (e.g., "kg" or "%") or static text (e.g., ".com"). In this blog post, we’ll explore how to implement a fixed suffix in Jetpack Compose's TextField while maintaining a clean and reusable approach.

Why Add a Fixed Suffix to a TextField?

Adding a fixed suffix can improve the user experience in several ways:

  1. Clarity: Indicates the expected format of the input, such as "Amount in USD ($)."

  2. Guidance: Provides context for user input, reducing errors.

  3. Consistency: Enhances the visual consistency of the UI, especially in forms.

Now, let’s dive into the implementation details of this feature.

Prerequisites

Before we proceed, ensure you have the following:

  • Android Studio Bumblebee or later.

  • Knowledge of Kotlin and Jetpack Compose.

  • Jetpack Compose library set up in your project (latest stable version recommended).

Here’s a minimal build.gradle setup for Jetpack Compose:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk 34

    defaultConfig {
        applicationId "com.example.suffixtextfield"
        minSdk 21
        targetSdk 34
        versionCode 1
        versionName "1.0"
    }

    buildFeatures {
        compose true
    }

    composeOptions {
        kotlinCompilerExtensionVersion '1.5.3'
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {
    implementation "androidx.compose.ui:ui:1.6.0"
    implementation "androidx.compose.material:material:1.6.0"
    implementation "androidx.compose.ui:ui-tooling:1.6.0"
    implementation "androidx.compose.runtime:runtime-livedata:1.6.0"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1"
}

Implementing a Fixed Suffix in TextField

Jetpack Compose’s TextField does not have a built-in option for suffixes. However, we can achieve this by leveraging the Row composable to combine a TextField and a Text element that serves as the suffix. Here’s how:

Basic Implementation

import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp

@Composable
fun FixedSuffixTextField(placeholder: String, suffix: String) {
    var text by remember { mutableStateOf("") }

    Row(modifier = Modifier.fillMaxWidth()) {
        TextField(
            value = text,
            onValueChange = { text = it },
            placeholder = { Text(placeholder) },
            modifier = Modifier.weight(1f)
        )
        Text(
            text = suffix,
            modifier = Modifier.padding(start = 8.dp, top = 16.dp),
            style = MaterialTheme.typography.bodyMedium
        )
    }
}

Key Points

  1. Row Layout: The Row composable ensures the TextField and suffix align horizontally.

  2. Weight Modifier: The TextField is given a weight of 1f to occupy the remaining space, while the Text for the suffix adjusts dynamically.

  3. Padding: Proper padding is applied to the suffix to maintain alignment with the input text.

Preview Example

Here’s a preview of the composable in action:

@Preview
@Composable
fun PreviewFixedSuffixTextField() {
    MaterialTheme {
        FixedSuffixTextField(placeholder = "Enter value", suffix = "%")
    }
}

Advanced Features

Supporting Outlined TextField

If you’re using OutlinedTextField for a more modern UI, the implementation remains similar. Simply replace TextField with OutlinedTextField:

OutlinedTextField(
    value = text,
    onValueChange = { text = it },
    placeholder = { Text(placeholder) },
    modifier = Modifier.weight(1f)
)

Customizing Suffix Style

To enhance the appearance of the suffix, you can customize its style:

Text(
    text = suffix,
    modifier = Modifier.padding(start = 8.dp, top = 16.dp),
    style = MaterialTheme.typography.bodyMedium.copy(
        color = MaterialTheme.colorScheme.primary
    )
)

Handling Long Input Text

To ensure the suffix remains visible with long text inputs, use the maxLines parameter and scrollable modifier in the TextField:

TextField(
    value = text,
    onValueChange = { text = it },
    placeholder = { Text(placeholder) },
    modifier = Modifier
        .weight(1f)
        .horizontalScroll(rememberScrollState()),
    maxLines = 1
)

Best Practices

  • Validation: Ensure the suffix does not interfere with user input validation.

  • Localization: If the suffix changes based on locale (e.g., currency symbols), handle localization appropriately.

  • Accessibility: Use content descriptions to make the UI accessible for screen readers.

Wrapping Up

Adding a fixed suffix to a TextField in Jetpack Compose is straightforward yet powerful for improving usability. By combining composables like Row, TextField, and Text, you can create a flexible and visually appealing UI component. With the advanced features outlined above, you can further customize and optimize this implementation to fit various app requirements.

Jetpack Compose’s declarative nature allows for endless possibilities in crafting dynamic and user-friendly interfaces. By mastering techniques like this, you can enhance the user experience in your applications while maintaining clean and maintainable code.

Call to Action

If you found this tutorial helpful, consider sharing it with fellow developers! For more tips and in-depth guides on Jetpack Compose and Android development, follow our blog and stay tuned for upcoming posts.

Happy coding!