How to show/hide password in TextFormField?

生来就可爱ヽ(ⅴ<●) 提交于 2021-02-05 14:20:16

问题


Currently I have my password TextFormField like this:

TextFormField(
  decoration: const InputDecoration(
      labelText: 'Password',
      icon: const Padding(
        padding: const EdgeInsets.only(top: 15.0),
        child: const Icon(Icons.lock),
      )),
  validator: (val) => val.length < 6 ? 'Password too short.' : null,
  onSaved: (val) => _password = val,
  obscureText: true,
);

I want a button like interaction which will make password visible and invisible. Can I do it inside TextFormField? Or I will have to make a Stack widget to get my required UI. And how will the condition be made regarding obscureText true/false?


回答1:


First make you widget StatefulWidget if it is a StatelessWidget.

Then have a variable bool _obscureText and pass it to your TextFormField. The toggle it with setState as required.

Example:

class _FormFieldSampleState extends State<FormFieldSample> {

  // Initially password is obscure
  bool _obscureText = true;

  String _password;

  // Toggles the password show status
  void _toggle() {
    setState(() {
      _obscureText = !_obscureText;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Sample"),
      ),
      body: new Container(
        child: new Column(
          children: <Widget>[
            new TextFormField(
              decoration: const InputDecoration(
                  labelText: 'Password',
                  icon: const Padding(
                      padding: const EdgeInsets.only(top: 15.0),
                      child: const Icon(Icons.lock))),
              validator: (val) => val.length < 6 ? 'Password too short.' : null,
              onSaved: (val) => _password = val,
              obscureText: _obscureText,
            ),
            new FlatButton(
                onPressed: _toggle,
                child: new Text(_obscureText ? "Show" : "Hide"))
          ],
        ),
      ),
    );
  }
}

Hope this helps!




回答2:


I have created a solution as per @Hemanth Raj but in a more robust way.

First declare a bool variable _passwordVisible.

Initiate _passwordVisible to false in initState()

@override
  void initState() {
    _passwordVisible = false;
  }

Following is the TextFormField widget :

TextFormField(
   keyboardType: TextInputType.text,
   controller: _userPasswordController,
   obscureText: !_passwordVisible,//This will obscure text dynamically
   decoration: InputDecoration(
       labelText: 'Password',
       hintText: 'Enter your password',
       // Here is key idea
       suffixIcon: IconButton(
            icon: Icon(
              // Based on passwordVisible state choose the icon
               _passwordVisible
               ? Icons.visibility
               : Icons.visibility_off,
               color: Theme.of(context).primaryColorDark,
               ),
            onPressed: () {
               // Update the state i.e. toogle the state of passwordVisible variable
               setState(() {
                   _passwordVisible = !_passwordVisible;
               });
             },
            ),
          ),
        );



回答3:


I did it with holding and releasing the longTap:

    bool _passwordVisible;

@override
void initState() {
    _passwordVisible = false;
    super.initState();
}

// ...
TextFormField(
  obscureText: !_passwordVisible,
  decoration: InputDecoration(
    hasFloatingPlaceholder: true,
    filled: true,
    fillColor: Colors.white.withOpacity(0.5),
    labelText: "Password",
    suffixIcon: GestureDetector(
      onLongPress: () {
        setState(() {
          _passwordVisible = true;
        });
      },
      onLongPressUp: () {
        setState(() {
          _passwordVisible = false;
        });
      },
      child: Icon(
          _passwordVisible ? Icons.visibility : Icons.visibility_off),
    ),
  ),
  validator: (String value) {
    if (value.isEmpty) {
      return "*Password needed";
    }
  },
  onSaved: (String value) {
    _setPassword(value);
  },
);



回答4:


Well I personally like to keep the passwords hidden all the time and seen when you want to see them, so this is the approach I use to hide/unhide passwords,Incase you want the password to be visible when the touch is In contact with the hide icon, and hidden as soon as you remove the contact then this is for you

//make it invisible globally
  bool invisible = true;

//wrap your toggle icon in Gesture Detector
  GestureDetector(
   onTapDown: inContact,//call this method when incontact
   onTapUp: outContact,//call this method when contact with screen is removed
   child: Icon(
   Icons.remove_red_eye,
   color: colorButton,
   ),
  ),

  void inContact(TapDownDetails details) {
    setState(() {
      invisible = false;
    });
  }

  void outContact(TapUpDetails details) {
    setState(() {
      invisible=true;
    });
  }

I have also published this as a package here https://pub.dev/packages/passwordfield

The output of the above code




回答5:


With a credit goes to X-Wei, you can create the widget as a separate password.dart:

import 'package:flutter/material.dart';

class PasswordField extends StatefulWidget {
  const PasswordField({
    this.fieldKey,
    this.hintText,
    this.labelText,
    this.helperText,
    this.onSaved,
    this.validator,
    this.onFieldSubmitted,
  });

  final Key fieldKey;
  final String hintText;
  final String labelText;
  final String helperText;
  final FormFieldSetter<String> onSaved;
  final FormFieldValidator<String> validator;
  final ValueChanged<String> onFieldSubmitted;

  @override
  _PasswordFieldState createState() => new _PasswordFieldState();
}

class _PasswordFieldState extends State<PasswordField> {
  bool _obscureText = true;

