papilo
papilo

Reputation: 221

Show/Hide Passwords in Flutter's TextFormField

I'm working on a TextFormField to accept passwords. I have set the suffix icon to have IconButton child to detect on click events and to toggle the obscuretext attribute of the TextFormField. The callback function for the iconButton gets called but the TextFormField doesn't get repainted. Any ideas on how to solve this?

static Widget buildTextFormField(String id, 
                               FormFieldValidator<String> validateField,
                               FormFieldSetter<String> saveField,
                               InputDecoration decoration,
                               EdgeInsetsGeometry paddingInfo,
                               EdgeInsetsGeometry marginInfo,
                               TextInputType keyboardType,
                               {bool obscureField:false, double width:328.0,
                                TextEditingController controller}
  ){
return Container(
  padding: paddingInfo,
  margin: marginInfo,
  width: width,
  child: TextFormField(
    key: Key(id),
    obscureText: obscureField,
    validator: validateField,
    onSaved: saveField,
    keyboardType: keyboardType,
    decoration: decoration,
    controller: controller,
  ),
);

}

InputDecoration passwordDecoration = InputDecoration(
   hintText: 'Password',
   labelText: 'Enter your password',
   suffixIcon:
      IconButton(
         icon: Icon(
            _passwordVisible ? Icons.visibility : Icons.visibility_off,
            semanticLabel: _passwordVisible ? 'hide password' : 'show password',
         ),
         onPressed: () {
            setState(() {
               _passwordVisible ^= true;
               //print("Icon button pressed! state: $_passwordVisible"); //Confirmed that the _passwordVisible is toggled each time the button is pressed.
            });
         }),
   labelStyle: TextStyle(
      fontFamily: 'Roboto Medium',
      fontSize: 12.0,
      color: Color(0x99000000),
      letterSpacing: 0.4,
   ),
);
final passwordPaddingInfo = const EdgeInsets.only(top: 15.0, bottom:15.0,
                                                  left: 22.0, right:25.0);
this._passwordField = AdministrationComponents.
buildTextFormField('passwordField', validatePassword,
   (value) => _password = value, passwordDecoration, passwordPaddingInfo,
   null, null, controller:_passwordController,
   obscureField: !_passwordVisible);

Upvotes: 20

Views: 21598

Answers (7)

Fahad Sparrow
Fahad Sparrow

Reputation: 17

class PasswordInput extends StatelessWidget {
  final TextEditingController controller;
  final ValueNotifier<bool> _obscureTextNotifier = ValueNotifier(true);

  PasswordInput({super.key, required this.controller});

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.3),
            spreadRadius: 2,
            blurRadius: 10,
            offset: const Offset(0.1, 2),
          ),
        ],
        borderRadius: BorderRadius.circular(10),
      ),
      child: ValueListenableBuilder<bool>(
          valueListenable: _obscureTextNotifier,
          builder: (context, obscureText, child) {
            return TextFormField(
              controller: controller,
              obscureText: obscureText,
              decoration: InputDecoration(
                  fillColor: Colors.white,
                  filled: true,
                  labelText: 'Password',
                  labelStyle: TextStyle(color: Colors.black),
                  suffixIcon: IconButton(
                    onPressed: () {
                      _obscureTextNotifier.value = !obscureText;
                    },
                    icon: Icon(
                        obscureText ? Icons.visibility_off : Icons.visibility),
                  ),
                  enabledBorder: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(10),
                      borderSide: BorderSide(color: Colors.transparent)),
                  focusedBorder: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(10),
                      borderSide: BorderSide(color: Colors.transparent))),
            );
          }),
    );
  }
}

Upvotes: 0

Samarth Sinha
Samarth Sinha

Reputation: 1

Try this.

I have used obscureText for hiding the text

import 'package:flutter/material.dart';

class PasswordTextFiled extends StatefulWidget {
  const PasswordTextFiled({super.key});

  @override
  State<PasswordTextFiled> createState() => _PasswordTextFiledState();
}

class _PasswordTextFiledState extends State<PasswordTextFiled> {
  bool isPasswordVisible = true;
  @override
  Widget build(BuildContext context) {
    return TextField(
      onChanged: (value) {},
      obscureText: isPasswordVisible,
      decoration: InputDecoration(
        suffixIcon: IconButton(
            onPressed: () {
              setState(() {
                isPasswordVisible = !isPasswordVisible;
              });
            },
            icon: Icon(
              isPasswordVisible
                  ? Icons.visibility_outlined
                  : Icons.visibility_off_outlined,
            )),
        label: const Text(
          "Password",
        ),
      ),
    );
  }
}

