Skip to content

Instantly share code, notes, and snippets.

@vicmans
Created February 3, 2021 02:53
Show Gist options
  • Select an option

  • Save vicmans/f0908f13e859e0738c560e69ed4d4cbd to your computer and use it in GitHub Desktop.

Select an option

Save vicmans/f0908f13e859e0738c560e69ed4d4cbd to your computer and use it in GitHub Desktop.
First Dart App #30DaysOfFlutter
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