import 'package:flutter/material.dart'; void main() => runApp(const SignUpApp()); class SignUpApp extends StatelessWidget { const SignUpApp(); @override Widget build(BuildContext context) { return MaterialApp( routes: { '/': (context) => const SignUpScreen(), '/welcome': (context) => WelcomeScreen(), }, ); } } class SignUpScreen extends StatelessWidget { const SignUpScreen(); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[200], body: const Center( child: SizedBox( width: 400, child: Card( child: SignUpForm(), ), ), ), ); } } class WelcomeScreen extends StatelessWidget { const WelcomeScreen(); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Text('Welcome!', style: Theme.of(context).textTheme.headline2), ), ); } } class SignUpForm extends StatefulWidget { const SignUpForm(); @override _SignUpFormState createState() => _SignUpFormState(); } class _SignUpFormState extends State { final _firstNameTextController = TextEditingController(); final _lastNameTextController = TextEditingController(); final _usernameTextController = TextEditingController(); double _formProgress = 0; void _showWelcomeScreen() { Navigator.of(context).pushNamed('/welcome'); } void _updateFormProgress() { var progress = 0.0; final controllers = [ _firstNameTextController, _lastNameTextController, _usernameTextController ]; for (final controller in controllers) { if (controller.value.text.isNotEmpty) { progress += 1 / controllers.length; } } setState(() { _formProgress = progress; }); } @override Widget build(BuildContext context) { return Form( onChanged: _updateFormProgress, child: Column( mainAxisSize: MainAxisSize.min, children: [ LinearProgressIndicator(value: _formProgress), Text('Sign up', style: Theme.of(context).textTheme.headline4), Padding( padding: const EdgeInsets.all(8.0), child: TextFormField( controller: _firstNameTextController, decoration: const InputDecoration(hintText: 'First name'), ), ), Padding( padding: const EdgeInsets.all(8.0), child: TextFormField( controller: _lastNameTextController, decoration: const InputDecoration(hintText: 'Last name'), ), ), Padding( padding: const EdgeInsets.all(8.0), child: TextFormField( controller: _usernameTextController, decoration: const InputDecoration(hintText: 'Username'), ), ), TextButton( style: ButtonStyle( foregroundColor: MaterialStateProperty.resolveWith( (Set states) { return states.contains(MaterialState.disabled) ? null : Colors.white; }), backgroundColor: MaterialStateProperty.resolveWith( (Set states) { return states.contains(MaterialState.disabled) ? null : Colors.blue; }), ), onPressed: null, child: const Text('Sign up'), ), ], ), ); } } class AnimatedProgressIndicator extends StatefulWidget { final double value; const AnimatedProgressIndicator({ required this.value, }); @override State createState() { return _AnimatedProgressIndicatorState(); } } class _AnimatedProgressIndicatorState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _colorAnimation; late Animation _curveAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(milliseconds: 1200), vsync: this); final colorTween = TweenSequence([ TweenSequenceItem( tween: ColorTween(begin: Colors.red, end: Colors.orange), weight: 1, ), TweenSequenceItem( tween: ColorTween(begin: Colors.orange, end: Colors.yellow), 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), ), ); } }