Upvotes: 0

Alan John
Alan John

Reputation: 777

Show/Hide Passwords in Flutter's TextFormField

Step 1:

bool _obscureText = true;

Step 2:

void _toggle() {
    setState(() {
      _obscureText = !_obscureText;
    });
  }

Step 3:

 TextField(
                controller: password,
                style: TextStyle(fontSize: 16.0),
                obscureText: _obscureText,
                decoration: new InputDecoration(
                  border: InputBorder.none,
                  focusedBorder: InputBorder.none,
                  enabledBorder: InputBorder.none,
                  errorBorder: InputBorder.none,
                  disabledBorder: InputBorder.none,
                  hintText: "Password",
                  suffixIcon: InkWell(
                    onTap: _toggle,
                    child: Icon(
                      _obscureText
                          ? FontAwesomeIcons.eye
                          : FontAwesomeIcons.eyeSlash,
                      size: 15.0,
                      color: Colors.black,
                    ),
                  ),
                ),
              ),

Upvotes: 9

Genzo
Genzo

Reputation: 55

This is the Password dart i use

import 'package:flutter/material.dart';
class LoginPass extends StatefulWidget {
LoginPass(this.controllerUpass);

  final Function controllerUpass;

  @override
  _LoginPassState createState() => _LoginPassState();
}

class _LoginPassState extends State<LoginPass> {
  bool _isHidden = true;
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.fromLTRB(0, 30, 0, 10),
      child: Container(
        height: 35,
        child: Center(
          child: Padding(
            padding: const EdgeInsets.only(left: 20),
            child: TextField(
              obscureText: _isHidden,
              onChanged: (value) {
                widget.controllerUpass(value);
              },
              decoration: InputDecoration(
                  hintText: 'Password',
                  border: InputBorder.none,
                  focusedBorder: InputBorder.none,
                  enabledBorder: InputBorder.none,
                  errorBorder: InputBorder.none,
                  disabledBorder: InputBorder.none,
                  suffixIcon: GestureDetector(
                    onTap: () {
                      setState(() {
                        _isHidden = !_isHidden;
                      });
                    },
                    child: _isHidden
                        ? Icon(
                            Icons.remove_red_eye_sharp,
                            color: Colors.blue,
                          )
                        : Icon(
                            Icons.remove_red_eye,
                            color: Colors.red,
                          ),
                  )),
            ),
          ),
        ),
        decoration: BoxDecoration(
          boxShadow: <BoxShadow>[
            BoxShadow(
              color: Colors.black26,
              spreadRadius: 1,
              blurRadius: 3,
              offset: Offset(0, 3),
            ),
          ],
          color: Colors.white,
          borderRadius: BorderRadius.all(Radius.circular(3)),
        ),
      ),
    );
  }
}

In Main call

LoginPass(controllerUpass),

Upvotes: -1

TipVisor
TipVisor

Reputation: 1092

Try to this

 bool _showPassword = false;
  void _togglevisibility() {
    setState(() {
      _showPassword = !_showPassword;
    });
  }

Textform field code

child: TextFormField(
                                controller: _passwordController,
                                obscureText: !_showPassword,
                                cursorColor: Colors.red,
                                style: TextStyle(color: Colors.white),
                                decoration: InputDecoration(
                                  hintText: "Password",
                                  border: InputBorder.none,
                                  suffixIcon: GestureDetector(
                                    onTap: () {
                                      _togglevisibility();
                                    },
                                    child: Icon(
                                      _showPassword ? Icons.visibility : Icons
                                          .visibility_off, color: Colors.red,),
                                  ),
                                ),
                              ),

Upvotes: 18

papilo
papilo

Reputation: 221

Thanks @ShyjuM and @ diegoveloper! I see what I was doing wrong - I was calling the buildTextFormField in the constructor of my State class and not in the build method. Moving the call to buildTextFormField inside the build method fixed it. Thanks again for all of your help!

Upvotes: 2

diegoveloper
diegoveloper

Reputation: 103401

You have some errors in your code.

Replace this :

_passwordVisible > Icons.visibility : Icons.visibility_off,

and

_passwordVisible ^= true;

By this:

_passwordVisible ? Icons.visibility : Icons.visibility_off,

and

  _passwordVisible = !_passwordVisible;

Upvotes: 1

Related Questions