It took 4 days search to find this, so I'm sharing it with the community, credit goes to X-Wei.
Problem:
Creating a password field in flutter with preview check as below:
Solution:
- Define
StatefulWidget
to for a newwidget
namedPasswordField
as below:
class PasswordField extends StatefulWidget {
const PasswordField({
});
@override
_PasswordFieldState createState() => new _PasswordFieldState();
}
class _PasswordFieldState extends State<PasswordField> {
@override
Widget build(BuildContext context) {
return TextFormField(
);
}
- Define the required
widget
parameter in theStatefulWidget
class above, as below:
const PasswordField({
this.fieldKey,
this.maxLength,
this.hintText,
this.labelText,
this.helperText,
this.onSaved,
this.validator,
this.onFieldSubmitted,
});
final Key fieldKey;
final int maxLength;
final String hintText;
final String labelText;
final String helperText;
final FormFieldSetter<String> onSaved;
final FormFieldValidator<String> validator;
final ValueChanged<String> onFieldSubmitted;
In the widget
State
return aTextFormField
that has adecoration: InputDecoration
In the
decoration: InputDecoration
define asuffixIcon: GestureDetector
that has achild: Icon
andonTap
function that change the state, like below:
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child: Icon(_obscureText ? Icons.visibility : Icons.visibility_off),
),
- So, the full
StatefulWidget
of ourPasswordField
, became as belowpassword.dart
:
import 'package:flutter/material.dart';
class PasswordField extends StatefulWidget {
const PasswordField({
this.fieldKey,
this.maxLength,
this.hintText,
this.labelText,
this.helperText,
this.onSaved,
this.validator,
this.onFieldSubmitted,
});
final Key fieldKey;
final int maxLength;
final String hintText;
final String labelText;
final String helperText;
final FormFieldSetter<String> onSaved;
final FormFieldValidator<String> validator;
final ValueChanged<String> onFieldSubmitted;
@override
_PasswordFieldState createState() => _PasswordFieldState();
}
class _PasswordFieldState extends State<PasswordField> {
bool _obscureText = true;
@override
Widget build(BuildContext context) {
return TextFormField(
key: widget.fieldKey,
obscureText: _obscureText,
maxLength: widget.maxLength ?? 8, // if not provided by the user, then it is 8
onSaved: widget.onSaved,
validator: widget.validator,
onFieldSubmitted: widget.onFieldSubmitted,
decoration: InputDecoration(
border: const UnderlineInputBorder(),
filled: true,
hintText: widget.hintText,
labelText: widget.labelText,
helperText: widget.helperText,
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child: Icon(_obscureText ? Icons.visibility : Icons.visibility_off),
),
),
);
}
}
- Call this widget in your screen as any other widget, just like:
child: PasswordField( ),
- Before calling this child, you need to define the below:
String _password;
final _passwordFieldKey = GlobalKey<FormFieldState<String>>();
- The full code to call it, can be as:
import 'package:flutter/material.dart';
import 'package:myApp/password.dart';
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => new _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _email, _password;
final _passwordFieldKey = GlobalKey<FormFieldState<String>>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
validator: (input) {
if(input.isEmpty){
return 'Provide an email';
}
},
decoration: InputDecoration(
labelText: 'Email'
),
onSaved: (input) => _email = input,
),
PasswordField(
fieldKey: _passwordFieldKey,
helperText: 'No more than 8 characters.',
labelText: 'Password *',
onSaved: (input) => _password = input,
),
SizedBox(height: 24.0),
RaisedButton(
onPressed: signIn,
child: Text('Sign in'),
),
],
)
),
);
}
void signIn() async {
if(_formKey.currentState.validate()){
_formKey.currentState.save();
print("email: $_email, password: $_password");
}
}
}