Unverified Commit b6cca392 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Updated the gallery text fields demo (#15362)

parent c345c1bb
......@@ -23,6 +23,60 @@ class PersonData {
String password = '';
}
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),
),
),
);
}
}
class TextFormFieldDemoState extends State<TextFormFieldDemo> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
......@@ -36,6 +90,7 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
bool _autovalidate = false;
bool _formWasEdited = false;
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> _passwordFieldKey = new GlobalKey<FormFieldState<String>>();
final _UsNumberTextInputFormatter _phoneNumberFormatter = new _UsNumberTextInputFormatter();
......@@ -64,7 +119,7 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
_formWasEdited = true;
final RegExp phoneExp = new RegExp(r'^\(\d\d\d\) \d\d\d\-\d\d\d\d$');
if (!phoneExp.hasMatch(value))
return '(###) ###-#### - Please enter a valid US phone number.';
return '(###) ###-#### - Enter a US phone number.';
return null;
}
......@@ -72,9 +127,9 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
_formWasEdited = true;
final FormFieldState<String> passwordField = _passwordFieldKey.currentState;
if (passwordField.value == null || passwordField.value.isEmpty)
return 'Please choose a password.';
return 'Please enter a password.';
if (passwordField.value != value)
return 'Passwords don\'t match';
return 'The passwords don\'t match';
return null;
}
......@@ -118,11 +173,16 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
key: _formKey,
autovalidate: _autovalidate,
onWillPop: _warnUserAboutInvalidData,
child: new ListView(
child: new SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
const SizedBox(height: 24.0),
new TextFormField(
decoration: const InputDecoration(
border: const UnderlineInputBorder(),
filled: true,
icon: const Icon(Icons.person),
hintText: 'What do people call you?',
labelText: 'Name *',
......@@ -130,12 +190,15 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
onSaved: (String value) { person.name = value; },
validator: _validateName,
),
const SizedBox(height: 24.0),
new TextFormField(
decoration: const InputDecoration(
border: const UnderlineInputBorder(),
filled: true,
icon: const Icon(Icons.phone),
hintText: 'Where can we reach you?',
labelText: 'Phone Number *',
prefixText: '+1'
prefixText: '+1',
),
keyboardType: TextInputType.phone,
onSaved: (String value) { person.phoneNumber = value; },
......@@ -147,8 +210,11 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
_phoneNumberFormatter,
],
),
const SizedBox(height: 24.0),
new TextFormField(
decoration: const InputDecoration(
border: const UnderlineInputBorder(),
filled: true,
icon: const Icon(Icons.email),
hintText: 'Your email address',
labelText: 'E-mail',
......@@ -156,17 +222,21 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
keyboardType: TextInputType.emailAddress,
onSaved: (String value) { person.email = value; },
),
const SizedBox(height: 24.0),
new TextFormField(
decoration: const InputDecoration(
border: const OutlineInputBorder(),
hintText: 'Tell us about yourself',
helperText: 'Keep it short, this is just a demo',
helperText: 'Keep it short, this is just a demo.',
labelText: 'Life story',
),
maxLines: 3,
),
const SizedBox(height: 24.0),
new TextFormField(
keyboardType: TextInputType.number,
decoration: const InputDecoration(
border: const OutlineInputBorder(),
labelText: 'Salary',
prefixText: '\$',
suffixText: 'USD',
......@@ -174,50 +244,43 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
),
maxLines: 1,
),
new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Expanded(
child: new TextFormField(
key: _passwordFieldKey,
decoration: const InputDecoration(
hintText: 'How do you log in?',
labelText: 'New Password *',
),
obscureText: true,
const SizedBox(height: 24.0),
new PasswordField(
fieldKey: _passwordFieldKey,
helperText: 'No more than 8 characters.',
labelText: 'Password *',
onSaved: (String value) { person.password = value; },
),
),
const SizedBox(width: 16.0),
new Expanded(
child: new TextFormField(
const SizedBox(height: 24.0),
new TextFormField(
decoration: const InputDecoration(
hintText: 'How do you log in?',
labelText: 'Re-type Password *',
border: const UnderlineInputBorder(),
filled: true,
labelText: 'Re-type password',
),
maxLength: 8,
onFieldSubmitted: (String value) { person.password = value; },
obscureText: true,
onFieldSubmitted: (String value) { _handleSubmitted(); },
validator: _validatePassword,
),
),
],
),
new Container(
padding: const EdgeInsets.all(20.0),
alignment: Alignment.center,
const SizedBox(height: 24.0),
new Center(
child: new RaisedButton(
child: const Text('SUBMIT'),
onPressed: _handleSubmitted,
),
),
new Container(
padding: const EdgeInsets.only(top: 20.0),
child: new Text('* indicates required field', style: Theme.of(context).textTheme.caption),
const SizedBox(height: 24.0),
new Text(
'* indicates required field',
style: Theme.of(context).textTheme.caption
),
const SizedBox(height: 24.0),
],
),
),
),
),
);
}
}
......
......@@ -16,21 +16,36 @@ void main() {
final Finder nameField = find.widgetWithText(TextFormField, 'Name *');
expect(nameField, findsOneWidget);
final Finder passwordField = find.widgetWithText(TextFormField, 'Password *');
expect(passwordField, findsOneWidget);
await tester.enterText(nameField, '');
// The submit button isn't initially visible. Drag it into view so that
// it will see the tap.
await tester.drag(nameField, const Offset(0.0, -1200.0));
await tester.pumpAndSettle();
await tester.tap(submitButton);
await tester.pump();
await tester.pumpAndSettle();
// Now drag the password field (the submit button will be obscured by
// the snackbar) and expose the name field again.
await tester.drag(passwordField, const Offset(0.0, 1200.0));
await tester.pumpAndSettle();
expect(find.text('Name is required.'), findsOneWidget);
expect(find.text('Please enter only alphabetical characters.'), findsNothing);
await tester.enterText(nameField, '#');
// Make the submit button visible again (by dragging the name field), so
// it will see the tap.
await tester.drag(nameField, const Offset(0.0, -1200.0));
await tester.tap(submitButton);
await tester.pump();
await tester.pumpAndSettle();
expect(find.text('Name is required.'), findsNothing);
expect(find.text('Please enter only alphabetical characters.'), findsOneWidget);
await tester.enterText(nameField, 'Jane Doe');
await tester.tap(submitButton);
await tester.pump();
await tester.pumpAndSettle();
expect(find.text('Name is required.'), findsNothing);
expect(find.text('Please enter only alphabetical characters.'), findsNothing);
});
......
......@@ -60,7 +60,9 @@ class TextFormField extends FormField<String> {
bool autofocus: false,
bool obscureText: false,
bool autocorrect: true,
bool maxLengthEnforced: true,
int maxLines: 1,
int maxLength,
ValueChanged<String> onFieldSubmitted,
FormFieldSetter<String> onSaved,
FormFieldValidator<String> validator,
......@@ -71,7 +73,9 @@ class TextFormField extends FormField<String> {
assert(autofocus != null),
assert(obscureText != null),
assert(autocorrect != null),
assert(maxLengthEnforced != null),
assert(maxLines == null || maxLines > 0),
assert(maxLength == null || maxLength > 0),
super(
key: key,
initialValue: controller != null ? controller.text : (initialValue ?? ''),
......@@ -91,7 +95,9 @@ class TextFormField extends FormField<String> {
autofocus: autofocus,
obscureText: obscureText,
autocorrect: autocorrect,
maxLengthEnforced: maxLengthEnforced,
maxLines: maxLines,
maxLength: maxLength,
onChanged: field.onChanged,
onSubmitted: onFieldSubmitted,
inputFormatters: inputFormatters,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment