Flutter UI of login screen, adorned with background animations, transforms the authentication process into a captivating experience. With Flutter’s dynamic animation capabilities, developers can craft login screens. This tutorial can teach you about the flutter’s animation and design sense. Copy the code below and run it.
import 'dart:async';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:ui' as ui;
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
late AnimationController controller1;
late AnimationController controller2;
late Animation<double> animation1;
late Animation<double> animation2;
late Animation<double> animation3;
late Animation<double> animation4;
void _incrementCounter() {
setState(() {
});
}
@override
void initState() {
super.initState();
controller1 = AnimationController(
vsync: this,
duration: Duration(
seconds: 1,
),
);
animation1 = Tween<double>(begin: .1, end: .15).animate(
CurvedAnimation(
parent: controller1,
curve: Curves.easeInOut,
),
)
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller1.reverse();
} else if (status == AnimationStatus.dismissed) {
controller1.forward();
}
});
animation2 = Tween<double>(begin: -0.10, end: .04).animate(
CurvedAnimation(
parent: controller1,
curve: Curves.easeInOut,
),
)..addListener(() {
setState(() {});
});
controller2 = AnimationController(
vsync: this,
duration: Duration(
seconds: 2,
),
);
animation3 = Tween<double>(begin: .41, end: .38).animate(CurvedAnimation(
parent: controller2,
curve: Curves.easeInOut,
))
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller2.reverse();
} else if (status == AnimationStatus.dismissed) {
controller2.forward();
}
});
animation4 = Tween<double>(begin: 170, end: 190).animate(
CurvedAnimation(
parent: controller2,
curve: Curves.easeInOut,
),
)..addListener(() {
setState(() {});
});
Timer(Duration(milliseconds: 2500), () {
controller1.forward();
});
controller2.forward();
}
@override
void dispose() {
controller1.dispose();
controller2.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: Color(0xff192028),
body: ScrollConfiguration(
behavior: MyBehavior(),
child: SizedBox(
height: size.height,
child: Stack(
children: [
Positioned(
top: size.height,
left: size.width * .21,
child: CustomPaint(
painter: MyPainter(50),
),
),
Positioned(
top: size.height * .98,
left: size.width * .1,
child: CustomPaint(
painter: MyPainter(animation4.value - 30),
),
),
Positioned(
top: size.height * .5,
left: size.width * (animation2.value + .8),
child: CustomPaint(
painter: MyPainter(30),
),
),
Positioned(
top: size.height * animation3.value,
left: size.width * (animation1.value + .1),
child: CustomPaint(
painter: MyPainter(60),
),
),
Positioned(
top: size.height * .1,
left: size.width * .8,
child: CustomPaint(
painter: MyPainter(animation4.value),
),
),
BackdropFilter(
filter: ui.ImageFilter.blur(
sigmaX: 10.0,
sigmaY: 10.0,
),
child: Container(
color: Colors.transparent,
),
),
Column(
children: [
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.only(top: size.height * .1),
child: Text(
'APP NAME',
style: TextStyle(
color: Colors.white.withOpacity(.7),
fontSize: 30,
fontWeight: FontWeight.bold,
letterSpacing: 1,
wordSpacing: 4,
),
),
),
),
Expanded(
flex: 10,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(32.0, 0, 32, 0),
child: TextField(
style: TextStyle(color: Colors.white.withOpacity(1)),
cursorColor: Colors.white,
obscureText: false,
decoration: InputDecoration(
fillColor: Colors.greenAccent.withOpacity(.30),
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff2E8B57)),
borderRadius: BorderRadius.circular(15),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff2E8B57)),
borderRadius: BorderRadius.circular(15),
),
prefixIcon: Icon(
Icons.account_circle_outlined,
color: Colors.white.withOpacity(.7),
),
border: InputBorder.none,
hintMaxLines: 1,
hintText: 'User name...',
hintStyle:
TextStyle(fontSize: 14, color: Colors.white.withOpacity(.5)),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(32.0, 16, 32, 0),
child: TextField(
style: TextStyle(color: Colors.white.withOpacity(1)),
cursorColor: Colors.white,
obscureText: false,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
fillColor: Colors.greenAccent.withOpacity(.30),
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff2E8B57)),
borderRadius: BorderRadius.circular(15),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff2E8B57)),
borderRadius: BorderRadius.circular(15),
),
prefixIcon: Icon(
Icons.email_outlined,
color: Colors.white.withOpacity(.7),
),
border: InputBorder.none,
hintMaxLines: 1,
hintText: 'Email...',
hintStyle:
TextStyle(fontSize: 14, color: Colors.white.withOpacity(.5)),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(32.0, 16, 32, 0),
child: TextField(
style: TextStyle(color: Colors.white.withOpacity(1)),
cursorColor: Colors.white,
obscureText: true,
decoration: InputDecoration(
fillColor: Colors.greenAccent.withOpacity(.30),
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff2E8B57)),
borderRadius: BorderRadius.circular(15),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff2E8B57)),
borderRadius: BorderRadius.circular(15),
),
prefixIcon: Icon(
Icons.lock_outline,
color: Colors.white.withOpacity(.7),
),
border: InputBorder.none,
hintMaxLines: 1,
hintText: 'Password...',
hintStyle:
TextStyle(fontSize: 14, color: Colors.white.withOpacity(.5)),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(32, 16, 32, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 3,
child: OutlinedButton(
onPressed: () {
},
style: OutlinedButton.styleFrom(
minimumSize: Size.fromHeight(60),
backgroundColor: Colors.greenAccent.withOpacity(.30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
side: BorderSide(width: 1.0, color: Color(0xff2E8B57)),
),
child: const Text('LOGIN', style: TextStyle(color: Colors.white)),
),
),
SizedBox(width: size.width / 20),
Expanded(
flex: 4,
child: OutlinedButton(
onPressed: () {
},
style: OutlinedButton.styleFrom(
minimumSize: Size.fromHeight(60),
backgroundColor: Colors.greenAccent.withOpacity(.30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
side: BorderSide(width: 1.0, color: Color(0xff2E8B57)),
),
child: const Text('Forgot Password', style: TextStyle(color: Colors.white)),
),
),
],
),
),
],
),
),
Expanded(
flex: 3,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
component2(
'Create a new Account',
2,
() {
HapticFeedback.lightImpact();
// Fluttertoast.showToast(
// msg: 'Create a new account button pressed');
},
),
SizedBox(height: size.height * .05),
],
),
),
],
),
],
),
),
),
);
}
Widget component2(String string, double width, VoidCallback voidCallback) {
Size size = MediaQuery.of(context).size;
return ClipRRect(
borderRadius: BorderRadius.circular(15),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaY: 0, sigmaX: 0),
child: InkWell(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
onTap: voidCallback,
child: Container(
height: size.width / 8,
width: size.width / width,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white.withOpacity(.05),
borderRadius: BorderRadius.circular(15),
),
child: Text(
string,
style: TextStyle(color: Colors.white.withOpacity(.8)),
),
),
),
),
);
}
}
class MyPainter extends CustomPainter {
final double radius;
MyPainter(this.radius);
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..shader = LinearGradient(
colors: [Color(0xff2E8B57), Color(0x00FA9A)],
begin: Alignment.topLeft,
end: Alignment.bottomRight)
.createShader(Rect.fromCircle(center: Offset(0, 0), radius: radius));
canvas.drawCircle(Offset.zero, radius, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
class MyBehavior extends ScrollBehavior {
Widget buildViewportChrome(
BuildContext context, Widget child, AxisDirection axisDirection) {
return child;
}
}
By the way. If you are looking for native android development of this kind of UI you can visit here. You can also see a video here: https://www.youtube.com/watch?v=549TzfZ2gYs&ab_channel=CaptainDroid