Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetpack compose single number text field

I am trying to create a phone verification screen where the user must enter 5 numbers each in their own text field like below. Verification text field

I have two questions:

  1. Is there a way to limit a TextField to 1 character. I can set single line and max lines, but don't see a way to limit to character length like 'Ms' from the view system. I can easily limit the character length in code by ignoring characters after the first one, but this still lets the user 'scroll' to the left and right even though there is only 1 character.
  2. Is there a way to wrap the width to the 1 character? Currently the only way I have found to limit the width is to set it specifically, but then if the system text size is changed it could break.

Here is some code incase it helps, this is some very jumbled together solution so apologies if something is incorrect:

@Composable
fun CodeTextFields(
    modifier: Modifier = Modifier,
    length: Int = 5,
    onFilled: (code: String) -> Unit
) {
    var code: List<Char> by remember {
        mutableStateOf(listOf())
    }
    val focusRequesters: List<FocusRequester> = remember {
        val temp = mutableListOf<FocusRequester>()
        repeat(length) {
            temp.add(FocusRequester())
        }
        temp
    }

    Row(modifier = modifier) {
        (0 until length).forEach { index ->
            OutlinedTextField(
                modifier = Modifier
                    .weight(1f)
                    .padding(vertical = 2.dp)
                    .focusRequester(focusRequesters[index]),
                textStyle = MaterialTheme.typography.h4.copy(textAlign = TextAlign.Center),
                singleLine = true,
                value = code.getOrNull(index)?.takeIf { it.isDigit() }?.toString() ?: "",
                onValueChange = { value: String ->
                    if (focusRequesters[index].freeFocus()) {   //For some reason this fixes the issue of focusrequestor causing on value changed to call twice
                        val temp = code.toMutableList()
                        if (value == "") {
                            if (temp.size > index) {
                                temp.removeAt(index)
                                code = temp
                                focusRequesters.getOrNull(index - 1)?.requestFocus()
                            }
                        } else {
                            if (code.size > index) {
                                temp[index] = value.getOrNull(0) ?: ' '
                            } else if (value.getOrNull(0)?.isDigit() == true) {
                                temp.add(value.getOrNull(0) ?: ' ')
                                code = temp
                                focusRequesters.getOrNull(index + 1)?.requestFocus() ?: onFilled(
                                    code.joinToString(separator = "")
                                )
                            }
                        }
                    }
                },
                keyboardOptions = KeyboardOptions.Default.copy(
                    keyboardType = KeyboardType.Number,
                    imeAction = ImeAction.Next
                ),

                )
            Spacer(modifier = Modifier.width(16.dp))
        }
    }
}
like image 207
Bailey Tye Avatar asked Apr 09 '21 17:04

Bailey Tye


People also ask

What is textfield in jetpack compose?

TextField in Jetpack Compose What's TextField? TextField is a user interface control that is used to allow the user to enter the text. This widget is used to get the data from the user as numbers or text. A simple example of TextField is Login page. We get the username and password using TextField widget. What are options available in TextField?

Does jetpack compose support material design?

Compose is built to support material design principles. Many of its UI elements implement material design out of the box. In this article, we will explain how you can create Material design Text Input Fields using Jetpack Compose.

What are textfield and textfield in compose?

At a higher level, Compose provides Text and TextField , which are composables following Material Design guidelines. It’s recommended to use them as they have the right look and feel for users on Android, and includes other options to simplify their customization without having to write a lot of code.

How do I create a jetpack project in Android Studio?

Knowledge in Jetpack compose. Physical device or emulator to run the application. To get started, open up Android Studio and create a new project using the “Empty Compose activity” template. Give it any name you would like. You can go ahead to customize the theme to your liking.


1 Answers

To limit to 1 number you can use something like:

@Composable
fun Field (modifier: Modifier = Modifier,
      onValueChange: (String, String) -> String = { _, new -> new }){

    val state = rememberSaveable { mutableStateOf("") }

    OutlinedTextField(
        modifier = modifier.requiredWidth(75.dp),
        singleLine = true,
        value = state.value,
        onValueChange = {
            val value = onValueChange(state.value, it)
            state.value = value
        },
        keyboardOptions = KeyboardOptions(
            keyboardType = KeyboardType.Number,
            imeAction = ImeAction.Next),
        )
}

and then use:

Field(onValueChange = { old, new ->
    if (new.length > 1 || new.any { !it.isDigit() }) old else new
})

enter image description here

like image 159
Gabriele Mariotti Avatar answered Nov 25 '22 07:11

Gabriele Mariotti