Created
February 3, 2021 02:53
-
-
Save vicmans/f0908f13e859e0738c560e69ed4d4cbd to your computer and use it in GitHub Desktop.
First Dart App #30DaysOfFlutter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'package:flutter/material.dart'; | |
| void main() => runApp(SignUpApp()); | |
| class SignUpApp extends StatelessWidget { | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| routes: { | |
| '/': (context) => SignUpScreen(), | |
| '/welcome': (context) => WelcomeScreen(), | |
| }, | |
| ); | |
| } | |
| } | |
| class SignUpScreen extends StatelessWidget { | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| backgroundColor: Colors.grey[200], | |
| body: Center( | |
| child: SizedBox( | |
| width: 500, | |
| child: Card( | |
| child: SignUpForm(), | |
| ), | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| class WelcomeScreen extends StatelessWidget { | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| body: Center( | |
| child: Text('Welcome!', style: Theme.of(context).textTheme.headline2), | |
| ), | |
| floatingActionButton: FloatingActionButton( | |
| onPressed: () { | |
| Navigator.of(context).pushNamed('/'); | |
| }, | |
| child: Icon(Icons.arrow_back), | |
| backgroundColor: Theme.of(context).primaryColor, | |
| ), | |
| ); | |
| } | |
| } | |
| class SignUpForm extends StatefulWidget { | |
| @override | |
| _SignUpFormState createState() => _SignUpFormState(); | |
| } | |
| bool isEmail(String string) { | |
| if (string == null || string.isEmpty) { | |
| return true; | |
| } | |
| const pattern = r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'; | |
| final regExp = RegExp(pattern); | |
| if (!regExp.hasMatch(string)) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| class _SignUpFormState extends State<SignUpForm> { | |
| final _firstNameTextController = TextEditingController(); | |
| final _emailTextController = TextEditingController(); | |
| final _usernameTextController = TextEditingController(); | |
| final _formKey = GlobalKey<FormState>(); | |
| double _formProgress = 0; | |
| void _updateFormProgress() { | |
| var progress = 0.0; | |
| final controllers = [ | |
| _firstNameTextController, | |
| _emailTextController, | |
| _usernameTextController | |
| ]; | |
| for (final controller in controllers) { | |
| if (controller.value.text.isNotEmpty) { | |
| progress += 1 / controllers.length; | |
| } | |
| } | |
| setState(() { | |
| _formProgress = progress; | |
| }); | |
| } | |
| void _showWelcomeScreen() { | |
| if (_formKey.currentState.validate()) { | |
| // If the form is valid, display a Snackbar. | |
| ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Congratulations!'))); | |
| Navigator.of(context).pushNamed('/welcome'); | |
| } | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| return Form( | |
| key: _formKey, | |
| onChanged: _updateFormProgress, | |
| child: Column( | |
| mainAxisSize: MainAxisSize.min, | |
| children: [ | |
| AnimatedProgressIndicator(value: _formProgress), | |
| //LinearProgressIndicator(value: _formProgress), | |
| Text('Sign up', style: Theme.of(context).textTheme.headline4), | |
| Padding( | |
| padding: EdgeInsets.all(8.0), | |
| child: TextFormField( | |
| validator: (value) { | |
| if (value.toString().length < 2) { | |
| return 'Please enter some text'; | |
| } | |
| return null; | |
| }, | |
| controller: _firstNameTextController, | |
| decoration: InputDecoration(hintText: 'Full name'), | |
| ), | |
| ), | |
| Padding( | |
| padding: EdgeInsets.all(8.0), | |
| child: TextFormField( | |
| validator: (value) { | |
| if (!isEmail(value.toString())) { | |
| return 'Please enter a valid email'; | |
| } | |
| return null; | |
| }, | |
| controller: _emailTextController, | |
| decoration: InputDecoration(hintText: 'Email'), | |
| ), | |
| ), | |
| Padding( | |
| padding: EdgeInsets.all(8.0), | |
| child: TextFormField( | |
| validator: (value) { | |
| if (value.toString().length < 4) { | |
| return 'Please at least 4 characters'; | |
| } | |
| return null; | |
| }, | |
| controller: _usernameTextController, | |
| decoration: InputDecoration(hintText: 'Username'), | |
| ), | |
| ), | |
| Padding( | |
| padding: EdgeInsets.all(8.0), | |
| child: ElevatedButton( | |
| style: ButtonStyle( | |
| foregroundColor: | |
| MaterialStateColor.resolveWith((Set<MaterialState> states) { | |
| return states.contains(MaterialState.disabled) | |
| ? null | |
| : Colors.white; | |
| }), | |
| backgroundColor: | |
| MaterialStateColor.resolveWith((Set<MaterialState> states) { | |
| return states.contains(MaterialState.disabled) | |
| ? null | |
| : Colors.blue; | |
| }), | |
| ), | |
| onPressed: _formProgress == 1 ? _showWelcomeScreen : null, | |
| child: Text('Sign up'), | |
| ), | |
| ), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class AnimatedProgressIndicator extends StatefulWidget { | |
| final double value; | |
| AnimatedProgressIndicator({ | |
| @required this.value, | |
| }); | |
| @override | |
| State<StatefulWidget> createState() { | |
| return _AnimatedProgressIndicatorState(); | |
| } | |
| } | |
| class _AnimatedProgressIndicatorState extends State<AnimatedProgressIndicator> | |
| with SingleTickerProviderStateMixin { | |
| AnimationController _controller; | |
| Animation<Color> _colorAnimation; | |
| Animation<double> _curveAnimation; | |
| void initState() { | |
| super.initState(); | |
| _controller = AnimationController( | |
| duration: Duration(milliseconds: 1200), vsync: this); | |
| final colorTween = TweenSequence([ | |
| TweenSequenceItem( | |
| tween: ColorTween(begin: Colors.red, end: Colors.red), | |
| weight: 1, | |
| ), | |
| TweenSequenceItem( | |
| tween: ColorTween(begin: Colors.orange, end: Colors.orange), | |
| weight: 1, | |
| ), | |
| TweenSequenceItem( | |
| tween: ColorTween(begin: Colors.yellow, end: Colors.green), | |
| weight: 1, | |
| ), | |
| ]); | |
| _colorAnimation = _controller.drive(colorTween); | |
| _curveAnimation = _controller.drive(CurveTween(curve: Curves.easeIn)); | |
| } | |
| @override | |
| void didUpdateWidget(oldWidget) { | |
| super.didUpdateWidget(oldWidget); | |
| _controller.animateTo(widget.value); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| return AnimatedBuilder( | |
| animation: _controller, | |
| builder: (context, child) => LinearProgressIndicator( | |
| value: _curveAnimation.value, | |
| valueColor: _colorAnimation, | |
| backgroundColor: _colorAnimation.value.withOpacity(0.4), | |
| ), | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment