Unit 2 Flutter
Unit 2 Flutter
Objectives
Widgets
Gestures
Concept of State
Layers
Functions
Introduction to Widgets
Materials
Widgets
In Flutter, widgets are the building blocks of a Flutter app. Everything you see
on the screen of a Flutter app is a widget. They are like small pieces of a puzzle
that you put together to make a complete picture.
:
Chapter 2 Flutter Basics 1
Lifecycle of a StatefulWidget
In Flutter, a StatefulWidget is a widget that can change its state during its
lifetime. This means it can rebuild itself multiple times, reflecting changes in its
internal state or external data. Understanding the lifecycle of a StatefulWidget
is crucial for managing resources, performing actions at the right time, and
ensuring optimal performance.
2. initState()
3. didChangeDependencies()
4. build()
5. setState()
6. dispose()
:
Chapter 2 Flutter Basics 2
1. createState()
Purpose: This method is the first step in the lifecycle. It is called when the
StatefulWidget is created. It returns an instance of the State class associated with
the StatefulWidget .
Example:
@override
_ExampleState createState() => _ExampleState();
2. initState()
Purpose: This method is called once when the State object is inserted into
the widget tree. It is used for initializing any data or state the widget needs.
For example, initializing variables, setting up streams, or starting
animations.
Key Point: Always call super.initState() to ensure the parent class is also
initialized properly.
Example:
@override
void initState() {
super.initState();
// Initialization code here
}
3. didChangeDependencies()
Purpose: This method is called immediately after initState() and whenever the
widget’s dependencies change. Dependencies can change if the widget
depends on an InheritedWidget that itself changes.
Key Point: Useful for actions that depend on the context or inherited
widgets.
Example:
:
Chapter 2 Flutter Basics 3
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Respond to dependency changes
}
4. build()
Purpose: This method is called whenever the widget is to be rendered. It is
responsible for constructing the widget tree, which represents the UI. The
build() method can be called multiple times during the widget's lifecycle,
especially after calling setState() .
Key Point: The UI is built based on the current state, so changes in state
will trigger a rebuild.
Example:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stateful Widget Lifecycle'), ),
body: Center(
child: Text('Hello, World!'),
),
);
}
5. setState()
Purpose: This method is used to notify the framework that the internal state
of this object has changed. When called, it triggers a rebuild of the widget,
ensuring that the UI reflects the updated state.
Example:
:
Chapter 2 Flutter Basics 4
void _incrementCounter() {
setState(() {
_counter++;
});
}
6. dispose()
Purpose: This method is called when the State object is permanently removed
from the widget tree. It is used for final cleanup, such as canceling timers,
closing streams, or disposing of controllers.
Key Point: After dispose() , the widget is no longer active, and its State
object is considered dead.
Example:
@override
void dispose() {
// Clean up resources
super.dispose();
}
:
Chapter 2 Flutter Basics 5
Button Button
:
Chapter 2 Flutter Basics 6
Alert Box
Alert Box
��
https://vanshshah1411.github.io/MaterialVSCupertino_flutter/
void main() {
runApp(MyApp());
}
:
Chapter 2 Flutter Basics 7
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false, home:
DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text('Material vs Cupertino'), bottom: TabBar(
tabs: [
Tab(text: 'Material (Android)'), Tab(text: 'Cupertino (Apple / ios)'), ],
),
),
body: TabBarView(
children: [
// Material Design UI
MaterialUI(),
// Cupertino Design UI
CupertinoUI(),
],
),
),
),
);
}
}
:
Chapter 2 Flutter Basics 8
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, foregroundColor:
Colors.white,
padding: EdgeInsets.symmetric(horizontal: 24, ve shape:
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), ),
),
onPressed: () {
print('Material Button Pressed'); },
child: Text('Material Button'),
),
SizedBox(height: 20),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Backgrou foregroundColor: Colors.white, //
Text color padding: EdgeInsets.symmetric(horizontal: 24, ve shape:
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), ),
),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) { return AlertDialog(
title: Text('Material Alert'), content: Text('Material Design AlertDialog actions:
<Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop(); },
child: Text('OK'),
),
],
:
Chapter 2 Flutter Basics 9
);
},
);
},
child: Text('Material Alert'),
),
],
),
);
}
}
:
Chapter 2 Flutter Basics 10
actions: <Widget>[
CupertinoDialogAction(
child: Text('OK'),
onPressed: () {
Navigator.of(context).pop(); },
),
],
);
},
);
},
),
],
),
);
}
}
1. Row Widget
The Row widget in Flutter is used to display its children widgets in a horizontal
array. It arranges its children in a single horizontal line, which can be useful for
creating layouts where you want elements to be aligned side-by-side.
Here’s a simple example:
:
Chapter 2 Flutter Basics 11
2. mainAxisAlignment :
Defines how the children are aligned along the horizontal axis (main
axis).
:
Chapter 2 Flutter Basics 12
3. crossAxisAlignment :
Defines how the children are aligned along the vertical axis (cross axis).
Defines how much space the row should take along the main axis.
Values include:
MainAxisSize.min :
The row only takes up as much horizontal space as
needed by its children.
2. Column
The Column widget in Flutter is used to display its children widgets in a vertical
array. It arranges its children in a single vertical line, which is useful for creating
layouts where you want elements to be stacked one on top of the other.
:
Chapter 2 Flutter Basics 13
2. mainAxisAlignment :
Defines how the children are aligned along the vertical axis (main axis).
:
Chapter 2 Flutter Basics 14
MainAxisAlignment.spaceEvenly : Distributes children evenly with equal
space between them.
3. crossAxisAlignment :
Defines how the children are aligned along the horizontal axis (cross
axis).
CrossAxisAlignment.start :
Aligns children to the start of the column (left
for vertical columns).
4. mainAxisSize :
Defines how much space the column should take along the main axis.
Values include:
3. Container
The Container widget in Flutter is a versatile and flexible widget used to create
rectangular visual elements. It can be used for a variety of purposes such as
adding padding, margins, borders, and background colors, or for positioning
widgets in a specific layout.
:
Chapter 2 Flutter Basics 15
2. padding :
Adds space inside the container between its border and the child
widget.
3. margin :
Adds space outside the container, separating it from other widgets.
Defines the size of the container. If not provided, the container will size
itself based on its child and constraints.
5. color :
6. decoration :
:
Chapter 2 Flutter Basics 16
Allows more complex styling, such as adding borders, gradients, and
shadows.
7. child :
The widget inside the container. This is where you place the content of
the container.
Example Usage
Here’s an example demonstrating various properties of the Container widget:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Container Widget Exampl e')),
body: ContainerExample(),
),
));
}
:
Chapter 2 Flutter Basics 17
child: Text(
'Blue Container',
style: TextStyle(color: Colors.white), ),
),
SizedBox(height: 20),
Container(
alignment: Alignment.center,
padding: EdgeInsets.all(16.0), margin:
EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(12), boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.5), spreadRadius: 2,
blurRadius: 5,
offset: Offset(0, 3),
),
],
),
child: Text(
'Green Container with Shadow', style: TextStyle(color: Colors.white),
),
),
SizedBox(height: 20),
Container(
alignment: Alignment.center,
padding: EdgeInsets.all(16.0), margin:
EdgeInsets.all(16.0),
width: 200,
height: 100,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.purple, Colors.orange], ),
:
Chapter 2 Flutter Basics 18
borderRadius: BorderRadius.circular(10), ),
child: Text(
'Gradient Container',
style: TextStyle(color: Colors.white), ),
),
],
),
);
}
}
Explanation
1. Basic Container:
Key Points
Container is
highly customizable and can be used for many layout and
styling needs.
:
Chapter 2 Flutter Basics 19
margin adds space outside the container.
alignment and child control the placement and content within the container.
This flexibility makes the Container widget a powerful tool for creating various UI
elements and layouts in Flutter.
container
column
row
Text
Text('Hello, world!')
ElevatedButton(
onPressed: () {
// Action when button is pressed
},
child: Text('Press Me'),
)
This widget creates a button that says "Press Me". When you press it,
something happens (like ringing the doorbell).
Image.network('<https://example.com/myimage.jpg>')
Widgets Example
:
Chapter 2 Flutter Basics 20
Just like you combine different materials to build a house, you can combine
different widgets to build your app.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
:
Chapter 2 Flutter Basics 21
),
),
);
}
}
:
Chapter 2 Flutter Basics 22
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Ro unded corners
),
),
onPressed: () {
print("Row Button 2 Pressed");
},
child: Text('Button 2'),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Backgrou nd color
foregroundColor: Colors.white, // Text color padding:
EdgeInsets.symmetric(horizontal: 24, vertic al: 12), // Padding
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Ro unded corners
),
),
onPressed: () {
print("Row Button 3 Pressed");
},
child: Text('Button 3'),
),
],
);
}
}
class ColumnWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
:
Chapter 2 Flutter Basics 23
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Backgrou nd color
foregroundColor: Colors.white, // Text color padding:
EdgeInsets.symmetric(horizontal: 24, vertic al: 12), // Padding
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Ro unded corners
),
),
onPressed: () {
print("Column Button 1 Pressed"); },
child: Text('Button 1'),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Backgrou nd color
foregroundColor: Colors.white, // Text color padding:
EdgeInsets.symmetric(horizontal: 24, vertic al: 12), // Padding
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Ro unded corners
),
),
onPressed: () {
print("Column Button 2 Pressed"); },
child: Text('Button 2'),
),
ElevatedButton(
:
Chapter 2 Flutter Basics 24
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Backgrou nd color
foregroundColor: Colors.white, // Text color padding:
EdgeInsets.symmetric(horizontal: 24, vertic al: 12), // Padding
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Ro unded corners
),
),
onPressed: () {
print("Column Button 3 Pressed"); },
child: Text('Button 3'),
),
],
);
}
}
:
Chapter 2 Flutter Basics 25
}
class ContainerWidget extends StatelessWidget { @override
Widget build(BuildContext context) {
return Center(
child: Container(
decoration: BoxDecoration(color: Colors.deepPurple[90 0]),
padding: EdgeInsets.all(32),
child: Container(
padding: EdgeInsets.all(32), // Padding inside the container
decoration: BoxDecoration(
color: Colors.deepPurple[400], // Highlight paddi ng area
border: Border.all(color: Colors.black, width: 1 0),
),
child: Text(
'Content Area',
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w500,
color: Colors.black,
backgroundColor: Colors.deepPurple[100], ),
),
),
));
}
}
In this example:
Scaffold: Provides a structure for the app (like a skeleton for the house).
:
Chapter 2 Flutter Basics 26
AppBar: A widget for the app’s title bar.
Summary
Widgets in Flutter are like the pieces you use to build your
app. Each widget has a specific role, and by combining them,
you create the full user interface of your app.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
useMaterial3: true,
),
debugShowCheckedModeBanner: false,
home: DefaultTabController(
length: 10,
child: Scaffold(
appBar: AppBar(
title: const Text('Widget Examples'), bottom: const TabBar(
isScrollable: true,
tabs: [
:
Chapter 2 Flutter Basics 27
Tab(text: 'Row'), Tab(text: 'Column'), Tab(text: 'Text'),
Tab(text: 'Container'), Tab(text: 'Text Field'), Tab(text:
'Image'), Tab(text: 'List View'), Tab(text: 'Stack'),
Tab(text: 'Icon'), Tab(text: 'Scaffold'), ],
),
),
body: const TabBarView( children: [
RowWidget(),
ColumnWidget(),
TextWidget(),
ContainerWidget(), TextFieldWidget(),
ImageWidget(),
ListViewWidget(), StackWidget(),
IconWidget(),
ScaffoldWidget(), ],
),
),
),
);
}
}
@override
Widget build(BuildContext context) {
:
Chapter 2 Flutter Basics 28
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Background foregroundColor:
Colors.white, // Text color padding:
const EdgeInsets.symmetric(horizontal: 24, ve shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Round ),
),
onPressed: () {
print("Row Button 1 Pressed");
},
child: const Text('Button 1'),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Background foregroundColor:
Colors.white, // Text color padding:
const EdgeInsets.symmetric(horizontal: 24, ve shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Round ),
),
onPressed: () {
print("Row Button 2 Pressed");
},
child: const Text('Button 2'),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Background foregroundColor:
Colors.white, // Text color padding:
:
Chapter 2 Flutter Basics 29
const EdgeInsets.symmetric(horizontal: 24, ve shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Round ),
),
onPressed: () {
print("Row Button 3 Pressed");
},
child: const Text('Button 3'),
),
],
);
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Background foregroundColor:
Colors.white, // Text color padding:
const EdgeInsets.symmetric(horizontal: 24, ve shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Round ),
),
onPressed: () {
print("Column Button 1 Pressed");
},
child: const Text('Button 1'),
),
:
Chapter 2 Flutter Basics 30
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Background foregroundColor:
Colors.white, // Text color padding:
const EdgeInsets.symmetric(horizontal: 24, ve shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Round ),
),
onPressed: () {
print("Column Button 2 Pressed");
},
child: const Text('Button 2'),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent, // Background foregroundColor:
Colors.white, // Text color padding:
const EdgeInsets.symmetric(horizontal: 24, ve shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Round ),
),
onPressed: () {
print("Column Button 3 Pressed");
},
child: const Text('Button 3'),
),
],
);
}
}
:
Chapter 2 Flutter Basics 31
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'Material Design Text Widget',
style: TextStyle(
fontSize: 20, // Font size
fontWeight: FontWeight.w500, // Font weight color: Colors.black, // Text
color
letterSpacing: 1.0, // Letter spacing height: 1.5, // Line height
),
),
);
}
}
@override
Widget build(BuildContext context) {
return Center(
child: Container(
decoration: BoxDecoration(color: Colors.deepPurple[900] padding: const
EdgeInsets.all(32),
child: Container(
padding: const EdgeInsets.all(32), // Padding inside decoration: BoxDecoration(
color: Colors.deepPurple[400], // Highlight padding border: Border.all(color:
Colors.black, width: 10), ),
child: Text(
'Content Area',
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w500,
:
Chapter 2 Flutter Basics 32
color: Colors.black,
backgroundColor: Colors.deepPurple[100], ),
),
),
));
}
}
@override
Widget build(BuildContext context) {
return Center(
child: Padding(
padding: const EdgeInsets.all(32.0), child: TextField(
decoration: InputDecoration(
labelText: 'Enter your name', border: const OutlineInputBorder(),
prefixIcon: const Icon(Icons.person), filled: true,
fillColor: Colors.grey[200], ),
),
),
);
}
}
:
Chapter 2 Flutter Basics 33
padding: const EdgeInsets.all(32.0),
child: Center(
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2), spreadRadius: 5,
blurRadius: 7,
offset: const Offset(0, 3),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16), child: Image.network(
'https://images.unsplash.com/photo-17219905703 fit: BoxFit.cover,
),
),
),
),
),
);
}
}
@override
Widget build(BuildContext context) {
return Center(
child: Container(
padding: const EdgeInsets.all(32.0),
:
Chapter 2 Flutter Basics 34
child: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: const CircleAvatar(
backgroundColor: Colors.deepPurpleAccent, child: Icon(Icons.star, color:
Colors.white ),
title: Text('Item $index'),
subtitle: Text('Subtitle $index'), trailing: const Icon(Icons.chevron_right),
contentPadding:
const EdgeInsets.symmetric(horizontal: 16 ),
);
},
),
),
);
}
}
@override
Widget build(BuildContext context) {
return Center(
child: Stack(
alignment: Alignment.center,
children: [
// First Card (bottom-most)
Positioned(
child: Card(
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
:
Chapter 2 Flutter Basics 35
),
child: const SizedBox(
width: 200,
height: 200,
child: Center(child: Text('Card 1')), ),
),
),
// Second Card (middle)
Positioned(
left: 10,
top: 10,
child: Card(
elevation: 12,
shape: RoundedRectangleBorder( borderRadius:
BorderRadius.circular(16), ),
child: const SizedBox(
width: 180,
height: 180,
child: Center(child: Text('Card 2')), ),
),
),
// Third Card (top-most)
Positioned(
left: 20,
top: 20,
child: Card(
elevation: 16,
shape: RoundedRectangleBorder( borderRadius:
BorderRadius.circular(16), ),
child: const SizedBox(
width: 160,
height: 160,
child: Center(child: Text('Card 3')), ),
:
Chapter 2 Flutter Basics 36
),
),
],
),
);
}
}
@override
Widget build(BuildContext context) {
return const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center, children: [
Icon(Icons.favorite, size: 100, color: Colors.redAcc SizedBox(height: 20),
Icon(Icons.thumb_up, size: 100, color: Colors.blueAc SizedBox(height: 20),
Icon(Icons.access_alarm, size: 100, color: Colors.de ],
),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Scaffold Example'),
),
drawer: Drawer(
:
Chapter 2 Flutter Basics 37
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
const DrawerHeader(
decoration: BoxDecoration( color: Colors.deepPurpleAccent, ),
child: Text(
'Drawer Header',
style: TextStyle(
color: Colors.white, fontSize: 24,
),
),
),
ListTile(
title: const Text('Item 1'), onTap: () {},
),
ListTile(
title: const Text('Item 2'), onTap: () {},
),
],
),
),
body: const Center(
child: Text('Hello, Scaffold!'), ),
floatingActionButton: FloatingActionButton( onPressed: () {},
child: const Icon(Icons.add), ),
);
}
}
:
Chapter 2 Flutter Basics 38
Gestures
In Flutter, gestures are actions that users can perform with their fingers, like
tapping, dragging, or swiping, to interact with the app. Think of gestures as the
ways you can communicate with your app using touch.
Tap Gesture
A simple tap gesture can be detected using the GestureDetector widget.
GestureDetector(
onTap: () {
print('Tapped!');
},
child: Container(
color: Colors.blue,
width: 100,
height: 100,
child: Center(
child: Text('Tap Me'),
),
),
)
In this example:
:
Chapter 2 Flutter Basics 39
GestureDetector: This widget detects various gestures. Here, it detects a
tap.
Container: A widget that contains a blue box with text "Tap Me".
GestureDetector(
onLongPress: () {
print('Long Pressed!');
},
child: Container(
color: Colors.green,
width: 100,
height: 100,
child: Center(
child: Text('Long Press Me'),
),
),
)
Here:
Swipe Gesture
You can detect a swipe gesture (or drag) using the GestureDetector as well.
GestureDetector(
onPanUpdate: (details) {
print('Swiped: ${details.delta}');
},
child: Container(
color: Colors.red,
width: 100,
height: 100,
:
Chapter 2 Flutter Basics 40
child: Center(
child: Text('Swipe Me'),
),
),
)
In this example:
details.delta: This provides information about the swipe, like the direction
and speed.
Combining Gestures
You can detect multiple gestures on the same widget. Here’s an example:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
:
Chapter 2 Flutter Basics 41
@override
_GestureExamplesState createState() => _GestureExamplesSt ate();
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center, children: [
GestureDetector(
onTap: () => _updateMessage('Tap detected'), onDoubleTap: () =>
_updateMessage('Double Tap d etected'),
onLongPress: () => _updateMessage('Long Press d etected'),
onPanUpdate: (details) => _updateMessage( 'Pan detected:
${details.localPosition.toSt ring()}'),
onVerticalDragUpdate: (details) => _updateMessa ge(
'Vertical Drag detected: ${details.localPos ition.toString()}'),
child: Container(
color: Colors.blueAccent,
width: 500,
height: 500,
child: Center(
child: Text(
'Gesture Area',
style: TextStyle(color: Colors.white, fon tSize: 20),
),
:
Chapter 2 Flutter Basics 42
),
),
),
SizedBox(height: 20),
Text(
_gestureMessage,
style: TextStyle(fontSize: 16),
),
],
),
);
}
In this example:
Summary
Concept of State
In Flutter, the concept of "state" refers to any data or information that can
change over time within your app. The state of a widget is what allows it
to
:
Chapter 2 Flutter Basics 43
remember information and change its appearance or behavior in response to
user actions or other events.
StatelessWidget vs StatefulWidget
StatelessWidget: A widget that doesn't change over time. It has no state.
StatefulWidget: A widget that can change over time. It has a state that can
change.
1. Create a New Flutter Project: You can use your IDE or the command line to
create a new Flutter project.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
:
Chapter 2 Flutter Basics 44
_CounterScreenState createState() => _CounterScreenState ();
}
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Text(
'You have pressed the button this many time s:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4, ),
],
),
),
floatingActionButton: FloatingActionButton( onPressed:
_incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
:
Chapter 2 Flutter Basics 45
),
);
}
}
Explanation
1. Main Function:
void main() {
runApp(MyApp());
}
This is the entry point of the app. runApp starts the app and takes a widget
as an argument.
2. MyApp Widget:
This is the main widget of the app, which sets CounterScreen as the home
screen.
3. CounterScreen StatefulWidget:
:
Chapter 2 Flutter Basics 46
4. _CounterScreenState:
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Text(
'You have pressed the button this many tim es:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlin e4,
),
],
),
),
floatingActionButton: FloatingActionButton( onPressed:
_incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
:
Chapter 2 Flutter Basics 47
);
}
}
_counter: This variable holds the state, which is the number of times
the button has been pressed.
build Method: This method builds the UI. It includes a Scaffold with an
AppBar , a Center widget containing a Column , and a FloatingActionButton .
Summary
Layers
In modern software development, maintaining a well-organized and scalable
codebase is crucial for building robust applications. The layered architecture,
often referred to as clean architecture, is a design pattern that divides an
application into distinct layers, each responsible for a specific aspect of the
system.
:
Chapter 2 Flutter Basics 48
1. Presentation Layer
Widgets:
In Flutter, widgets are the basic building blocks of the user interface
(UI). They define the visual components and structure of the UI, such as
buttons, text fields, and layouts. Widgets are used to create the visual
representation of the app.
States:
State refers to the dynamic data in your application that can change
over time. In Flutter, state management is crucial for building interactive
and responsive UIs. State holds the current values of the UI
components and allows for updating them when needed.
Controllers:
Controllers manage the logic and interaction between the UI and the
data. They handle user inputs, update the state, and manage the flow of
data between the UI (widgets) and the underlying layers. Controllers are
responsible for ensuring that the correct data is displayed in the UI and
that user actions trigger the appropriate responses.
2. Application Layer
:
Chapter 2 Flutter Basics 49
Services:
3. Domain Layer
Models:
Models represent the core data structures and business logic of the
application. They define the entities and their relationships,
encapsulating the rules and behaviors associated with the data. Models
are usually independent of the UI and can be reused across different
parts of the application.
4. Data Layer
Repositories:
DTOs are simple objects used to transfer data between different layers
of the application. They are often used to encapsulate data that needs
to be passed from the data layer to the domain or presentation layers.
DTOs help in keeping the application layers loosely coupled by
providing a common format for data exchange.
Data Sources:
Data sources refer to the origin of the data, such as databases, web
APIs, or local storage. They provide the raw data that the repositories
access and manage. The data layer interacts directly with these
sources to retrieve or store information needed by the application.
:
Chapter 2 Flutter Basics 50
The Application Layer uses Services to execute business logic and interact
with the Domain Layer.
The Domain Layer contains the core models that represent the business
entities and logic.
The Data Layer manages the actual data, with Repositories accessing Data
Sources and using DTOs to transfer data across layers.
What is Dart?
Dart is a free and open-source programming language developed by Google.
It's used to create both the backend (server side) and frontend (user side) of
applications.
Key Components
1. Dart SDK:
The Software Development Kit (SDK) includes tools to write and run
Dart programs.
2. Dart VM:
The Dart Virtual Machine is a program that runs Dart code directly.
3. dart2js:
A tool that converts Dart code into JavaScript. This is useful because
not all websites support Dart, but they do support JavaScript.
:
Chapter 2 Flutter Basics 51
Simple Example
Here's a basic example to show how Dart works:
void main() {
print('Hello, world!');
}
Key Features
Server Side: Dart can be used to write server code.
User Side: Dart can be used to create user interfaces, especially with
Flutter for mobile apps.
Example Breakdown
1. Printing a Message:
void main() {
print('Hello, world!');
}
This code is the starting point of a Dart program. It uses the print
function to display a message.
2. Variables:
void main() {
var name = 'John Doe';
print('Hello, $name!');
}
Here, var name = 'John Doe'; creates a variable called name and assigns it the
value 'John Doe'. The print function then uses this variable to display a
personalized message.
:
Chapter 2 Flutter Basics 52
Like Java and C++, Dart follows OOP principles, making it powerful for
building complex applications.
3. Open Source:
4. Browser Support:
5. Type Safe:
7. Asynchronous Programming:
Example of Asynchronous
Programming in Dart
:
Chapter 2 Flutter Basics 53
void main() async {
print('Start');
print('End');
}
Explanation:
Declaring Variables
Single Variable:
type variable_name;
Multiple Variables:
:
Chapter 2 Flutter Basics 54
type variable1, variable2, variable3;
Types of Variables
1. Static Variables
2. Dynamic Variables
void main() {
int age = 30;
double height = 5.9;
bool isStudent = false;
String name = "Alice", city = "Wonderland";
print(age); // Output: 30
print(height); // Output: 5.9
print(isStudent);// Output: false
print(name); // Output: Alice
print(city); // Output: Wonderland
}
Keywords in Dart
Keywords in Dart are reserved words with predefined functions.
These keywords help define the structure and syntax of the Dart
programming language.
:
Chapter 2 Flutter Basics 55
https://dart.dev/language/keywords
Dynamic Variables
Declared with dynamic keyword.
Example:
void main() {
dynamic item = "Book";
print(item); // Output: Book
item = 10;
print(item); // Output: 10
}
:
Chapter 2 Flutter Basics 56
final name = "Alice";
final String city = "Wonderland";
const pi = 3.14;
const String greeting = "Hello";
void main() {
int? age;
age = null;
print(age); // Output: null
}
Introduction to Dart Data Types
In Dart, just like in other programming languages such as C, C++, or Java,
every variable has a specific type. This type determines what kind of data the
variable can hold. Understanding data types is crucial because it helps you
handle data correctly in your programs.
1. Numbers in Dart
In Dart, numbers are essential for representing and manipulating numeric
values. Dart provides a few different types for handling numbers, and each type
has its own characteristics and uses.
Example:
:
Chapter 2 Flutter Basics 57
void main() {
// Declare an integer
int num1 = 10;
print(num1); // Output: 10
}
Example:
void main() {
// Declare a double value
double num2 = 10.5;
print(num2); // Output: 10.5
}
3. num : This is a general type that can hold either int or double . It is useful when
you need a variable that can be either an integer or a floating-point
number.
Example:
void main() {
// Use num to hold different types of numbers num num1 = 10;
// an integer
num num2 = 10.5; // a double
print(num1); // Output: 10
print(num2); // Output: 10.5
}
Example:
:
Chapter 2 Flutter Basics 58
void main() {
// Parsing strings to numbers
var num1 = num.parse("5");
var num2 = num.parse("3.14");
Properties of Numbers
hashCode : Gets the hash code of the number.
sign :
Returns -1 for negative numbers, 0 for zero, and 1 for positive
numbers.
void main() {
int number = -5;
print(number.abs()); // Output: 5
}
void main() {
double number = 3.14;
:
Chapter 2 Flutter Basics 59
print(number.ceil()); // Output: 4
}
void main() {
double number = 3.14;
print(number.floor()); // Output: 3
}
void main() {
int number1 = 10;
int number2 = 20;
print(number1.compareTo(number2)); // Output: -1 }
void main() {
int dividend = 10;
int divisor = 3;
print(dividend.remainder(divisor)); // Output: 1 round() : Rounds the
void main() {
double number = 3.6;
print(number.round()); // Output: 4
}
void main() {
int number = 10;
:
Chapter 2 Flutter Basics 60
print(number.toDouble()); // Output: 10.0
}
void main() {
double number = 10.5;
print(number.toInt()); // Output: 10
}
void main() {
int number = 10;
print(number.toString()); // Output: "10"
}
void main() {
double number = 10.9;
print(number.truncate()); // Output: 10
}
void main() {
// Correct usage of num
num variable = 10;
variable = 10.5; // No error, num can be int or double
double
:
Chapter 2 Flutter Basics 61
double doubleVar = 10; // Can store an int value doubleVar = 10.5; //
Can also store a double value
2. Strings in Dart
Strings in Dart are used to represent sequences of characters. Dart provides
various features and methods to handle and manipulate strings efficiently.
Declaring Strings
In Dart, you can declare strings using either single quotes ( ' ) or double quotes
( " ). Both types of quotes work the same way.
Syntax:
Example:
void main() {
String greeting = 'Hello, Dart!';
print(greeting); // Output: Hello, Dart!
}
String Concatenation
You can combine strings using the + operator.
Example:
void main() {
String firstName = 'John';
String lastName = 'Doe';
String fullName = firstName + ' ' + lastName; print(fullName); //
Output: John Doe
}
String Interpolation
:
Chapter 2 Flutter Basics 62
Dart allows you to embed variables inside strings using ${} within double
quoted strings.
Example:
void main() {
String name = 'Alice';
int age = 30;
String introduction = 'Hello, my name is $name and I am $age years old.';
print(introduction); // Output: Hello, my name is Alice a nd I am 30 years old.
}
For simple variables, you can directly use the variable name without curly
braces:
Example:
void main() {
String name = 'Bob';
String greeting = 'Hi, $name!';
print(greeting); // Output: Hi, Bob!
}
Multi-line Strings
You can create multi-line strings using triple quotes ( ''' or """ ).
Example:
void main() {
String multiLine = '''This is a string
that spans across multiple
lines.''';
print(multiLine);
// Output:
// This is a string
// that spans across multiple
:
Chapter 2 Flutter Basics 63
// lines.
}
String Methods
Dart provides various methods to manipulate strings. Here are some commonly
used methods:
// Print length
print('Length of greeting: ${greeting.length}'); // Outpu t: Length of greeting: 13
// Convert to uppercase
print(greeting.toUpperCase()); // Output: HELLO, ALICE!
// Trim spaces
String padded = ' Dart ';
print(padded.trim()); // Output: Dart
// Substring
print(greeting.substring(7, 12)); // Output: Alice
// Check if contains
print(greeting.contains('Alice')); // Output: true
// Replace text
print(greeting.replaceAll('Alice', 'Bob')); // Output: He llo, Bob!
// Split text
String sentence = 'I love Dart programming.';
:
Chapter 2 Flutter Basics 64
List<String> words = sentence.split(' ');
print(words); // Output: [I, love, Dart, programming.] }
This guide should help you understand the basics of working with strings in
Dart, including declaring, manipulating, and using various string methods.
2. Accessing Characters
3. Querying Strings
contains(Pattern pattern, [int start = 0]) : Checks if the string contains the specified
pattern.
startsWith(Pattern pattern, [int start = 0]) : Checks if the string starts with the
specified pattern.
endsWith(String other) : Checks if the string ends with the specified string.
4. Manipulating Strings
:
Chapter 2 Flutter Basics 65
toUpperCase() : Converts all characters in the string to uppercase.
replaceFirst(Pattern from, String to, [int startIndex = 0]) : Replaces the first occurrence of a
pattern with a new string.
replaceRange(int start, int end, String replacement) : Replaces the substring from start to
end with a new string.
padLeft(int width, [String padding = ' ']) : Pads the string on the left to the specified
width.
padRight(int width, [String padding = ' ']) : Pads the string on the right to the
specified width.
substring(int start, [int end]) : Returns the substring from start to end.
split(Pattern pattern) :
Splits the string at each occurrence of the pattern and
returns a list of substrings.
Comparing Strings
Example Usage
Here's an example demonstrating some of these string methods:
:
Chapter 2 Flutter Basics 66
void main() {
String str = 'Hello, World!';
// Accessing Characters
print(str.codeUnitAt(0)); // Output: 72
print(str.runes.toList()); // Output: [72, 101, 108, 10 8, 111, 44, 32, 87, 111, 114,
108, 100, 33]
// Querying Strings
print(str.contains('World')); // Output: true
print(str.startsWith('Hello')); // Output: true print(str.endsWith('!')); //
Output: true
print(str.isEmpty); // Output: false
print(str.isNotEmpty); // Output: true
print(str.length); // Output: 13
// Manipulating Strings
print(str.toLowerCase()); // Output: hello, world! print(str.toUpperCase()); //
Output: HELLO, WORLD! print(str.trim()); // Output: Hello, World!
print(str.replaceAll('World', 'Dart')); // Output: Hell o, Dart!
print(str.substring(0, 5)); // Output: Hello print(str.split(', ')); // Output: [Hello,
World!] print(str.padLeft(15, '*')); // Output: **Hello, World! print(str.padRight(15,
'*')); // Output: Hello, World!**
// Advanced Replacement
String text = 'The quick brown fox';
String newText = text.replaceAllMapped(RegExp(r'\\b\\w'), (match) =>
match.group(0)!.toUpperCase());
print(newText); // Output: The Quick Brown Fox }
:
Chapter 2 Flutter Basics 67
3. Booleans
Booleans represent truth values: either true or false .
Example:
void main() {
// Declare boolean variables
bool isDay = true;
bool isNight = false;
Output:
Is it day? true
Is it night? false
4. List in Dart
In Dart, a List is a collection of items that are ordered and can be accessed by
their index. It is similar to arrays in other programming languages. Lists are
versatile and can hold various types of data, such as numbers, strings, or even
other lists.
Creating Lists
Lists in Dart can be created in several ways. Here’s a basic guide to creating
and using lists.
You can declare an empty list and then add elements to it.
void main() {
List<int> numbers = []; // Empty list of integers
:
Chapter 2 Flutter Basics 68
numbers.add(10); // Add elements to the list
numbers.add(20);
numbers.add(30);
void main() {
List<String> fruits = ['Apple', 'Banana', 'Cherry'];
3. Fixed-Size List:
You can create a list with a fixed size, where the size is defined at the time of
creation. You can then modify the elements, but the size remains fixed.
void main() {
List<String> fixedList = List<String>.filled(3, 'defaul t');
fixedList[0] = 'Hello';
fixedList[1] = 'World';
fixedList[2] = 'Dart';
dartCopy code
void main() {
List<int> generatedList = List<int>.generate(5, (index) =
:
Chapter 2 Flutter Basics 69
> index * 2);
dartCopy code
void main() {
List<String> colors = ['Red', 'Green', 'Blue'];
dartCopy code
void main() {
List<String> animals = ['Cat', 'Dog', 'Bird']; animals[1] = 'Fish'; //
addAll(Iterable<E> iterable) : Adds all elements of the given iterable to the end of
the list.
2. Removing Elements
:
Chapter 2 Flutter Basics 70
remove(Object value) : Removes the first occurrence of the value from the
list.
removeRange(int start, int end) : Removes elements from the specified range.
3. Accessing Elements
4. Updating Elements
insertAll(int index, Iterable<E> iterable) : Inserts all elements of the given iterable at
the specified index.
5. Querying Lists
:
Chapter 2 Flutter Basics 71
reversed : Returns an iterable with the elements of the list in reverse
order.
sublist(int start, [int end]) : Returns a new list containing the elements in the
specified range.
where(bool test(E element)) : Returns a new iterable with all elements that
satisfy the test.
forEach(void f(E element)) : Applies the function to each element of the list.
toList({bool growable = true}) : Returns a new list containing the elements of the
iterable.
Example Usage
Here's an example demonstrating some of these methods:
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
:
Chapter 2 Flutter Basics 72
// Add elements
numbers.add(6);
numbers.addAll([7, 8, 9]);
// Remove elements
numbers.remove(2);
numbers.removeAt(0);
numbers.removeLast();
// Access elements
print(numbers[0]); // Output: 3
print(numbers.first); // Output: 3
print(numbers.last); // Output: 8
// Update elements
numbers[0] = 10;
numbers.insert(1, 15);
// Query list
print(numbers.contains(15)); // Output: true
print(numbers.isEmpty); // Output: false
print(numbers.length); // Output: 6
// Transformation
var mapped = numbers.map((e) => e * 2).toList(); print(mapped); // Output:
[198, 198, 10, 12, 14, 20, 30]
:
Chapter 2 Flutter Basics 73
// Copy and clear
var copy = numbers.toList();
numbers.clear();
print(numbers); // Output: []
print(copy); // Output: [99, 99, 5, 6, 7, 10, 15] }
5. Maps in Dart
A Map in Dart is a collection of key-value pairs, where each key is associated
with a value. It is similar to dictionaries in Python or hash maps in other
programming languages. Maps are useful when you need to store and retrieve
data based on a unique key.
Creating Maps
Maps in Dart can be created in different ways. Here’s a basic guide to creating
and using maps.
You can declare an empty map and then add key-value pairs to it.
dartCopy code
void main() {
// Declaring an empty map
Map<String, String> emptyMap = {};
:
Chapter 2 Flutter Basics 74
dartCopy code
void main() {
// Declaring a map with initial values
Map<String, int> ages = {
'Alice': 30,
'Bob': 25,
'Charlie': 35
};
print(ages); // Output: {Alice: 30, Bob: 25, Charlie: 35} }
dartCopy code
void main() {
Map<String, String> capitals = {
'USA': 'Washington, D.C.',
'France': 'Paris',
'Japan': 'Tokyo'
};
// Accessing a value
print(capitals['France']); // Output: Paris
// Modifying a value
capitals['Japan'] = 'Kyoto'; // Change Tokyo to Kyoto
:
Chapter 2 Flutter Basics 75
putIfAbsent(K key, V ifAbsent()) : Adds a key-value pair to the map if the key is
not already present.
addAll(Map<K, V> other) : Adds all key-value pairs from another map to the
current map.
update(K key, V update(V value), {V ifAbsent()}) : Updates the value for the provided
key, or adds it if it does not exist.
remove(Object key) : Removes the value for the specified key from the
map.
3. Accessing Elements
4. Querying Maps
5. Transforming Maps
:
Chapter 2 Flutter Basics 76
forEach(void action(K key, V value)) : Applies the function to each key value
pair in the map.
Example Usage
Here's an example demonstrating some of these methods:
void main() {
Map<String, int> map = {'a': 1, 'b': 2, 'c': 3};
// Removing elements
map.remove('b'); // Remove key-value pair by key map.clear(); //
Clear all key-value pairs
// Accessing elements
map = {'a': 1, 'b': 2, 'c': 3};
print(map['a']); // Access value by key, Output: 1 print(map.containsKey('a')); //
Check if key exists, Out put: true
print(map.containsValue(2)); // Check if value exists, O utput: true
// Querying map
print(map.isEmpty); // Check if map is empty, Output: fa lse
print(map.isNotEmpty); // Check if map is not empty, Out
:
Chapter 2 Flutter Basics 77
put: true
print(map.length); // Get the number of key-value pairs, Output: 3
// Transforming maps
map.forEach((key, value) {
print('Key: $key, Value: $value');
});
// Output:
// Key: a, Value: 1
// Key: b, Value: 2
// Key: c, Value: 3
// Entries
print(map.entries); // Output: (MapEntry(a: 1), MapEntry (b: 2), MapEntry(c: 3),
MapEntry(d: 4))
}
Explanation:
Adding and Updating Elements: Methods like putIfAbsent , addAll , and update
Removing Elements: Methods like remove and clear are used to remove
elements from the map.
:
Chapter 2 Flutter Basics 78
Accessing Elements: Methods and properties like containsKey , containsValue , keys ,
values , and entries provide access to various parts of the map.
Querying Maps: Properties like isEmpty , isNotEmpty , and length help to query
the map.
Transforming Maps: Methods like map and forEach are used to transform or
apply functions to the map.
These methods provide powerful ways to manage and manipulate maps in Dart,
making them essential for Flutter development when dealing with key-value
data structures.
Comments in Dart
Comments help explain code for better understanding. They are not executed
by the compiler and serve as documentation.
Types of Comments
1. Single-line Comment:
Example:
void main() {
double area = 3.14 * 4 * 4;
// This prints the area of a circle with radius 4 print(area);
}
Output: 50.24
2. Multi-line Comment:
Example:
:
Chapter 2 Flutter Basics 79
void main() {
var lst = [1, 2, 3];
/* This prints the whole list at once */
print(lst);
}
Output: [1, 2, 3]
3. Documentation Comment:
Provide detailed explanations, often used for public APIs and generating
documentation.
Example:
/**
* This function prints a farewell message.
* It is used to say goodbye to users.
*/
void farewell() {
print('Goodbye, world!');
}
Summary
Single-line Comments: For brief notes or explanations on a single line.
:
Chapter 2 Flutter Basics 80