Below is a complete Flutter example (single file) that includes:
- Login screen
- Signup screen
- Form validation (email, password, confirm password)
- Navigation between Login & Signup
- Clean and beginner-friendly structure
You can copy-paste this directly into lib/main.dart.
✅ Features
- Email validation
- Password length validation
- Confirm password matching
- Separate Login & Signup screens
- Material UI
📁 main.dart (FULL CODE)
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Login & Signup',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const LoginScreen(),
);
}
}
/* -------------------- LOGIN SCREEN -------------------- */
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _formKey = GlobalKey<FormState>();
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Login")),
body: Padding(
padding: const EdgeInsets.all(20),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: emailController,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
labelText: "Email",
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return "Email is required";
}
if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
return "Enter a valid email";
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: passwordController,
obscureText: true,
decoration: const InputDecoration(
labelText: "Password",
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return "Password is required";
}
if (value.length < 6) {
return "Password must be at least 6 characters";
}
return null;
},
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Login Successful")),
);
}
},
child: const Text("Login"),
),
const SizedBox(height: 12),
TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SignupScreen(),
),
);
},
child: const Text("Don't have an account? Sign Up"),
),
],
),
),
),
);
}
}
/* -------------------- SIGNUP SCREEN -------------------- */
class SignupScreen extends StatefulWidget {
const SignupScreen({super.key});
@override
State<SignupScreen> createState() => _SignupScreenState();
}
class _SignupScreenState extends State<SignupScreen> {
final _formKey = GlobalKey<FormState>();
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final TextEditingController confirmPasswordController =
TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Sign Up")),
body: Padding(
padding: const EdgeInsets.all(20),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: [
TextFormField(
controller: emailController,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
labelText: "Email",
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return "Email is required";
}
if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
return "Enter a valid email";
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: passwordController,
obscureText: true,
decoration: const InputDecoration(
labelText: "Password",
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return "Password is required";
}
if (value.length < 6) {
return "Password must be at least 6 characters";
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: confirmPasswordController,
obscureText: true,
decoration: const InputDecoration(
labelText: "Confirm Password",
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return "Confirm password is required";
}
if (value != passwordController.text) {
return "Passwords do not match";
}
return null;
},
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Signup Successful")),
);
Navigator.pop(context);
}
},
child: const Text("Sign Up"),
),
],
),
),
),
),
);
}
}
