🎯 Exemples recommandés
Balanced sample collections from various categories for you to explore
Exemples Flutter
Exemples du framework de développement mobile Dart Flutter incluant les widgets, gestion d'état, navigation et intégration plateforme
💻 Bonjour Monde Flutter dart
🟢 simple
Exemples d'applications Flutter de base avec widgets, layouts, stylisation et concepts fondamentaux
// Flutter Hello World Examples
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// 1. Basic Hello World App
class HelloWorldApp extends StatelessWidget {
const HelloWorldApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const HelloWorldScreen(),
);
}
}
class HelloWorldScreen extends StatelessWidget {
const HelloWorldScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Hello World'),
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Hello, World!',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
SizedBox(height: 16),
Text(
'Welcome to Flutter!',
style: TextStyle(
fontSize: 16,
color: Colors.grey,
),
),
],
),
),
);
}
}
// 2. Interactive Counter App
class CounterApp extends StatefulWidget {
const CounterApp({super.key});
@override
State<CounterApp> createState() => _CounterAppState();
}
class _CounterAppState extends State<CounterApp> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
void _decrementCounter() {
setState(() {
_counter--;
});
}
void _resetCounter() {
setState(() {
_counter = 0;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Counter App',
theme: ThemeData(
primarySwatch: Colors.green,
useMaterial3: true,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Counter App'),
backgroundColor: Colors.green,
foregroundColor: Colors.white,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'You have pushed the button this many times:',
style: TextStyle(fontSize: 16),
),
Text(
'$_counter',
style: const TextStyle(
fontSize: 48,
fontWeight: FontWeight.bold,
color: Colors.green,
),
),
const SizedBox(height: 32),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
FloatingActionButton(
onPressed: _decrementCounter,
tooltip: 'Decrement',
backgroundColor: Colors.red,
child: const Icon(Icons.remove),
),
FloatingActionButton(
onPressed: _resetCounter,
tooltip: 'Reset',
backgroundColor: Colors.orange,
child: const Icon(Icons.refresh),
),
FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
backgroundColor: Colors.green,
child: const Icon(Icons.add),
),
],
),
],
),
),
),
);
}
}
// 3. User Profile Form
class UserProfileForm extends StatefulWidget {
const UserProfileForm({super.key});
@override
State<UserProfileForm> createState() => _UserProfileFormState();
}
class _UserProfileFormState extends State<UserProfileForm> {
final _formKey = GlobalKey<FormState>();
final _nameController = TextEditingController();
final _emailController = TextEditingController();
final _ageController = TextEditingController();
final _bioController = TextEditingController();
bool _isEditing = false;
Map<String, String> _userProfile = {};
@override
void dispose() {
_nameController.dispose();
_emailController.dispose();
_ageController.dispose();
_bioController.dispose();
super.dispose();
}
void _toggleEditMode() {
setState(() {
_isEditing = !_isEditing;
if (_isEditing) {
_nameController.text = _userProfile['name'] ?? '';
_emailController.text = _userProfile['email'] ?? '';
_ageController.text = _userProfile['age'] ?? '';
_bioController.text = _userProfile['bio'] ?? '';
}
});
}
void _saveProfile() {
if (_formKey.currentState!.validate()) {
setState(() {
_userProfile = {
'name': _nameController.text,
'email': _emailController.text,
'age': _ageController.text,
'bio': _bioController.text,
};
_isEditing = false;
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Profile saved successfully!'),
backgroundColor: Colors.green,
),
);
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'User Profile',
theme: ThemeData(
primarySwatch: Colors.purple,
useMaterial3: true,
),
home: Scaffold(
appBar: AppBar(
title: Text(_isEditing ? 'Edit Profile' : 'User Profile'),
backgroundColor: Colors.purple,
foregroundColor: Colors.white,
actions: [
IconButton(
icon: Icon(_isEditing ? Icons.save : Icons.edit),
onPressed: _isEditing ? _saveProfile : _toggleEditMode,
),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!_isEditing && _userProfile.isNotEmpty) ...[
_buildProfileDisplay(),
] else ...[
TextFormField(
controller: _nameController,
decoration: const InputDecoration(
labelText: 'Name',
prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your name';
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _emailController,
decoration: const InputDecoration(
labelText: 'Email',
prefixIcon: Icon(Icons.email),
border: OutlineInputBorder(),
),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
if (!value.contains('@')) {
return 'Please enter a valid email';
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _ageController,
decoration: const InputDecoration(
labelText: 'Age',
prefixIcon: Icon(Icons.cake),
border: OutlineInputBorder(),
),
keyboardType: TextInputType.number,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your age';
}
if (int.tryParse(value) == null) {
return 'Please enter a valid number';
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _bioController,
decoration: const InputDecoration(
labelText: 'Bio',
prefixIcon: Icon(Icons.description),
border: OutlineInputBorder(),
),
maxLines: 3,
),
const SizedBox(height: 24),
if (_isEditing)
Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: _saveProfile,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.purple,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
),
child: const Text('Save Profile'),
),
),
const SizedBox(width: 16),
Expanded(
child: OutlinedButton(
onPressed: _toggleEditMode,
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
),
child: const Text('Cancel'),
),
),
],
),
],
],
),
),
),
),
);
}
Widget _buildProfileDisplay() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildInfoCard('Name', _userProfile['name']!, Icons.person),
_buildInfoCard('Email', _userProfile['email']!, Icons.email),
_buildInfoCard('Age', _userProfile['age']!, Icons.cake),
if (_userProfile['bio']!.isNotEmpty)
_buildInfoCard('Bio', _userProfile['bio']!, Icons.description),
const SizedBox(height: 24),
ElevatedButton(
onPressed: _toggleEditMode,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.purple,
foregroundColor: Colors.white,
minimumSize: const Size(double.infinity, 48),
),
child: const Text('Edit Profile'),
),
],
);
}
Widget _buildInfoCard(String label, String value, IconData icon) {
return Card(
margin: const EdgeInsets.only(bottom: 16),
child: ListTile(
leading: Icon(icon, color: Colors.purple),
title: Text(label),
subtitle: Text(value),
),
);
}
}
// 4. Todo List App
class TodoApp extends StatefulWidget {
const TodoApp({super.key});
@override
State<TodoApp> createState() => _TodoAppState();
}
class _TodoAppState extends State<TodoApp> {
final List<Todo> _todos = [];
final TextEditingController _textFieldController = TextEditingController();
void _addTodoItem(String title) {
if (title.isNotEmpty) {
setState(() {
_todos.add(Todo(
title: title,
createdAt: DateTime.now(),
));
});
_textFieldController.clear();
}
}
void _toggleTodoStatus(int index) {
setState(() {
_todos[index].isDone = !_todos[index].isDone;
});
}
void _deleteTodoItem(int index) {
setState(() {
_todos.removeAt(index);
});
}
void _clearCompleted() {
setState(() {
_todos.removeWhere((todo) => todo.isDone);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Todo App',
theme: ThemeData(
primarySwatch: Colors.teal,
useMaterial3: true,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Todo List'),
backgroundColor: Colors.teal,
foregroundColor: Colors.white,
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _textFieldController,
decoration: InputDecoration(
labelText: 'What needs to be done?',
hintText: 'Enter a todo item',
border: const OutlineInputBorder(),
suffixIcon: IconButton(
icon: const Icon(Icons.add),
onPressed: () => _addTodoItem(_textFieldController.text),
),
),
onSubmitted: _addTodoItem,
),
),
],
),
),
_buildStatsBar(),
Expanded(
child: ListView.builder(
itemCount: _todos.length,
itemBuilder: (context, index) {
final todo = _todos[index];
return Dismissible(
key: Key(todo.title),
background: Container(
color: Colors.red,
alignment: Alignment.centerRight,
padding: const EdgeInsets.only(right: 20.0),
child: const Icon(Icons.delete, color: Colors.white),
),
onDismissed: (direction) {
_deleteTodoItem(index);
},
child: ListTile(
leading: Checkbox(
value: todo.isDone,
onChanged: (value) => _toggleTodoStatus(index),
activeColor: Colors.teal,
),
title: Text(
todo.title,
style: TextStyle(
decoration: todo.isDone ? TextDecoration.lineThrough : null,
color: todo.isDone ? Colors.grey : null,
),
),
subtitle: Text(
'Created: ${_formatDate(todo.createdAt)}',
style: const TextStyle(fontSize: 12),
),
trailing: IconButton(
icon: const Icon(Icons.delete_outline),
onPressed: () => _deleteTodoItem(index),
),
),
);
},
),
),
],
),
),
);
}
Widget _buildStatsBar() {
final completedCount = _todos.where((todo) => todo.isDone).length;
final totalCount = _todos.length;
final activeCount = totalCount - completedCount;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
color: Colors.teal.withOpacity(0.1),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('$activeCount active, $completedCount completed'),
if (completedCount > 0)
TextButton(
onPressed: _clearCompleted,
child: const Text('Clear completed'),
),
],
),
);
}
String _formatDate(DateTime date) {
return '${date.day}/${date.month}/${date.year}';
}
}
class Todo {
String title;
DateTime createdAt;
bool isDone;
Todo({
required this.title,
required this.createdAt,
this.isDone = false,
});
}
// 5. Main Demo App
class FlutterDemoApp extends StatefulWidget {
const FlutterDemoApp({super.key});
@override
State<FlutterDemoApp> createState() => _FlutterDemoAppState();
}
class _FlutterDemoAppState extends State<FlutterDemoApp> {
int _selectedIndex = 0;
final List<Widget> _pages = [
const HomePage(),
const CounterPage(),
const ProfilePage(),
const TodoPage(),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.indigo,
useMaterial3: true,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo App'),
backgroundColor: Colors.indigo,
foregroundColor: Colors.white,
),
body: _pages[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: _onItemTapped,
selectedItemColor: Colors.indigo,
unselectedItemColor: Colors.grey,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.countertops),
label: 'Counter',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
BottomNavigationBarItem(
icon: Icon(Icons.checklist),
label: 'Todos',
),
],
),
),
);
}
}
// Page widgets
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return const Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Welcome to Flutter!',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.indigo,
),
),
SizedBox(height: 16),
Text(
'This is a comprehensive Flutter demo showcasing:',
style: TextStyle(fontSize: 16),
),
SizedBox(height: 8),
_FeatureList(),
],
),
);
}
}
class _FeatureList extends StatelessWidget {
const _FeatureList({super.key});
@override
Widget build(BuildContext context) {
final features = [
'📱 Cross-platform mobile development',
'🎨 Beautiful Material Design UI',
'⚡ Fast development with Hot Reload',
'🔄 Reactive state management',
'🧩 Reusable widgets',
'🧪 Built-in testing support',
'📦 Rich package ecosystem',
'🎯 Native performance',
];
return Column(
children: features.map((feature) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
children: [
Expanded(
child: Text(
feature,
style: const TextStyle(fontSize: 14),
),
),
],
),
)).toList(),
);
}
}
class CounterPage extends StatelessWidget {
const CounterPage({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'Counter Page
Navigate to see the counter app',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
),
);
}
}
class ProfilePage extends StatelessWidget {
const ProfilePage({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'Profile Page
Navigate to see the profile form',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
),
);
}
}
class TodoPage extends StatelessWidget {
const TodoPage({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'Todo Page
Navigate to see the todo list app',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
),
);
}
}
// Main entry point for running individual apps
void main() {
runApp(const FlutterDemoApp());
} // Change to HelloWorldApp(), CounterApp(), etc. to run individual apps
💻 Flutter Widgets and Layouts dart
🟡 intermediate
Comprehensive guide to Flutter widgets, layouts, and responsive design patterns
// Flutter Widgets and Layouts Examples
import 'package:flutter/material.dart';
// 1. Basic Layout Widgets
class LayoutWidgetsDemo extends StatelessWidget {
const LayoutWidgetsDemo({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Layout Widgets Demo',
theme: ThemeData(
primarySwatch: Colors.purple,
useMaterial3: true,
),
home: const LayoutWidgetsScreen(),
);
}
}
class LayoutWidgetsScreen extends StatelessWidget {
const LayoutWidgetsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Layout Widgets'),
backgroundColor: Colors.purple,
foregroundColor: Colors.white,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Layout Widgets',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.purple,
),
),
const SizedBox(height: 16),
_ContainerExample(),
const SizedBox(height: 24),
_RowExample(),
const SizedBox(height: 24),
_ColumnExample(),
const SizedBox(height: 24),
_StackExample(),
const SizedBox(height: 24),
_ListViewExample(),
const SizedBox(height: 24),
_GridViewExample(),
const SizedBox(height: 24),
_WrapExample(),
const SizedBox(height: 24),
_ExpandedExample(),
],
),
),
);
}
Widget _ContainerExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Container',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Row(
children: [
Container(
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(right: 8),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.circular(8),
),
child: const Text('Styled Container'),
),
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.purple, Colors.pink],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.purple.withOpacity(0.3),
spreadRadius: 2,
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: const Center(
child: Text(
'Gradient',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
);
}
Widget _RowExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Row',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Expanded(
flex: 2,
child: Text('Flexible Item 1'),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(4),
),
child: const Text(
'Fixed',
style: TextStyle(color: Colors.white),
),
),
const SizedBox(width: 16),
const Expanded(
flex: 1,
child: Text('Item 2'),
),
],
),
),
],
);
}
Widget _ColumnExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Column',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.orange.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
height: 40,
decoration: BoxDecoration(
color: Colors.orange,
borderRadius: BorderRadius.circular(4),
),
child: const Center(
child: Text(
'Header Item',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(height: 8),
const Expanded(
child: Text('Flexible content that can expand or contract'),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
border: Border.all(color: Colors.orange),
borderRadius: BorderRadius.circular(4),
),
child: const Text('Footer Item'),
),
],
),
),
],
);
}
Widget _StackExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Stack',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
SizedBox(
height: 200,
child: Container(
decoration: BoxDecoration(
color: Colors.red.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Stack(
children: [
// Background layer
Positioned.fill(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.red.withOpacity(0.2), Colors.pink.withOpacity(0.2)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(8),
),
),
),
// Middle layer
Positioned(
top: 50,
left: 50,
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50),
boxShadow: [
BoxShadow(
color: Colors.red.withOpacity(0.3),
spreadRadius: 4,
blurRadius: 8,
),
],
),
child: const Center(
child: Icon(
Icons.favorite,
size: 40,
color: Colors.red,
),
),
),
),
// Top layer
Positioned(
bottom: 20,
right: 20,
child: FloatingActionButton.small(
onPressed: () {},
backgroundColor: Colors.pink,
child: const Icon(Icons.add),
),
),
],
),
),
),
],
);
}
Widget _ListViewExample() {
final items = List.generate(20, (index) => 'Item ${index + 1}');
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'ListView',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
SizedBox(
height: 200,
child: Container(
decoration: BoxDecoration(
color: Colors.teal.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: items.length,
itemBuilder: (context, index) {
return Card(
margin: const EdgeInsets.only(bottom: 8),
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.teal,
child: Text(
'${index + 1}',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
title: Text(items[index]),
subtitle: Text('Subtitle for ${items[index]}'),
trailing: const Icon(Icons.arrow_forward_ios),
),
);
},
),
),
),
],
);
}
Widget _GridViewExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'GridView',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
SizedBox(
height: 200,
child: Container(
decoration: BoxDecoration(
color: Colors.amber.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: GridView.builder(
padding: const EdgeInsets.all(8),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
childAspectRatio: 1,
),
itemCount: 6,
itemBuilder: (context, index) {
final colors = [Colors.amber, Colors.orange, Colors.deepOrange];
final icons = [Icons.star, Icons.favorite, Icons.thumb_up];
return Container(
decoration: BoxDecoration(
color: colors[index % colors.length],
borderRadius: BorderRadius.circular(8),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icons[index % icons.length],
size: 40,
color: Colors.white,
),
const SizedBox(height: 8),
Text(
'Grid ${index + 1}',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
],
),
);
},
),
),
),
],
);
}
Widget _WrapExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Wrap',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Wrap(
spacing: 8,
runSpacing: 8,
children: [
'Flutter',
'Dart',
'Mobile',
'Cross-platform',
'Widgets',
'State Management',
'Navigation',
'Animation',
'Testing',
'Performance',
].map((tag) {
final colors = [
Colors.blue,
Colors.purple,
Colors.pink,
Colors.indigo,
Colors.cyan,
];
final color = colors[tag.length % colors.length];
return Chip(
label: Text(tag),
backgroundColor: color.withOpacity(0.1),
labelStyle: TextStyle(
color: color,
fontWeight: FontWeight.w500,
),
side: BorderSide(color: color.withOpacity(0.3)),
);
}).toList(),
),
),
],
);
}
Widget _ExpandedExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Expanded & Flexible',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Container(
height: 150,
decoration: BoxDecoration(
color: Colors.green.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Expanded(
flex: 1,
child: Container(
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(4),
),
child: const Center(
child: Text(
'Expanded (flex: 1)',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
Flexible(
flex: 2,
child: Container(
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.lightGreen,
borderRadius: BorderRadius.circular(4),
),
child: const Center(
child: Text(
'Flexible (flex: 2)',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
Expanded(
flex: 1,
child: Container(
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(4),
),
child: const Center(
child: Text(
'Expanded (flex: 1)',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
],
);
}
}
// 2. Responsive Design with LayoutBuilder
class ResponsiveDesignDemo extends StatelessWidget {
const ResponsiveDesignDemo({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Responsive Design Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const ResponsiveDesignScreen(),
);
}
}
class ResponsiveDesignScreen extends StatelessWidget {
const ResponsiveDesignScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Responsive Design'),
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Responsive Layouts',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
const SizedBox(height: 16),
_LayoutBuilderExample(),
const SizedBox(height: 24),
_MediaQueryExample(),
const SizedBox(height: 24),
_OrientationExample(),
const SizedBox(height: 24),
_AspectRatioExample(),
],
),
),
);
}
Widget _LayoutBuilderExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'LayoutBuilder',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
return _WideLayout();
} else {
return _NarrowLayout();
}
},
),
],
);
}
Widget _WideLayout() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.blue),
),
child: Row(
children: [
Expanded(
flex: 1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Icon(Icons.desktop_mac, size: 48, color: Colors.blue),
const SizedBox(height: 8),
const Text(
'Wide Layout',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
const SizedBox(height: 8),
const Text(
'This layout is shown on screens wider than 600px',
style: TextStyle(fontSize: 14),
),
],
),
),
const SizedBox(width: 32),
Expanded(
flex: 2,
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
),
],
),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Content Area',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
'This is the content area for wide screens. '
'We can use the extra space for more detailed content or side-by-side layouts.',
style: TextStyle(fontSize: 14),
),
],
),
),
),
],
),
);
}
Widget _NarrowLayout() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.blue),
),
child: Column(
children: [
const Icon(Icons.smartphone, size: 48, color: Colors.blue),
const SizedBox(height: 8),
const Text(
'Narrow Layout',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
const SizedBox(height: 8),
const Text(
'This layout is shown on screens narrower than 600px',
style: TextStyle(fontSize: 14),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
),
],
),
child: const Text(
'Content is stacked vertically on narrow screens to optimize for mobile viewing.',
style: TextStyle(fontSize: 14),
),
),
],
),
);
}
Widget _MediaQueryExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'MediaQuery',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Builder(
builder: (context) {
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
final isTablet = screenWidth > 600 && screenWidth < 1200;
final isDesktop = screenWidth >= 1200;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.purple.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.purple),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
isDesktop
? Icons.desktop_windows
: isTablet
? Icons.tablet_mac
: Icons.phone_android,
size: 48,
color: Colors.purple,
),
const SizedBox(height: 8),
Text(
'Screen Size: ${screenWidth.toStringAsFixed(0)} x ${screenHeight.toStringAsFixed(0)}',
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Text(
'Device Type: ${isDesktop ? 'Desktop' : isTablet ? 'Tablet' : 'Mobile'}',
style: const TextStyle(fontSize: 14),
),
],
),
);
},
),
],
);
}
Widget _OrientationExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Orientation',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
OrientationBuilder(
builder: (context, orientation) {
final isPortrait = orientation == Orientation.portrait;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.orange.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.orange),
),
child: Column(
children: [
Icon(
isPortrait ? Icons.phone_iphone : Icons.screen_rotation,
size: 48,
color: Colors.orange,
),
const SizedBox(height: 8),
Text(
'Orientation: ${isPortrait ? 'Portrait' : 'Landscape'}',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
isPortrait
? 'Content is optimized for portrait viewing'
: 'Content is optimized for landscape viewing',
style: const TextStyle(fontSize: 14),
textAlign: TextAlign.center,
),
if (!isPortrait)
Container(
margin: const EdgeInsets.only(top: 16),
child: const Row(
children: [
Expanded(
child: Placeholder(),
),
SizedBox(width: 16),
Expanded(
child: Placeholder(),
),
],
),
),
],
),
);
},
),
],
);
}
Widget _AspectRatioExample() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'AspectRatio',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.teal.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.teal),
),
child: Column(
children: [
const Text(
'16:9 Aspect Ratio',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
AspectRatio(
aspectRatio: 16 / 9,
child: Container(
decoration: BoxDecoration(
color: Colors.teal,
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: Text(
'Video Content',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
),
const SizedBox(height: 16),
const Text(
'1:1 Aspect Ratio',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
AspectRatio(
aspectRatio: 1 / 1,
child: Container(
decoration: BoxDecoration(
color: Colors.lightGreen,
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: Icon(
Icons.photo,
size: 48,
color: Colors.white,
),
),
),
),
],
),
),
],
);
}
}
// 3. Custom Widget Example
class CustomWidgetDemo extends StatefulWidget {
const CustomWidgetDemo({super.key});
@override
State<CustomWidgetDemo> createState() => _CustomWidgetDemoState();
}
class _CustomWidgetDemoState extends State<CustomWidgetDemo> {
int _rating = 3;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Widget Demo',
theme: ThemeData(
primarySwatch: Colors.red,
useMaterial3: true,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Custom Widgets'),
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Custom Widgets',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
const SizedBox(height: 16),
const CustomCard(
title: 'Custom Card Widget',
description: 'This is a reusable custom card component',
icon: Icons.star,
color: Colors.red,
),
const SizedBox(height: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Interactive Rating Widget',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
RatingWidget(
rating: _rating,
onRatingChanged: (rating) {
setState(() {
_rating = rating;
});
},
),
const SizedBox(height: 8),
Text(
'Current Rating: $_rating',
style: const TextStyle(fontSize: 16),
),
],
),
const SizedBox(height: 16),
const ProgressIndicatorWidget(
progress: 0.75,
label: 'Project Completion',
),
const SizedBox(height: 16),
_buildAnimatedContainer(),
],
),
),
),
);
}
Widget _buildAnimatedContainer() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Animated Container',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
const AnimatedContainerWidget(),
],
);
}
}
// Custom Card Widget
class CustomCard extends StatelessWidget {
final String title;
final String description;
final IconData icon;
final Color color;
const CustomCard({
super.key,
required this.title,
required this.description,
required this.icon,
required this.color,
});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
color.withOpacity(0.1),
color.withOpacity(0.05),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: color.withOpacity(0.3)),
boxShadow: [
BoxShadow(
color: color.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(8),
),
child: Icon(icon, color: Colors.white, size: 24),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: color,
),
),
const SizedBox(height: 4),
Text(
description,
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
],
),
),
],
),
);
}
}
// Rating Widget
class RatingWidget extends StatefulWidget {
final int rating;
final ValueChanged<int>? onRatingChanged;
const RatingWidget({
super.key,
required this.rating,
this.onRatingChanged,
});
@override
State<RatingWidget> createState() => _RatingWidgetState();
}
class _RatingWidgetState extends State<RatingWidget> {
late int _rating;
@override
void initState() {
super.initState();
_rating = widget.rating;
}
void _updateRating(int newRating) {
setState(() {
_rating = newRating;
});
widget.onRatingChanged?.call(newRating);
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(5, (index) {
return IconButton(
onPressed: () => _updateRating(index + 1),
icon: Icon(
index < _rating ? Icons.star : Icons.star_border,
color: index < _rating ? Colors.amber : Colors.grey,
size: 32,
),
);
}),
);
}
}
// Progress Indicator Widget
class ProgressIndicatorWidget extends StatelessWidget {
final double progress;
final String label;
const ProgressIndicatorWidget({
super.key,
required this.progress,
required this.label,
});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
label,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
'${(progress * 100).toInt()}%',
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 8),
Container(
height: 8,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(4),
),
child: FractionallySizedBox(
alignment: Alignment.centerLeft,
widthFactor: progress,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.green, Colors.lightGreen],
),
borderRadius: BorderRadius.circular(4),
),
),
),
),
],
),
);
}
}
// Animated Container Widget
class AnimatedContainerWidget extends StatefulWidget {
const AnimatedContainerWidget({super.key});
@override
State<AnimatedContainerWidget> createState() => _AnimatedContainerWidgetState();
}
class _AnimatedContainerWidgetState extends State<AnimatedContainerWidget> {
Color _color = Colors.blue;
double _width = 100;
double _height = 100;
BorderRadius _borderRadius = BorderRadius.circular(8);
void _animateProperties() {
setState(() {
_color = Colors.primaries[(DateTime.now().millisecond % Colors.primaries.length)];
_width = 80 + (DateTime.now().millisecond % 120);
_height = 80 + (DateTime.now().millisecond % 120);
_borderRadius = BorderRadius.circular(8 + (DateTime.now().millisecond % 32));
});
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Animated Container',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Center(
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
width: _width,
height: _height,
decoration: BoxDecoration(
color: _color,
borderRadius: _borderRadius,
boxShadow: [
BoxShadow(
color: _color.withOpacity(0.3),
spreadRadius: 4,
blurRadius: 12,
offset: const Offset(0, 6),
),
],
),
child: const Center(
child: Text(
'Tap to Animate',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _animateProperties,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
child: const Text('Animate Properties'),
),
],
);
}
}
// Main entry point
void main() {
runApp(const LayoutWidgetsDemo());
}