[英]How to show/hide password in TextFormField?
Currently I have my password TextFormField
like this:目前我的密码
TextFormField
是这样的:
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
?我可以在
TextFormField
里面做吗? Or I will have to make a Stack
widget to get my required UI.或者我将不得不制作一个
Stack
小部件来获得我所需的 UI。 And how will the condition be made regarding obscureText
true/false?以及关于
obscureText
真/假的条件将如何制定?
I have created a solution as per @Hemanth Raj but in a more robust way.我已经按照@Hemanth Raj 创建了一个解决方案,但方式更强大。
First declare a bool
variable _passwordVisible
.首先声明一个
bool
变量_passwordVisible
。
Initiate _passwordVisible
to false
in initState()
启动
_passwordVisible
以false
的initState()
@override
void initState() {
_passwordVisible = false;
}
Following is the TextFormField
widget :以下是
TextFormField
小部件:
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;
});
},
),
),
);
First make you widget StatefulWidget
if it is a StatelessWidget
.首先让你小部件
StatefulWidget
如果它是一个StatelessWidget
。
Then have a variable bool _obscureText
and pass it to your TextFormField
.然后有一个变量
bool _obscureText
并将其传递给您的TextFormField
。 The toggle it with setState
as required.根据需要使用
setState
切换它。
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!希望这可以帮助!
With a credit goes to X-Wei , you can create the widget as a separate password.dart
:归功于X-Wei ,您可以将小部件创建为单独的
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;
});
},
),
I did it with holding and releasing the longTap:我通过按住并释放 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);
},
);
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;
});
}
This approach is being used in of my packages https://pub.dev/packages/passwordfield我的包https://pub.dev/packages/passwordfield正在使用这种方法
The output of the above code上面代码的输出
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();
});
},
),
],),),
),
);
}
}
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!希望这可以帮助!
This solution prevents taps in the suffixIcon from giving focus to the TextField, but if the TextField was focused and user wants to reveal/hide the password, then focus is not lost.此解决方案可防止在 suffixIcon 中点击将焦点放在 TextField 上,但如果 TextField 已聚焦并且用户想要显示/隐藏密码,则不会丢失焦点。
import 'package:flutter/material.dart';
class PasswordField extends StatefulWidget {
const PasswordField({Key? key}) : super(key: key);
@override
_PasswordFieldState createState() => _PasswordFieldState();
}
class _PasswordFieldState extends State<PasswordField> {
final textFieldFocusNode = FocusNode();
bool _obscured = false;
void _toggleObscured() {
setState(() {
_obscured = !_obscured;
if (textFieldFocusNode.hasPrimaryFocus) return; // If focus is on text field, dont unfocus
textFieldFocusNode.canRequestFocus = false; // Prevents focus if tap on eye
});
}
@override
Widget build(BuildContext context) {
return TextField(
keyboardType: TextInputType.visiblePassword,
obscureText: _obscured,
focusNode: textFieldFocusNode,
decoration: InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.never, //Hides label on focus or if filled
labelText: "Password",
filled: true, // Needed for adding a fill color
fillColor: Colors.grey.shade800,
isDense: true, // Reduces height a bit
border: OutlineInputBorder(
borderSide: BorderSide.none, // No border
borderRadius: BorderRadius.circular(12), // Apply corner radius
),
prefixIcon: Icon(Icons.lock_rounded, size: 24),
suffixIcon: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 4, 0),
child: GestureDetector(
onTap: _toggleObscured,
child: Icon(
_obscured
? Icons.visibility_rounded
: Icons.visibility_off_rounded,
size: 24,
),
),
),
),
);
}
}
Here's a simpler example with built-in material design icons:这是一个带有内置材料设计图标的简单示例:
child: TextFormField(
decoration: InputDecoration(
fillColor: Color(0xFFFFFFFF), filled: true,
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFF808080)),
),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_showPassword = !_showPassword;
});
},
child: Icon(
_showPassword ? Icons.visibility : Icons.visibility_off,
),
),
labelText: 'Password'),
obscureText: !_showPassword,
),
Thank @Parikshit Chalke for answer.感谢@Parikshit Chalke 的回答。 However,
setState
is quite expensive call if your only want to update your TextFormField
and IconButton
.但是,如果您只想更新您的
TextFormField
和IconButton
, setState
是非常昂贵的调用。 Instead, wrap it inside StatefulBuilder and have only child items updated.相反,将它包装在StatefulBuilder 中并且只更新子项。
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,
);
}),
],
);
}
}
○ Just a Simple 3 Steps you can follow and password Show/Hide done. ○ 只需简单的 3 个步骤,您就可以按照密码显示/隐藏完成。
Step 1:create variable第一步:创建变量
bool _isHidden = true;
Step 2: Magical Step, make the icon clickable and see/hide the password.第 2 步:魔法步骤,使图标可点击并查看/隐藏密码。
Now I will wrap the icon with InkWell which will make it clickable.现在我将用 InkWell 包裹图标,使其可点击。 So, when we will click on that it will toggle the obscureText the argument between true and false.
因此,当我们点击它时,它会在真假之间切换模糊文本的参数。
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).secondaryHeaderColor,
body: Center(
child: Container(
height: 55,
alignment: Alignment.center,
padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
child: TextField(
obscureText: _isHidden,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
suffix: InkWell(
onTap: _togglePasswordView, /// This is Magical Function
child: Icon(
_isHidden ? /// CHeck Show & Hide.
Icons.visibility :
Icons.visibility_off,
),
),
/*icon: Icon(
Icons.password_sharp,
color: Colors.black,
),*/
),
),
),
),
);
}
Step 3: Create This the Magical Function.第 3 步:创建这个神奇的功能。
void _togglePasswordView() {
setState(() {
_isHidden = !_isHidden;
});
}
☻♥Done. ☻♥完成。
//Password
const TextField(
obscureText: true, //for hide Password
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock_outline),
hintText: 'Password'),
),
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;
},
);
},
),
),
);```
I have more useful solution.我有更有用的解决方案。 You can use Provider and listen TextFormField with Consumer Widget
您可以使用 Provider 并通过 Consumer Widget 收听 TextFormField
obscure_text_state.dart晦涩的文本状态.dart
import 'package:flutter/material.dart';
class ObscureTextState with ChangeNotifier {
bool _isTrue = true;
bool get isTrue => _isTrue;
get switchObsIcon {
return _isTrue ? Icon(Icons.visibility_off) : Icon(Icons.visibility);
}
void toggleObs() {
_isTrue = !_isTrue;
notifyListeners();
}
}
Then you should listen that state with Consumer where TextFromField is.然后,您应该使用 TextFromField 所在的 Consumer 收听该状态。
Consumer<ObscureTextState>(
builder: (context, obs, child) {
return TextFormField(
controller: _passwordController,
validator: (value) {
if (value.isEmpty) {
return "Alan boş bırakılamaz!";
} else if (value.length < 6) {
return "Şifre en az 6 haneden oluşmalıdır.";
} else {
return null;
}
},
obscureText:
Provider.of<ObscureTextState>(context, listen: false)
.isTrue,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock),
suffixIcon: IconButton(
onPressed: () {
Provider.of<ObscureTextState>(context, listen: false)
.toggleObs();
},
icon: Provider.of<ObscureTextState>(context,
listen: false)
.switchObsIcon,
),
hintText: "Şifre",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0))),
);
},
),
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.