signinpage
unknown
plain_text
10 months ago
18 kB
63
Indexable
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
class SignInPage extends StatefulWidget {
const SignInPage({super.key});
@override
State<SignInPage> createState() => _SignInPageState();
}
class _SignInPageState extends State<SignInPage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _fadeAnimation;
late Animation<double> _slideAnimation;
late Animation<double> _scaleAnimation;
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
bool _obscurePassword = true;
bool _rememberMe = false;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1000),
);
_fadeAnimation = Tween<double>(begin: 0, end: 1).animate(
CurvedAnimation(
parent: _controller,
curve: const Interval(0.3, 1.0, curve: Curves.easeOut),
),
);
_slideAnimation = Tween<double>(begin: 40, end: 0).animate(
CurvedAnimation(
parent: _controller,
curve: const Interval(0.5, 1.0, curve: Curves.easeOut),
),
);
_scaleAnimation = Tween<double>(begin: 0.95, end: 1).animate(
CurvedAnimation(
parent: _controller,
curve: const Interval(0.6, 1.0, curve: Curves.easeOut),
),
);
WidgetsBinding.instance.addPostFrameCallback((_) {
_controller.forward();
});
}
@override
void dispose() {
_controller.dispose();
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[50],
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.black, size: 20),
onPressed: () => Navigator.of(context).pop(),
),
),
body: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Transform.translate(
offset: Offset(0, _slideAnimation.value),
child: Opacity(
opacity: _fadeAnimation.value,
child: Transform.scale(
scale: _scaleAnimation.value,
child: Card(
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Container(
padding: const EdgeInsets.all(32),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 20,
offset: const Offset(0, 10),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Title
const Text(
'Welcome Back',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.w800,
color: Colors.black,
),
),
const SizedBox(height: 8),
// Subtitle
Text(
'Sign in to continue your journey',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Colors.grey[600],
),
),
const SizedBox(height: 32),
// Email Field
TextField(
controller: _emailController,
decoration: InputDecoration(
labelText: 'Email',
labelStyle: TextStyle(color: Colors.grey[600]),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(
color: Colors.black,
width: 1.5,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Colors.grey[300]!,
),
),
floatingLabelStyle: const TextStyle(
color: Colors.black,
),
prefixIcon: Icon(
Icons.email,
color: Colors.grey[600],
),
contentPadding: const EdgeInsets.symmetric(
vertical: 16,
horizontal: 16,
),
),
keyboardType: TextInputType.emailAddress,
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 20),
// Password Field
TextField(
controller: _passwordController,
decoration: InputDecoration(
labelText: 'Password',
labelStyle: TextStyle(color: Colors.grey[600]),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(
color: Colors.black,
width: 1.5,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Colors.grey[300]!,
),
),
floatingLabelStyle: const TextStyle(
color: Colors.black,
),
prefixIcon: Icon(
Icons.lock,
color: Colors.grey[600],
),
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility_off
: Icons.visibility,
color: Colors.grey,
),
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
),
contentPadding: const EdgeInsets.symmetric(
vertical: 16,
horizontal: 16,
),
),
obscureText: _obscurePassword,
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 16),
// Remember Me & Forgot Password
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Checkbox(
value: _rememberMe,
onChanged: (value) {
setState(() {
_rememberMe = value!;
});
},
activeColor: Colors.black,
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
),
Text(
'Remember me',
style: TextStyle(color: Colors.grey[600]),
),
],
),
TextButton(
onPressed: () {
// Forgot password action
},
child: Text(
'Forgot Password?',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600,
),
),
),
],
),
const SizedBox(height: 24),
// Sign In Button
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton(
onPressed: () {
// Sign in action
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 0,
shadowColor: Colors.transparent,
),
child: const Text(
'SIGN IN',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
),
const SizedBox(height: 24),
// Divider
Row(
children: [
Expanded(
child: Divider(color: Colors.grey[300]),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
),
child: Text(
'or continue with',
style: TextStyle(color: Colors.grey[500]),
),
),
Expanded(
child: Divider(color: Colors.grey[300]),
),
],
),
const SizedBox(height: 24),
// Social Login Buttons
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: OutlinedButton.icon(
onPressed: () {},
icon: Image.asset(
'assets/images/google.png',
width: 20,
height: 20,
),
label: const Text(
'Google',
style: TextStyle(color: Colors.black),
),
style: OutlinedButton.styleFrom(
foregroundColor: Colors.black,
padding: const EdgeInsets.symmetric(
vertical: 16,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
side: BorderSide(
color: Colors.grey[300]!,
),
),
),
),
const SizedBox(width: 12),
Expanded(
child: OutlinedButton.icon(
onPressed: () {},
icon: Image.asset(
'assets/images/facebook.png',
width: 20,
height: 20,
),
label: const Text(
'Facebook',
style: TextStyle(color: Colors.black),
),
style: OutlinedButton.styleFrom(
foregroundColor: Colors.black,
padding: const EdgeInsets.symmetric(
vertical: 16,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
side: BorderSide(
color: Colors.grey[300]!,
),
),
),
),
],
),
const SizedBox(height: 32),
// Sign Up Prompt
Center(
child: RichText(
text: TextSpan(
style: TextStyle(
color: Colors.grey[600],
fontSize: 14,
),
children: [
const TextSpan(
text: "Don't have an account? ",
),
TextSpan(
text: 'Sign up',
style: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.w700,
),
recognizer: TapGestureRecognizer()
..onTap = () {
// Navigate to sign up
},
),
],
),
),
),
],
),
),
),
),
),
);
},
),
),
),
);
}
}
Editor is loading...
Leave a Comment