🌟 UI Design in Flutter: A Beginner’s Complete Guide with Examples
✅ Introduction
Flutter is Google’s open-source UI toolkit for building beautiful, fast, and cross-platform apps using a single codebase.
In this post, we’ll learn the very basics of UI design in Flutter, including:
- Stateless and Stateful widgets
- AppBar and SafeArea
- home and body in MaterialApp
- Flutter Widget Lifecycle (Basics)
- Simple Working Code Examples
✅ What is a Widget in Flutter?
In Flutter, everything is a Widget – buttons, text, layouts, even the entire app itself!
Widgets are the building blocks of your app’s UI.
✅ Types of Widgets: Stateless vs Stateful
1. StatelessWidget
A widget that never changes once built.
Ideal for static screens like splash screens, simple text, images, etc.
🧑💻 Example: Simple Stateless Widget
import 'package:flutter/material.dart';
void main() {
runApp(MyStatelessApp());
}
class MyStatelessApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Stateless Example',
home: Scaffold(
appBar: AppBar(title: Text('Stateless Widget')),
body: Center(
child: Text('Hello Flutter! This is Stateless.', style: TextStyle(fontSize: 20)),
),
),
);
}
}
Output: Displays a screen with AppBar and centered text.
2. StatefulWidget
A widget that can change over time.
Example: Buttons that change text, counters, animations.
🧑💻 Example: Simple Stateful Widget (Counter App)
import 'package:flutter/material.dart';
void main() {
runApp(MyStatefulApp());
}
class MyStatefulApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Stateful Example',
home: CounterScreen(),
);
}
}
class CounterScreen extends StatefulWidget {
@override
_CounterScreenState createState() => _CounterScreenState();
}
class _CounterScreenState extends State<CounterScreen> {
int count = 0;
void incrementCounter() {
setState(() {
count++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Stateful Widget')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Button pressed $count times', style: TextStyle(fontSize: 20)),
SizedBox(height: 20),
ElevatedButton(
onPressed: incrementCounter,
child: Text('Increment'),
),
],
),
),
);
}
}
Output: Displays a counter that increments when the button is clicked.
✅ Understanding MaterialApp, home, body, and Scaffold
👉 MaterialApp
The main wrapper for your app. Provides themes, navigation, etc.
👉 home
The first screen/page of your app. Usually holds a Scaffold.
👉 Scaffold
Provides a default visual layout. Includes AppBar, Body, Drawer, FloatingActionButton, etc.
👉 body
The main content area of your app screen.
🧑💻 Example: Using AppBar, Body, and Scaffold Together
import 'package:flutter/material.dart';
void main() {
runApp(MyScaffoldApp());
}
class MyScaffoldApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Scaffold Example',
home: Scaffold(
appBar: AppBar(title: Text('My AppBar')),
body: Center(child: Text('This is the body content')),
),
);
}
}
Output: Screen with a top AppBar and body text.
✅ What is SafeArea?
On some devices, content may get hidden behind notches, status bars, or other screen areas.
SafeArea ensures content avoids system UI intrusions.
🧑💻 Example:
import 'package:flutter/material.dart';
void main() {
runApp(MySafeAreaApp());
}
class MySafeAreaApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SafeArea Example',
home: Scaffold(
body: SafeArea(
child: Center(
child: Text('This content is safe from notches & status bars.'),
),
),
),
);
}
}
Output: Keeps your content safe inside visible screen areas.
✅ Flutter Widget Lifecycle (For StatefulWidgets)
Method | Purpose |
---|---|
initState() | Called when widget is first created |
build() | Builds the UI every time state changes |
setState() | Triggers UI rebuild |
dispose() | Clean-up work (e.g., close streams) |
🧑💻 Lifecycle Example with Logs:
import 'package:flutter/material.dart';
void main() {
runApp(LifecycleExampleApp());
}
class LifecycleExampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LifecycleScreen(),
);
}
}
class LifecycleScreen extends StatefulWidget {
@override
_LifecycleScreenState createState() => _LifecycleScreenState();
}
class _LifecycleScreenState extends State<LifecycleScreen> {
@override
void initState() {
super.initState();
print('initState called');
}
@override
void dispose() {
print('dispose called');
super.dispose();
}
@override
Widget build(BuildContext context) {
print('build called');
return Scaffold(
appBar: AppBar(title: Text('Lifecycle Demo')),
body: Center(child: Text('Check console for lifecycle logs')),
);
}
}
Output: Check your debug console for logs showing the order of method calls.
✅ Summary
In this beginner guide to Flutter UI design, you’ve learned:
- ✔️ Stateless and Stateful Widgets
- ✔️ AppBar, Scaffold, Body
- ✔️ SafeArea
- ✔️ Widget Lifecycle basics
✅ Next Steps
In upcoming posts, we’ll cover:
- Layouts (Row, Column, Stack)
- Navigation
- Theme and Styling
- Custom Widgets
✅ Practice Task for You!
Mini Project Idea:
👉 Create a Mini Counter App with two buttons: Increment and Decrement.
Happy Fluttering! 🚀
0 Comments