  @override
  Widget build(BuildContext context) {
    return new TextFormField(
      key: widget.fieldKey,
      obscureText: _obscureText,
      maxLength: 8,
      onSaved: widget.onSaved,
      validator: widget.validator,
      onFieldSubmitted: widget.onFieldSubmitted,
      decoration: new InputDecoration(
        border: const UnderlineInputBorder(),
        filled: true,
        hintText: widget.hintText,
        labelText: widget.labelText,
        helperText: widget.helperText,
        suffixIcon: new GestureDetector(
          onTap: () {
            setState(() {
              _obscureText = !_obscureText;
            });
          },
          child:
          new Icon(_obscureText ? Icons.visibility : Icons.visibility_off),
        ),
      ),
    );
  }
}

Call it as:

  import 'package:my_app/password.dart';

  String _password;
  final _passwordFieldKey = GlobalKey<FormFieldState<String>>();

  PasswordField(
    fieldKey: _passwordFieldKey,
    helperText: 'No more than 8 characters.',
    labelText: 'Password *',
    onFieldSubmitted: (String value) {
      setState(() {
        this._password = value;
      });
    },
  ),



回答6:


class SignIn extends StatefulWidget {

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

class _SignInState extends State<SignIn> {

        // Initially password is obscure
  bool _obscureText = true;
    // Toggles the password show status
  void _togglePasswordStatus() {
    setState(() {
      _obscureText = !_obscureText;
    });
  }
  @override
  Widget build(BuildContext context) {
    return 
    Scaffold(
      backgroundColor: Colors.brown[100],
      appBar: AppBar(
        backgroundColor: Colors.brown[400],
        elevation: 0.0,
        title: Text('Sign In'),
      ),
      body: Container(
        padding: EdgeInsets.symmetric(vertical:20.0,horizontal:50.0),
        child: Form(
          key: _formKey,
          child: Column(children: <Widget>[
            TextFormField(
              decoration: InputDecoration(
                hintText: 'Password',
                suffixIcon:  IconButton(
                  icon:Icon(_obscureText ? Icons.visibility:Icons.visibility_off,),
                   onPressed: _togglePasswordStatus,
                   color: Colors.pink[400],
                   ),
              ),
              validator: (val){
                return
                val.length < 6 ? 'Enter A Password Longer Than 6 Charchters' :null;
              },
              obscureText: _obscureText,
              onChanged: (val){
                setState(() {
                  password = val.trim();
                });
              },
            ),
        ],),),
      ),
    );
  }
}



回答7:


  bool _obscuredText = true; 

  _toggle(){
    setState(() {
      _obscuredText = !_obscuredText;
    });
  }

  Widget _createPassword(){
    return TextField(
      obscureText: _obscuredText,
      cursorColor: Colors.black54,
      style: TextStyle( color: Colors.black54),
      decoration: InputDecoration(
        labelStyle: TextStyle(
            color: Colors.black54
        ),
        focusedBorder: OutlineInputBorder(
            borderSide: BorderSide(
                color: Colors.black54
            )
        ),
        border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(5.0)
        ),
        labelText: 'Contraseña',
        hintText: 'Contraseña',
        suffixIcon: FlatButton(onPressed: _toggle, child:Icon(Icons.remove_red_eye, color: _obscuredText ? Colors.black12 : Colors.black54))
      ),
      onChanged: (value) {
        setState(() {
          _password = value;
        });
      },
    );
  }

Hope this helps!




回答8:


Thank @Parikshit Chalke for answer. However, setState is quite expensive call if your only want to update your TextFormField and IconButton. Instead, wrap it inside StatefulBuilder and have only child items updated.

Example solution:

import 'package:flutter/material.dart';

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  // initially password is invisible
  bool _passwordVisible = false;
  String _password;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // other widget that does not need update when password visibility is toggled
        Text("I do not require update"),
        
        StatefulBuilder(builder: (_context, _setState) {
          // only following widget gets update when _setState is used
          return TextFormField(
            decoration: InputDecoration(
              suffixIcon: IconButton(
                icon: Icon(
                  _passwordVisible ? Icons.visibility : Icons.visibility_off,
                ),
                onPressed: () {
                  // use _setState that belong to StatefulBuilder
                  _setState(() {
                    _passwordVisible = !_passwordVisible;
                  });
                },
              ),
              labelText: 'Password',
              icon: const Padding(
                padding: const EdgeInsets.only(top: 15.0),
                child: const Icon(Icons.lock),
              ),
            ),
            validator: (val) => val.length < 6 ? 'Password too short.' : null,
            onSaved: (val) => _password = val,
            obscureText: true,
          );
        }),
      ],
    );
  }
}




回答9:


    TextFormFeild(
    decoration:InputDecoration(
     icon: _isSecurityIcon == true
  ? IconButton(
   icon: Icon(Icons.visibility_off_outlined),
onPressed: () {
   setState(() {
_isSecurityIcon = false;
   });
  },
)
: IconButton(
icon: Icon(Icons.visibility_outlined),
onPressed: () {
setState(
() {
_isSecurityIcon = true;
    },
    );
    },
   ),
   ),
  );```


来源:https://stackoverflow.com/questions/49125064/how-to-show-hide-password-in-textformfield

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!