1

I am trying to use toggle in a password field. This is my code so far but for some reason it wont work. How can I achieve toggling a password as in this image? Much appreciated!

Image: https://gyazo.com/5ad35b44dc955e0846c68f61ec9630b0

    Column(
        modifier = Modifier.padding(20.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally

    ) {

        val username = remember { mutableStateOf(TextFieldValue()) }
        val password = remember { mutableStateOf("") }
        var revealPassword: MutableState<Boolean> =
            remember { mutableStateOf(false) } // To reveal the password with toggle


        Text(text = "Sign in", style = TextStyle(fontSize = 40.sp, fontFamily = FontFamily.Cursive))
        Text(
            text = "here",
            style = TextStyle(fontSize = 40.sp, fontFamily = FontFamily.Cursive)
        )
        // PASSWORD
        Spacer(modifier = Modifier.height(20.dp))
        OutlinedTextField(
            value = password.value,
            onValueChange = { newText ->
                password.value = newText
            },

            visualTransformation = if (revealPassword.value) {
                VisualTransformation.None
            } else {
                PasswordVisualTransformation()
            },
            trailingIcon = {
                if (revealPassword.value) {
                    IconButton(onClick = {
         (I changed this!! -->) revealPassword.Value = false
                    }) { Icon(imageVector = Icons.Filled.Visibility, contentDescription = null) }
                } else {
                  IconButton(onClick = { 
(I changed this!! -->) revealPassword.Value = true }) {
                        Icon(imageVector = Icons.Filled.VisibilityOff, contentDescription = null)
                    }
                }
            },

            label = { Text(text = "Password") },
            singleLine = true,
            leadingIcon = { Icon(imageVector = Icons.Default.Lock, contentDescription = null) },
            modifier = Modifier
                .fillMaxWidth(180F),
            
            )
Josef M
  • 412
  • 2
  • 5
  • 20
  • For your IconButton `onClick`, you are always setting `revealPassword` to true. Can you try setting `revealPassword` to false on your if-case while you are setting your trailingIcon? – lokesh Jun 30 '22 at 13:59
  • @lokesh I tried to change the code as you suggested but I then receive an error saying: The boolean literal does not conform to the expected type MutableState – Josef M Jun 30 '22 at 14:11
  • Check https://stackoverflow.com/questions/65304229/toggle-password-field-jetpack-compose/66998457?r=SearchResults&s=1%7C37.1327#66998457 – Gabriele Mariotti Oct 20 '22 at 17:44

2 Answers2

2

You have given revealPassword = true in both onClick().

Change the first one to revealPassword = false

Complete code

@Composable
fun TogglePassword() {
    val password = remember {
        mutableStateOf("")
    }
    var revealPassword: MutableState<Boolean> = remember {
        mutableStateOf(false)
    } // To reveal the password with toggle
    OutlinedTextField(
        value = password.value,
        onValueChange = { newText ->
            password.value = newText
        },
        visualTransformation = if (revealPassword.value) {
            VisualTransformation.None
        } else {
            PasswordVisualTransformation()
        },
        trailingIcon = {
            if (revealPassword.value) {
                IconButton(
                    onClick = {
                        revealPassword.value = false
                    },
                ) {
                    Icon(imageVector = Icons.Filled.Visibility, contentDescription = null)
                }
            } else {
                IconButton(
                    onClick = {
                        revealPassword.value = true
                    },
                ) {

                    Icon(imageVector = Icons.Filled.VisibilityOff, contentDescription = null)
                }
            }
        },
        label = {
            Text(text = "Password")
        },
        singleLine = true,
        leadingIcon = {
            Icon(imageVector = Icons.Default.Lock, contentDescription = null)
        },
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
    )
}
Abhimanyu
  • 11,351
  • 7
  • 51
  • 121
  • When I changed it to as you suggested I get this message: The boolean literal does not conform to the expected type MutableState – Josef M Jun 30 '22 at 14:06
  • I had to add .Value to the following which solved the issue: **revealPassword.Value** = false and **revealPassword.Value** = true. I also did swap the boolean values around as you suggested. It now works as a charm, thanks for the feedback! – Josef M Jun 30 '22 at 14:39
1

You are setting boolean wrong.
And I think it is cleaner to control VisualTransformation above.

@Composable
fun PasswordTextField() {
    var masked by remember {
        mutableStateOf(false)
    }
    var password by remember {
        mutableStateOf("")
    }
    val visualTransformation by remember(masked) {
        if (masked)
            mutableStateOf(PasswordVisualTransformation())
        else
            mutableStateOf(VisualTransformation.None)
    }
            OutlinedTextField(
                value = password,
                onValueChange = { newText ->
                    password = newText
                },
                visualTransformation = visualTransformation,
                trailingIcon = {
                    if (masked) {
                        IconButton(onClick = {
                            masked = false
                        }) { Icon(imageVector = Icons.Filled.VisibilityOff, contentDescription = null) }
                    } else {
                        IconButton(onClick = { masked = true }) {
                            Icon(imageVector = Icons.Filled.Visibility, contentDescription = null)
                        }
                    }
                },

                label = { Text(text = "Password") },
                singleLine = true,
                modifier = Modifier
                    .fillMaxWidth(.1f),
            )
}
talhatek
  • 320
  • 2
  • 6
  • I managed to solve it! I had set the boolean correct and everything correct, however the problem was I forgot to add .Value to the variable inside the if statments. By doing this it solved the initial problem. Appreciate the feedback nonetheless! – Josef M Jun 30 '22 at 14:35