TextField with hint text in jetpack compose

20,352

Solution 1

You can create hintTextField in jetpackCompose like below code:

@Composable
fun HintEditText(hintText: @Composable() () -> Unit) {
    val state = state { "" } // The unary plus is no longer needed. +state{""}
    val inputField = @Composable {
        TextField(
            value = state.value,
            onValueChange = { state.value = it }
        )
    }
    if (state.value.isNotEmpty()) {
        inputField()
    } else {
        Layout(inputField, hintText) { measurable, constraints ->
        val inputfieldPlacable = measurable[inputField].first().measure(constraints)
        val hintTextPlacable = measurable[hintText].first().measure(constraints)
        layout(inputfieldPlacable.width, inputfieldPlacable.height) {
                inputfieldPlacable.place(0.ipx, 0.ipx)
                hintTextPlacable.place(0.ipx, 0.ipx)
        } }
    }
}

Call @Compose function like below:

HintEditText @Composable {
                                Text(
                                    text = "Enter Email",
                                    style = TextStyle(
                                        color = Color.White,
                                        fontSize = 18.sp
                                    )
                                )
                            }

Solution 2

With 1.0.0 you can use something like:

var text by remember { mutableStateOf("text") }

OutlinedTextField(
        value = text, 
        onValueChange = {
             text = it
        },
        label = { Text("Label") }
)

enter image description here or

TextField(
    value = text, 
    onValueChange = {
         text = it
    },
    label = { Text("Label") }
)

enter image description here

Solution 3

compose_version = '1.0.0-beta07'

Use parameter placeholder to show hint

TextField(value = "", onValueChange = {}, placeholder = { Text("Enter Email") })

Use parameter label to show floating label

TextField(value = "", onValueChange = {}, label = { Text("Enter Email") })

Solution 4

Jetpack compose version: dev08

The benefit of compose is that we can easily create our widgets by composing current composable functions.

We can just create a function with all parameters of the current TextField and add a hint: String parameter.

@Composable
fun TextFieldWithHint(
        value: String,
        modifier: Modifier = Modifier.None,
        hint: String,
        onValueChange: (String) -> Unit,
        textStyle: TextStyle = currentTextStyle(),
        keyboardType: KeyboardType = KeyboardType.Text,
        imeAction: ImeAction = ImeAction.Unspecified,
        onFocus: () -> Unit = {},
        onBlur: () -> Unit = {},
        focusIdentifier: String? = null,
        onImeActionPerformed: (ImeAction) -> Unit = {},
        visualTransformation: VisualTransformation? = null,
        onTextLayout: (TextLayoutResult) -> Unit = {}
) {
    Stack(Modifier.weight(1f)) {
        TextField(value = value,
                modifier = modifier,
                onValueChange = onValueChange,
                textStyle = textStyle,
                keyboardType = keyboardType,
                imeAction = imeAction,
                onFocus = onFocus,
                onBlur = onBlur,
                focusIdentifier = focusIdentifier,
                onImeActionPerformed = onImeActionPerformed,
                visualTransformation = visualTransformation,
                onTextLayout = onTextLayout)
        if (value.isEmpty()) Text(hint)
    }
}

We can use it like this:

@Model
object model { var text: String = "" }
TextFieldWithHint(value = model.text, onValueChange = { data -> model.text = data },
                    hint= "Type book name or author")

The pitfall of this approach is we are passing the hint as a string so if we want to style the hint we should add extra parameters to the TextFieldWithHint (e.g hintStyle, hintModifier, hintSoftWrap, ...)

The better approach is to accept a composable lambda instead of string:

@Composable
fun TextFieldWithHint(
        value: String,
        modifier: Modifier = Modifier.None,
        hint: @Composable() () -> Unit,
        onValueChange: (String) -> Unit,
        textStyle: TextStyle = currentTextStyle(),
        keyboardType: KeyboardType = KeyboardType.Text,
        imeAction: ImeAction = ImeAction.Unspecified,
        onFocus: () -> Unit = {},
        onBlur: () -> Unit = {},
        focusIdentifier: String? = null,
        onImeActionPerformed: (ImeAction) -> Unit = {},
        visualTransformation: VisualTransformation? = null,
        onTextLayout: (TextLayoutResult) -> Unit = {}
) {
    Stack(Modifier.weight(1f)) {
        TextField(value = value,
                modifier = modifier,
                onValueChange = onValueChange,
                textStyle = textStyle,
                keyboardType = keyboardType,
                imeAction = imeAction,
                onFocus = onFocus,
                onBlur = onBlur,
                focusIdentifier = focusIdentifier,
                onImeActionPerformed = onImeActionPerformed,
                visualTransformation = visualTransformation,
                onTextLayout = onTextLayout)
        if (value.isEmpty()) hint()
    }
}

We can use it like this:

@Model
object model { var text: String = "" }

TextFieldWithHint(value = model.text, onValueChange = { data -> model.text = data },
            hint= { Text("Type book name or author", style = TextStyle(color = Color(0xFFC7C7C7))) })

Solution 5

    var textState by remember { mutableStateOf(TextFieldValue()) }
    var errorState by remember { mutableStateOf(false) }
    var errorMessage by remember { mutableStateOf("") }


        TextField(
            value = textState,
            onValueChange = {
                textState = it
                when {
                    textState.text.isEmpty() -> {
                        errorState = true
                        errorMessage = "Please Enter Site Code"
                    }
                    else -> {
                        errorState = false
                        errorMessage = ""
                    }
                }
            },
            isError = errorState,
            label = {
                Text(
                    text = if (errorState) errorMessage
                    else "You Hint"
                )
            },
            modifier = Modifier
                .padding(top = 20.dp, start = 30.dp, end = 30.dp)
                .fillMaxWidth())
Share:
20,352
affan ahmad
Author by

affan ahmad

Updated on July 30, 2022

Comments

  • affan ahmad
    affan ahmad almost 2 years

    I want to create textfield with hint text in jetpackcompose. Any example how create textfield using jectpack? Thanks

  • Cristan
    Cristan over 3 years
    Note: you need these 2 imports: import androidx.compose.runtime.getValue and import androidx.compose.runtime.setValue. The current canary of Android Studio doesn't automatically add them.
  • Lee WonJoong
    Lee WonJoong almost 3 years
    Or you can just add import androidx.compose.runtime.* like this.
  • Pietrek
    Pietrek over 2 years
    This is the correct and elegant answer.