【问题标题】:How to visible/hide password in flutter?如何在颤动中显示/隐藏密码?
【发布时间】:2021-02-26 08:49:04
【问题描述】:

我已经为我的应用程序创建了一个登录屏幕,但是在密码字段中,我想要一个功能,比如当我输入密码时,它是 * 格式,当用户点击它时,右侧的图标会显示密码,我创建了它的代码但是当我单击密码字段时,该图标变得不可见并且当密码字段失去焦点时,该图标再次出现,那么即使密码字段处于焦点,如何始终显示该图标? 我提供了一个快照以便于理解问题。

这是我的登录屏幕代码....

import 'package:flutter/material.dart';
import 'package:email_validator/email_validator.dart';
import 'package:secret_keeper/screens/home_screen/Home.dart';
import 'package:secret_keeper/screens/home_screen/passwords/PasswordsNavigation.dart';
import 'package:secret_keeper/screens/signup_page/SignupPage.dart';

class LoginPage extends StatefulWidget{
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {

  String _emailID, _password = "",_email = "abc@gmail.com", _pass = "Try.t.r.y@1";
  bool _obscureText = true;
  final _formKey = GlobalKey<FormState>();
  
  void _toggle(){
    setState(() {
      _obscureText = !_obscureText;
    });
  }

  void validateLogin(){
    if(_formKey.currentState.validate()){
      _formKey.currentState.save();
      if(_emailID == _email && _password == _pass){
        Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => Home()));
      }
    }
  }

  Widget emailInput(){
    return TextFormField(
      keyboardType: TextInputType.emailAddress,
      decoration: InputDecoration(
        labelText: "Email ID",
        labelStyle: TextStyle(fontSize: 14,color: Colors.grey.shade400),
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: BorderSide(
            color: Colors.grey.shade300,
          ),
        ),
        focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(10),
            borderSide: BorderSide(
              color: Colors.red,
            )
        ),
      ),
      validator: (email) {
        if (email.isEmpty)
          return 'Please Enter email ID';
        else if (!EmailValidator.validate(email))
          return 'Enter valid email address';
        else
          return null;
      },
      onSaved: (email)=> _emailID = email,
      textInputAction: TextInputAction.next,
    );
  }

  Widget passInput(){
    return TextFormField(
      keyboardType: TextInputType.text,
      decoration: InputDecoration(
        labelText: "Password",
        labelStyle: TextStyle(fontSize: 14,color: Colors.grey.shade400),
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: BorderSide(
            color: Colors.grey.shade300,
          ),
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: BorderSide(
            color: Colors.red,
          )
        ),
        suffixIcon: IconButton(
          icon: Icon(
            _obscureText ? Icons.visibility : Icons.visibility_off,
          ),
          onPressed: _toggle,
        ),
      ),
      validator: (password){
        Pattern pattern =
            r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#\$&*~]).{8,}$';
        RegExp regex = new RegExp(pattern);
        if (password.isEmpty){
          return 'Please Enter Password';
        }else if (!regex.hasMatch(password))
          return 'Enter valid password';
        else
          return null;
      },
      onSaved: (password)=> _password = password,
      textInputAction: TextInputAction.done,
      obscureText: _obscureText,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomPadding: false,
      backgroundColor: Colors.white,
      body: SafeArea(
        child: Container(
          padding: EdgeInsets.only(left: 16,right: 16),
          child: Form(
            key: _formKey,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    SizedBox(height: 50,),
                    Text("Welcome,",style: TextStyle(fontSize: 26,fontWeight: FontWeight.bold),),
                    SizedBox(height: 6,),
                    Text("Sign in to continue!",style: TextStyle(fontSize: 20,color: Colors.grey.shade400),),
                  ],
                ),
                Column(
                  children: <Widget>[
                    emailInput(),
                    SizedBox(height: 16,),
                    passInput(),
                    SizedBox(height: 12,),
                    Align(
                      alignment: Alignment.topRight,
                      child: Text("Forgot Password ?",style: TextStyle(fontSize: 14,fontWeight: FontWeight.w600),),
                    ),
                    SizedBox(height: 30,),
                    Container(
                      height: 50,
                      width: double.infinity,
                      child: FlatButton(
                        onPressed: validateLogin,
                        padding: EdgeInsets.all(0),
                        child: Ink(
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(6),
                            gradient: LinearGradient(
                              begin: Alignment.centerLeft,
                              end: Alignment.centerRight,
                              colors: [
                                Color(0xffff5f6d),
                                Color(0xffff5f6d),
                                Color(0xffffc371),
                              ],
                            ),
                          ),
                          child: Container(
                            alignment: Alignment.center,
                            constraints: BoxConstraints(maxWidth: double.infinity,minHeight: 50),
                            child: Text("Login",style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),textAlign: TextAlign.center,),
                          ),
                        ),
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(6),
                        ),
                      ),
                    ),
                    SizedBox(height: 16,),
                    Container(
                      height: 50,
                      width: double.infinity,
                      child: FlatButton(
                        onPressed: (){},
                        color: Colors.indigo.shade50,
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(6),
                        ),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Image.asset("assets/images/facebook.png",height: 18,width: 18,),
                            SizedBox(width: 10,),
                            Text("Connect with Facebook",style: TextStyle(color: Colors.indigo,fontWeight: FontWeight.bold),),
                          ],
                        ),
                      ),
                    ),
                    SizedBox(height: 16,),
                    Container(
                      height: 50,
                      width: double.infinity,
                      child: FlatButton(
                        onPressed: (){},
                        color: Colors.indigo.shade50,
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(6),
                        ),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Image.asset("assets/images/facebook.png",height: 18,width: 18,),
                            SizedBox(width: 10,),
                            Text("Connect with Facebook",style: TextStyle(color: Colors.indigo,fontWeight: FontWeight.bold),),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
                Padding(
                  padding: EdgeInsets.only(bottom: 10),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text("Don't have an account?",style: TextStyle(fontWeight: FontWeight.bold),),
                      SizedBox(width: 5,),
                      GestureDetector(
                        onTap: (){
                          Navigator.push(context, MaterialPageRoute(builder: (context){
                            return SignupPage();
                          }));
                        },
                        child: Text("Sign up",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.red),),
                      )
                    ],
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter


    【解决方案1】:

    这里有两种情况

    1. 如果您希望您的后缀图标颜色始终为灰色,您可以赋予图标的颜色属性,例如:

    密码显示隐藏按钮

    var passShowButton = GestureDetector(
          onLongPressEnd: outContact,
          onTapDown: inContact, //call this method when incontact
          onTapUp:
              outContact, //call this method when contact with screen is removed
          child: Icon(
            getXHelper.isEmailPasswordUpdate.isTrue
                ? AppIcons.hidePassword
                : AppIcons.hidePassword,
            size: 18,
            color:Colors.grey
          ),
        );
    

    文本字段

    TextField(
        obscureText: getXHelper.isPassInvisible  ,
        autocorrect: false,
        textAlignVertical: TextAlignVertical.bottom,
        decoration: InputDecoration(
          enabled: true,
          errorBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: AppColors.primary)),
          enabledBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: AppColors.primary)),
          focusedBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: AppColors.primary)),
          border: UnderlineInputBorder(
              borderSide: BorderSide(color: AppColors.primary)),
          fillColor: Colors.white,
          filled: true,
          isDense: true,
          prefixIconConstraints: BoxConstraints(maxHeight: 18, minHeight: 18),
          hintText: "Password",
          prefixIcon: Padding(
            padding: const EdgeInsets.only(top: 0, right: 12, bottom: 0),
            child: Icon(Icons.lock, size: 18, color: Colors.grey),
          ),
          suffixIcon: passShowButton,
        ),
        cursorColor: Colors.black,
        style: TextStyle(
            color: Colors.black, fontFamily: AppFontFamily.fontFamily),
      )
    
    1. 如果您希望您的应用程序的后缀图标颜色-主颜色,将在文本字段焦点时改变颜色,例如:

    密码显示隐藏按钮

    var passShowButton = GestureDetector(
              onLongPressEnd: outContact,
              onTapDown: inContact, //call this method when incontact
              onTapUp:
                  outContact, //call this method when contact with screen is removed
              child: Icon(
                getXHelper.isEmailPasswordUpdate.isTrue
                    ? AppIcons.hidePassword
                    : AppIcons.hidePassword,
                size: 18,
              ),
            );
    
    TextField(
        obscureText: getXHelper.isPassInvisible  ,
        autocorrect: false,
        textAlignVertical: TextAlignVertical.bottom,
        decoration: InputDecoration(
          enabled: true,
          errorBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: AppColors.primary)),
          enabledBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: AppColors.primary)),
          focusedBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: AppColors.primary)),
          border: UnderlineInputBorder(
              borderSide: BorderSide(color: AppColors.primary)),
          fillColor: Colors.white,
          filled: true,
          isDense: true,
          prefixIconConstraints: BoxConstraints(maxHeight: 18, minHeight: 18),
          hintText: "Password",
          prefixIcon: Padding(
            padding: const EdgeInsets.only(top: 0, right: 12, bottom: 0),
            child: Icon(Icons.lock, size: 18),
          ),
          suffixIcon: passShowButton,
        ),
        cursorColor: Colors.black,
        style: TextStyle(
            color: Colors.black, fontFamily: AppFontFamily.fontFamily),
      )
    

    【讨论】:

      【解决方案2】:

      完整的例子。这里的主登录是:

      1. 采用布尔参数来检测文本是否模糊
      2. 根据该布尔值更改后缀图标
      3. 更改后缀项单击时的布尔值

      下面我给出了该任务的完整示例。

      bool _passwordInVisible = true; //a boolean value
      
      TextFormField buildPasswordFormField() {
      return TextFormField(
        obscureText: _passwordInVisible,
        onSaved: (newValue) => registerRequestModel.password = newValue,
        onChanged: (value) {
          if (value.isNotEmpty) {
            removeError(error: kPassNullError);
          } else if (value.length >= 8) {
            removeError(error: kShortPassError);
          }
          return null;
        },
        validator: (value) {
          if (value.isEmpty) {
            addError(error: kPassNullError);
            return "";
          } else if (value.length < 8) {
            addError(error: kShortPassError);
            return "";
          }
          return null;
        },
        textInputAction: TextInputAction.next,
        decoration: InputDecoration(
          border: OutlineInputBorder(),
          labelText: "Password",
          hintText: "Enter your password",
          contentPadding: new EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
          floatingLabelBehavior: FloatingLabelBehavior.always,
          suffixIcon: IconButton(
            icon: Icon(
              _passwordInVisible ? Icons.visibility_off : Icons.visibility, //change icon based on boolean value
              color: Theme.of(context).primaryColorDark, 
            ),
            onPressed: () {
              setState(() {
                _passwordInVisible = !_passwordInVisible; //change boolean value
              });
            },
          ),
        ),
      );
      

      }

      【讨论】:

      • 最好加上一些描述。
      【解决方案3】:

      您可以将文本字段和图标按钮放在一个堆栈中 将此代码替换为您的密码文本字段。 您可以将图标按钮位置更改为您想要的位置。

      Stack(
            children: [
              TextFormField(
                keyboardType: TextInputType.text,
                decoration: InputDecoration(
                  labelText: "Password",
                  labelStyle:
                      TextStyle(fontSize: 14, color: Colors.grey.shade400),
                  enabledBorder: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(10),
                    borderSide: BorderSide(
                      color: Colors.grey.shade300,
                    ),
                  ),
                  focusedBorder: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(10),
                      borderSide: BorderSide(
                        color: Colors.red,
                      )),
                ),
                validator: (password) {
                  Pattern pattern =
                      r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#\$&*~]).{8,}$';
                  RegExp regex = new RegExp(pattern);
                  if (password.isEmpty) {
                    return 'Please Enter Password';
                  } else if (!regex.hasMatch(password))
                    return 'Enter valid password';
                  else
                    return null;
                },
                onSaved: (password) => _password = password,
                textInputAction: TextInputAction.done,
                obscureText: _obscureText,
              ),
              Positioned(
                top: 2,
                right: 10,
                child: IconButton(
                    icon: Icon(
                      _obscureText ? Icons.visibility : Icons.visibility_off,
                    ),
                    onPressed: () {
                      setState(() {
                        _obscureText = !_obscureText;
                      });
                    }),
              ),
            ],
          ),
      

      【讨论】:

      • 虽然起初这似乎是一个很好的解决方案,但我不会推荐这种方法而不是已经提供的 suffixIcon。当提示动画到 TextField 的顶部时,此解决方案会出现问题,这反过来会导致小部件的高度发生变化,进而导致图标不在 TextField 的中心。
      【解决方案4】:

      我刚刚复制并运行了您的代码,它运行良好。当密码字段具有焦点时,该图标可见。您可能应该检查您的颤振版本,或者它可能是您的模拟器设备。
      flutter --version
      Flutter 1.22.3 • 通道稳定 • https://github.com/flutter/flutter.git
      框架 • 修订 8874f21e79(2 周前) • 2020-10-29 14:14:35 -0700
      引擎 • 修订版 a1440ca392
      工具 • Dart 2.10.3

      【讨论】:

      • 我也在使用相同版本的flutter 'Flutter 1.22.3 • 通道稳定 • github.com/flutter/flutter.git 框架 • 修订版8874f21e79(2 周前) • 2020-10-29 14:14:35 -0700引擎 • 修订版 a1440ca392 工具 • Dart 2.10.3 '
      【解决方案5】:

      实际上,后缀图标是可见的,但是当我单击 TextFormField 时,图标颜色会变为白色,因此我只需在图标字段中添加一个颜色属性并为图标赋予黑色,因此即使文本字段处于焦点位置,它的颜色也会保持不变黑色。

      【讨论】:

        猜你喜欢
        • 2011-06-10
        • 2018-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-01
        • 2018-01-15
        • 1970-01-01
        • 2015-09-26
        相关资源
        最近更新 更多