0% found this document useful (0 votes)
7 views

Unit 2 Flutter

Chapter 2 covers the basics of Flutter, focusing on widgets, gestures, state management, and Dart programming concepts. It explains the lifecycle of StatefulWidgets, detailing methods like createState, initState, and dispose, which are essential for managing widget state and resources. Additionally, it introduces Material and Cupertino design principles, highlighting their key characteristics and differences.

Uploaded by

Rajesh Nagar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Unit 2 Flutter

Chapter 2 covers the basics of Flutter, focusing on widgets, gestures, state management, and Dart programming concepts. It explains the lifecycle of StatefulWidgets, detailing methods like createState, initState, and dispose, which are essential for managing widget state and resources. Additionally, it introduces Material and Cupertino design principles, highlighting their key characteristics and differences.

Uploaded by

Rajesh Nagar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 80

Chapter 2 : Flutter Basics

Objectives
Widgets

Gestures

Concept of State

Layers

Introduction to Dart Programming

Variables and Data types

Decision Making and Loops

Functions

Object Oriented Programming.

Introduction to Widgets

Widget Build Visualization

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.

The lifecycle of a StatefulWidget involves the following stages:


1. createState()

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 .

Key Point: This method is called only once.

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.

Key Point: Use this method responsibly to avoid unnecessary rebuilds.

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();
}

Summary of Stateful Widget Lifecycle:


1. createState() : Called once when the widget is created.

2. initState() : Initializes the widget's state.


3. didChangeDependencies() : Called when dependencies change. 4.

build() : Constructs the UI.

5. setState() : Triggers a rebuild of the widget.

6. dispose() : Final cleanup when the widget is permanently removed.

Understanding the Stateful Widget lifecycle allows you to manage resources


efficiently, perform initialization and cleanup actions at the right time, and
control how your widget responds to state changes.

Types of Design System

:
Chapter 2 Flutter Basics 5

Material Design impact.

Material Design is a design language 3. Motion Provides Meaning:


developed by Google. It is used Motion in Material Design is used
primarily for Android apps but has to provide context and meaning.
become popular across various For example, transitions and
platforms due to its clean, modern animations help users understand
aesthetics and usability principles. the relationship between different
Material Design provides a consistent elements.
look and feel with a set of guidelines Cupertino Design
and components.
Cupertino Design is a design
language developed by Apple for
Key Principles of
iOS. It aims to create a user
Material Design:
experience that aligns with iOS
1. Material Metaphor: Material conventions and aesthetics.
Design is based on the metaphor Cupertino widgets provide a native
of physical materials like paper iOS look and feel.
and ink. It uses shadows, depth,
and responsive animations to Key Principles of
mimic how real-world materials Cupertino Design:
behave.
1. Consistency with iOS: Cupertino
2. Bold, Graphic, Intentional: widgets adhere to the design
Emphasis on bold colors, large guidelines set by Apple for iOS
typography, and meaningful use apps, ensuring that apps have a
of space. It aims for clarity and consistent look and feel with
native iOS applications. Design.

2. Flat and Minimalistic: Cupertino 3. Native Feel: Cupertino widgets


design tends to use flat, are styled to feel native on iOS,
minimalistic elements without the using iOS-specific patterns,
elevated effects seen in Material colors, and interactions.

Button Button

:
Chapter 2 Flutter Basics 6

Alert Box

Alert Box
��

https://vanshshah1411.github.io/MaterialVSCupertino_flutter/

�� Material Design Vs Cupertino Design

import 'package:flutter/material.dart'; import


'package:flutter/cupertino.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {


@override

:
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(),
],
),
),
),
);
}
}

class MaterialUI extends StatelessWidget { @override


Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0), child: Column(
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
ElevatedButton(

:
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'),
),
],
),
);
}
}

class CupertinoUI extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
CupertinoButton(
color: CupertinoColors.activeBlue,
child: Text('Cupertino Button'),
onPressed: () {
print("Cupertino Button Pressed"); },
),
SizedBox(height: 20),
CupertinoButton(
color: CupertinoColors.activeBlue,
child: Text('Cupertino Alert'),
onPressed: () {
showCupertinoDialog(
context: context,
builder: (BuildContext context) { return CupertinoAlertDialog(
title: Text('Cupertino Alert'), content: Text('Cupertino Design AlertDialo

:
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

Key Properties of the Row Widget


1. children :

A list of widgets that are arranged horizontally. These can be any


widget, such as Text , Icon , Container , etc.

2. mainAxisAlignment :

Defines how the children are aligned along the horizontal axis (main
axis).

Common values include:


MainAxisAlignment.start : Aligns children to the start of the row.

MainAxisAlignment.end : Aligns children to the end of the row.

MainAxisAlignment.center : Centers children within the row.

MainAxisAlignment.spaceBetween : Distributes children evenly with space


between them.

MainAxisAlignment.spaceAround : Distributes children evenly with space


around them.

MainAxisAlignment.spaceEvenly : Distributes children evenly with equal


space between them.

:
Chapter 2 Flutter Basics 12
3. crossAxisAlignment :

Defines how the children are aligned along the vertical axis (cross axis).

Common values include:

CrossAxisAlignment.start : Aligns children to the start of the row (top for


horizontal rows).

CrossAxisAlignment.end : Aligns children to the end of the row (bottom for


horizontal rows).

CrossAxisAlignment.center : Centers children within the row vertically.

CrossAxisAlignment.stretch : Stretches children to fill the vertical space. 4. mainAxisSize :

Defines how much space the row should take along the main axis.

Values include:

MainAxisSize.max : The row takes up as much horizontal space as


possible.

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

Key Properties of the Column Widget


1. children :

A list of widgets arranged vertically. These can be any widget, such as


Text , Icon , Container , etc.

2. mainAxisAlignment :
Defines how the children are aligned along the vertical axis (main axis).

Common values include:

MainAxisAlignment.start : Aligns children to the top of the column.

MainAxisAlignment.end : Aligns children to the bottom of the column.

MainAxisAlignment.center : Centers children within the column.

MainAxisAlignment.spaceBetween : Distributes children evenly with space


between them.

MainAxisAlignment.spaceAround : Distributes children evenly with space


around them.

:
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).

Common values include:

CrossAxisAlignment.start :
Aligns children to the start of the column (left
for vertical columns).

CrossAxisAlignment.end : Aligns children to the end of the column (right for


vertical columns).

CrossAxisAlignment.center : Centers children within the column


horizontally.

CrossAxisAlignment.stretch : Stretches children to fill the horizontal


space.

4. mainAxisSize :

Defines how much space the column should take along the main axis.

Values include:

MainAxisSize.max : The column takes up as much vertical space as


possible.

MainAxisSize.min : The column only takes up as much vertical space as


needed by its children.

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

Key Properties of the Container Widget


1. alignment :

Aligns the child widget within the container.

Common values include Alignment.center , Alignment.topLeft ,


Alignment.bottomRight , etc.

2. padding :

Adds space inside the container between its border and the child
widget.

Defined using EdgeInsets (e.g., EdgeInsets.all(16.0) ).

3. margin :
Adds space outside the container, separating it from other widgets.

Defined using EdgeInsets (e.g., EdgeInsets.all(16.0) ).

4. width and height :

Defines the size of the container. If not provided, the container will size
itself based on its child and constraints.

5. color :

Sets the background color of the container.

6. decoration :

:
Chapter 2 Flutter Basics 16
Allows more complex styling, such as adding borders, gradients, and
shadows.

Defined using BoxDecoration (e.g., BoxDecoration(color: Colors.blue, borderRadius:


BorderRadius.circular(10)) ).

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(),
),
));
}

class ContainerExample extends StatelessWidget { @override


Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
alignment: Alignment.center,
padding: EdgeInsets.all(16.0),
margin: EdgeInsets.all(16.0),
width: 200,
height: 100,
color: Colors.blue,

:
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:

color : Sets a solid background color ( Colors.blue ).

padding : Adds space inside the container.

margin : Adds space outside the container.

width and height : Define the size of the container.

child : Displays a Text widget inside the container.

2. Container with Decoration:

decoration : Uses BoxDecoration to set a background color, border radius, and


shadow.

BoxShadow : Adds a shadow effect to the container.

3. Container with Gradient:


decoration : Uses BoxDecoration to set a gradient background. gradient :

Applies a linear gradient from Colors.purple to Colors.orange .

Key Points
Container is
highly customizable and can be used for many layout and
styling needs.

padding adds space inside the container.

:
Chapter 2 Flutter Basics 19
margin adds space outside the container.

decoration allows for complex styling including borders, gradients, and


shadows.

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 Widget: This is like writing something on the wall.

Text('Hello, world!')

This widget displays the text "Hello, world!" on the screen.

Button Widget: This is like a button you press to ring a doorbell.

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 Widget: This is like hanging a picture on the wall.

Image.network('<https://example.com/myimage.jpg>')

This widget shows an image from the internet.

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.

Here's a simple example of combining widgets to create a basic screen with


some text and a button:

import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
title: Text('Widget Examples'),
bottom: TabBar(
tabs: [
Tab(text: 'Row'),
Tab(text: 'Column'),
Tab(text: 'Text'),
Tab(text: 'Container'),
],
),
),
body: TabBarView(
children: [
RowWidget(),
ColumnWidget(),
TextWidget(),
ContainerWidget(),
],
),

:
Chapter 2 Flutter Basics 21
),
),
);
}
}

class RowWidget extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, 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("Row 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

:
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'),
),
],
);
}
}

class TextWidget extends StatelessWidget {


@override
Widget build(BuildContext context) {
return 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
),
),
);
}

:
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:

MaterialApp: The main widget that starts your app.

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.

Center: Centers its child widgets.

Column: Arranges its children vertically.

Text: Displays text.


ElevatedButton: A button you can press.

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());
}

class MyApp extends StatelessWidget {


const MyApp({super.key});

@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(), ],
),
),
),
);
}
}

class RowWidget extends StatelessWidget { const


RowWidget({super.key});

@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'),
),
],
);
}
}

class ColumnWidget extends StatelessWidget {


const ColumnWidget({super.key});

@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'),
),
],
);
}
}

class TextWidget extends StatelessWidget {


const TextWidget({super.key});

:
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
),
),
);
}
}

class ContainerWidget extends StatelessWidget { const


ContainerWidget({super.key});

@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], ),
),
),
));
}
}

class TextFieldWidget extends StatelessWidget { const


TextFieldWidget({super.key});

@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], ),
),
),
);
}
}

class ImageWidget extends StatelessWidget { const


ImageWidget({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Padding(

:
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,
),
),
),
),
),
);
}
}

class ListViewWidget extends StatelessWidget {


const ListViewWidget({super.key});

@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 ),
);
},
),
),
);
}
}

class StackWidget extends StatelessWidget {


const StackWidget({super.key});

@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
),
),
],
),
);
}
}

class IconWidget extends StatelessWidget {


const IconWidget({super.key});

@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 ],
),
);
}
}

class ScaffoldWidget extends StatelessWidget {


const ScaffoldWidget({super.key});

@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.

Example to Understand Gestures


Imagine you have a smartphone. When you touch the screen in different ways,
different things happen:

Tap: Like pressing a button on a remote control.

Double Tap: Like double-clicking with a mouse.

Long Press: Like holding down a button.

Swipe: Like flipping through pages in a book.

Common Gestures in Flutter


Flutter provides several widgets to detect and respond to these gestures. Here
are a few examples:

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.

onTap: This callback is triggered when the container is tapped.

Container: A widget that contains a blue box with text "Tap Me".

Long Press Gesture


Detecting a long press gesture is just as easy.

GestureDetector(
onLongPress: () {
print('Long Pressed!');
},
child: Container(
color: Colors.green,
width: 100,
height: 100,
child: Center(
child: Text('Long Press Me'),
),
),
)

Here:

onLongPress: This callback is triggered when the container is long


pressed.

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:

onPanUpdate: This callback is triggered when the container is swiped or


dragged.

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());
}

class MyApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text('Gesture Examples'),
),
body: GestureExamples(),
),
);
}
}
class GestureExamples extends StatefulWidget {

:
Chapter 2 Flutter Basics 41
@override
_GestureExamplesState createState() => _GestureExamplesSt ate();
}

class _GestureExamplesState extends State<GestureExamples> {


String _gestureMessage = 'Perform a gesture';

@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),
),
],
),
);
}

void _updateMessage(String message) {


setState(() {
_gestureMessage = message;
});
}
}

In this example:

onTap: Detects a single tap.

onDoubleTap: Detects a double tap.

onLongPress: Detects a long press.

Summary

Gestures in Flutter allow you to make your app interactive. By


using widgets like GestureDetector , you can respond to various
touch actions such as taps, swipes, and long presses. This
makes your app more engaging and user-friendly.

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.

Example to Understand State


Think of a simple counter app where you press a button to increase a number
displayed on the screen. The number is the state, and pressing the button
changes the state.

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.

Simple StatefulWidget Example: Counter App


Let's create a basic counter app where the number increases each time you
press a button.

1. Create a New Flutter Project: You can use your IDE or the command line to
create a new Flutter project.

2. Create the Counter Widget:

import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterScreen(),
);
}
}
class CounterScreen extends StatefulWidget {
@override

:
Chapter 2 Flutter Basics 44
_CounterScreenState createState() => _CounterScreenState ();
}

class _CounterScreenState extends State<CounterScreen> { int _counter =


0;

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:

class MyApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterScreen(),
);
}
}

This is the main widget of the app, which sets CounterScreen as the home
screen.

3. CounterScreen StatefulWidget:

class CounterScreen extends StatefulWidget {


@override
_CounterScreenState createState() => _CounterScreenSta te();
}
CounterScreen is a stateful widget that can change over time.

:
Chapter 2 Flutter Basics 46
4. _CounterScreenState:

class _CounterScreenState extends State<CounterScreen> { int _counter =


0;

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.

_incrementCounter: This method increases the _counter by 1 and calls


setState to update the UI.

build Method: This method builds the UI. It includes a Scaffold with an
AppBar , a Center widget containing a Column , and a FloatingActionButton .

Summary

In this simple example, the state ( _counter ) is stored in the


_CounterScreenState class. When the button is pressed, the state is
updated, and the UI is rebuilt to reflect the new state. This
demonstrates how state in Flutter allows your app to react to
user input and update its interface accordingly.

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:

Services contain the business logic of the application. They perform


operations that are not directly tied to the UI but are essential for the
functioning of the app, such as fetching data from an API, processing
user inputs, or executing business rules. Services act as intermediaries
between the presentation layer and the domain layer.

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:

Repositories are responsible for handling data operations such as


fetching, storing, and updating data. They abstract the data sources
from the rest of the application, providing a consistent interface for
accessing data. Repositories ensure that the application does not need
to know where the data comes from (e.g., a database, an API, or a local
file).

DTOs (Data Transfer Objects):

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

Summary of Layer Interaction


The Presentation Layer interacts with the Application Layer to handle user
inputs, display data, and manage UI state.

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.

This architecture promotes separation of concerns, making it easier to manage,


test, and maintain the application. Each layer has a distinct responsibility,
ensuring that changes in one part of the application do not negatively impact
other parts.

Introduction to Dart Programming


Objective: Understand what Dart is and why it's used with Flutter.

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!');
}

This program prints " Hello, world! " on the screen.

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.

JavaScript Compatibility: Dart code can be converted to JavaScript,


making it versatile for web development.

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

Features of Dart Programming


Language Dart has several important features:
1. Easy to Understand:

Dart's syntax is similar to C# and Java, making it familiar to many


developers.

It supports code reuse, keeping programs clean and easy to


understand.

2. Object-Oriented Programming (OOP):

Like Java and C++, Dart follows OOP principles, making it powerful for
building complex applications.

3. Open Source:

Dart is open source, making it popular among individual developers and


organizations.

4. Browser Support:

Dart programs can be converted to JavaScript using the dart2js


compiler, ensuring compatibility with all modern web browsers.

5. Type Safe:

Dart combines static and runtime checks to ensure variables match


their defined types, reducing errors.

6. Flexible Compilation and Execution:

Supports both Just-in-Time (JIT) and Ahead-of-Time (AOT)


compilation, offering flexibility in how code is compiled and executed.

The dart2js tool adds further value by converting Dart code to


JavaScript.

7. Asynchronous Programming:

Dart supports asynchronous programming, allowing it to handle multiple


tasks simultaneously and efficiently.

Example of Asynchronous
Programming in Dart

:
Chapter 2 Flutter Basics 53
void main() async {
print('Start');

await Future.delayed(Duration(seconds: 2), () { print('Hello after 2


seconds');
});

print('End');
}

Explanation:

print('Start'); is executed first.

await Future.delayed(...) waits for 2 seconds before printing 'Hello after 2


seconds'.

print('End'); is executed last, but before the delayed message.

This example demonstrates how Dart can handle tasks asynchronously,


allowing other parts of the code to run while waiting.

Variables and Data Types


Variables in Dart
What is a Variable?
A variable is a name assigned to a memory location where data is stored. The
type of variable depends on the type of data it stores.

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

3. Final or Const Variables

Rules for Variable Names


Cannot be a keyword.

Can contain alphabets and numbers.

No spaces or special characters (except _ and $ ).

Cannot start with a number.

Example of Variable Declaration

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.

They cannot be used as variable names or identifiers.

These keywords help define the structure and syntax of the Dart
programming language.

:
Chapter 2 Flutter Basics 55

Common Keywords in Dart

All Keywords refer

https://dart.dev/language/keywords

Dynamic Variables
Declared with dynamic keyword.

Can store any type of value.

Example:

void main() {
dynamic item = "Book";
print(item); // Output: Book

item = 10;
print(item); // Output: 10
}

Final and Const Variables


Final: Value assigned once, can be set at runtime.

:
Chapter 2 Flutter Basics 56
final name = "Alice";
final String city = "Wonderland";

Const: Compile-time constant, value known before runtime.

const pi = 3.14;
const String greeting = "Hello";

Null Safety in Dart


Variables can be declared to hold null values by appending ? .

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.

Types of Numbers in Dart


1. int : Used to represent whole numbers (integers).

Syntax: int var_name;

Example:

:
Chapter 2 Flutter Basics 57
void main() {
// Declare an integer
int num1 = 10;
print(num1); // Output: 10
}

2. double : Used to represent numbers with decimal points (floating-point


numbers).

Syntax: double var_name;

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
}

Parsing Strings to Numbers


Dart allows you to convert strings containing numeric values into actual
numbers using the parse() function.

Example:

:
Chapter 2 Flutter Basics 58
void main() {
// Parsing strings to numbers
var num1 = num.parse("5");
var num2 = num.parse("3.14");

// Adding parsed numbers


var sum = num1 + num2;
print("Sum = $sum"); // Output: Sum = 8.14 }

Properties of Numbers
hashCode : Gets the hash code of the number.

isFinite : Checks if the number is finite (not infinite).

isInfinite : Checks if the number is infinite.


isNaN : Checks if the number is 'Not a Number' (NaN).

isNegative : Checks if the number is negative.

sign :
Returns -1 for negative numbers, 0 for zero, and 1 for positive
numbers.

isEven : Checks if the number is even.

isOdd : Checks if the number is odd.

Methods for Numbers


abs() : Returns the absolute value.

void main() {
int number = -5;
print(number.abs()); // Output: 5
}

ceil() : Rounds the number up to the nearest integer.

void main() {
double number = 3.14;

:
Chapter 2 Flutter Basics 59
print(number.ceil()); // Output: 4
}

floor() : Rounds the number down to the nearest integer.

void main() {
double number = 3.14;
print(number.floor()); // Output: 3
}

compareTo() : Compares the number with another number.

void main() {
int number1 = 10;
int number2 = 20;
print(number1.compareTo(number2)); // Output: -1 }

remainder() : Returns the remainder after division.

void main() {
int dividend = 10;
int divisor = 3;
print(dividend.remainder(divisor)); // Output: 1 round() : Rounds the

number to the nearest integer.

void main() {
double number = 3.6;
print(number.round()); // Output: 4
}

toDouble() : Converts the number to a double.

void main() {
int number = 10;

:
Chapter 2 Flutter Basics 60
print(number.toDouble()); // Output: 10.0
}

toInt() : Converts the number to an integer.

void main() {
double number = 10.5;
print(number.toInt()); // Output: 10
}

toString() : Converts the number to a string.

void main() {
int number = 10;
print(number.toString()); // Output: "10"
}

truncate() : Removes the fractional part of the number.

void main() {
double number = 10.9;
print(number.truncate()); // Output: 10
}

Example: Handling Different Number Types


Example of Type Conversion and Errors:

void main() {
// Correct usage of num
num variable = 10;
variable = 10.5; // No error, num can be int or double

// Error: Cannot assign double to int


int integerVar = 10;
// integerVar = 10.5; // This line will cause an error // Correct usage of

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:

String var_name = 'value';

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:

Example: Working with Strings


Example:
void main() {
String name = 'Alice';
String greeting = 'Hello, $name!';

// 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.

Basic String Methods


1. Creating Strings

String.fromCharCodes(Iterable<int> charCodes) : Creates a string from a list of


character codes.
String.fromCharCode(int charCode) : Creates a string from a single character code.

String.fromEnvironment(String name, {String defaultValue}) : Gets a string from environment


variables.

2. Accessing Characters

codeUnitAt(int index) : Returns the UTF-16 code unit at the specified


index.

runes : Returns an iterable of the Unicode code points of the string.

characters :Returns an iterable of the string's characters (requires the


characters package).

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.

isEmpty : Checks if the string is empty.

isNotEmpty : Checks if the string is not empty.

length : Returns the number of characters in the string.

4. Manipulating Strings

toLowerCase() : Converts all characters in the string to lowercase.

:
Chapter 2 Flutter Basics 65
toUpperCase() : Converts all characters in the string to uppercase.

trim() : Removes leading and trailing whitespace from the string.

trimLeft() : Removes leading whitespace from the string.

trimRight() : Removes trailing whitespace from the string.

replaceAll(Pattern from, String replace) : Replaces all occurrences of a pattern


with a new string.

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.

join(Iterable<String> strings) : Joins a list of strings into a single string. 5.

Comparing Strings

compareTo(String other) : Compares this string to another string. ==

(equality operator): Checks if two strings are equal.

hashCode : Returns the hash code for the string.

6. Interpolating and Formatting Strings

String interpolation: String name = 'World'; print('Hello, $name!');

replaceAllMapped(Pattern from, String replace(Match match)) :


Replaces all occurrences
of a pattern with a new string computed from a function.

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!**

// Interpolating and Formatting Strings


String name = 'Dart';
print('Hello, $name!'); // Output: Hello, Dart!

// 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;

// Print the values


print("Is it day? $isDay");
print("Is it night? $isNight");
}

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.

1. Declaring an Empty List:

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);

print(numbers); // Output: [10, 20, 30]


}

2. Declaring a List with Initial Elements:

You can declare a list with some initial values.

void main() {
List<String> fruits = ['Apple', 'Banana', 'Cherry'];

print(fruits); // Output: [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';

print(fixedList); // Output: [Hello, World, Dart] }

4. List with Generated Values:

You can also create a list by generating values using a function.

dartCopy code
void main() {
List<int> generatedList = List<int>.generate(5, (index) =

:
Chapter 2 Flutter Basics 69
> index * 2);

print(generatedList); // Output: [0, 2, 4, 6, 8] }

Accessing List Elements


You can access elements in a list using their index, which starts at 0.

dartCopy code
void main() {
List<String> colors = ['Red', 'Green', 'Blue'];

print(colors[0]); // Output: Red


print(colors[1]); // Output: Green
print(colors[2]); // Output: Blue
}

Modifying List Elements


You can change the value of a specific element by accessing it via its index.

dartCopy code
void main() {
List<String> animals = ['Cat', 'Dog', 'Bird']; animals[1] = 'Fish'; //

Change 'Dog' to 'Fish'

print(animals); // Output: [Cat, Fish, Bird]


}

Basic List Methods


1. Adding Elements

add(E value) : Adds a single element to the end of the list.

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.

removeAt(int index) : Removes the element at the specified index.

removeLast() : Removes the last element of the list.

removeRange(int start, int end) : Removes elements from the specified range.

3. Accessing Elements

elementAt(int index) : Returns the element at the specified index. first :

Gets the first element of the list.

last : Gets the last element of the list.


single :
Gets the single element of the list, assuming the list has only
one element.

indexOf(E element) : Returns the first index of the element, or -1 if not


found.

lastIndexOf(E element) : Returns the last index of the element, or -1 if not


found.

4. Updating Elements

[] (index operator): Access or update the element at the specified


index.

insert(int index, E element) : Inserts an element at the specified index.

insertAll(int index, Iterable<E> iterable) : Inserts all elements of the given iterable at
the specified index.

5. Querying Lists

contains(Object element) : Checks if the list contains the specified element.

isEmpty : Checks if the list is empty.

isNotEmpty : Checks if the list is not empty.

length : Returns the number of elements in the list.

6. Sorting and Reversing

sort([int compare(E a, E b)]) :


Sorts the list in place according to the
provided comparison function.

:
Chapter 2 Flutter Basics 71
reversed : Returns an iterable with the elements of the list in reverse
order.

7. Sublist and Ranges

sublist(int start, [int end]) : Returns a new list containing the elements in the
specified range.

fillRange(int start, int end, [E fillValue]) :


Replaces the elements in the specified
range with the given value.

replaceRange(int start, int end, Iterable<E> newContents) :


Replaces the elements in
the specified range with the given iterable.
8. Transformation

map<T>(T f(E e)) :


Returns a new iterable with the results of applying the
function to each element.

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.

reduce(T combine(T value, E element)) :


Reduces the list to a single value by
repeatedly applying the combine function.

fold<T>(T initialValue, T combine(T previousValue, E element)) : Similar to reduce , but


allows specifying an initial value.

join([String separator = ""]) : Returns a string representation of the list, joined


by the separator.

9. Copy and Clear

toList({bool growable = true}) : Returns a new list containing the elements of the
iterable.

clear() : Removes all elements from the list.

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

// Sort and reverse


numbers.sort();
print(numbers); // Output: [3, 4, 5, 6, 7, 10, 15] print(numbers.reversed.toList());
// Output: [15, 10, 7, 6, 5, 4, 3]

// Sublist and ranges


print(numbers.sublist(1, 3)); // Output: [4, 5] numbers.fillRange(0, 2,
99);
print(numbers); // Output: [99, 99, 5, 6, 7, 10, 15]

// 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.

1. Declaring an Empty Map:

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 = {};

// Adding key-value pairs


emptyMap['name'] = 'John';
emptyMap['city'] = 'New York';

print(emptyMap); // Output: {name: John, city: New York} }

2. Declaring a Map with Initial Key-Value Pairs:

You can declare a map with some initial key-value pairs.

:
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} }

Accessing and Modifying Map Elements


You can access values in a map using their keys and modify them as needed.

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

print(capitals); // Output: {USA: Washington, D.C., Franc e: Paris, Japan: Kyoto}


}

Basic Map Methods


1. Adding and Updating Elements

:
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.

updateAll(V update(K key, V value)) :


Updates all values in the map by
applying the provided function.
2. Removing Elements

remove(Object key) : Removes the value for the specified key from the
map.

clear() : Removes all key-value pairs from the map.

3. Accessing Elements

[] (index operator): Accesses the value associated with the specified


key.

containsKey(Object key) : Checks if the map contains the specified key.

containsValue(Object value) : Checks if the map contains the specified


value.

entries : Returns an iterable of the key-value pairs in the map.

keys : Returns an iterable of the keys in the map.

values : Returns an iterable of the values in the map.

4. Querying Maps

isEmpty : Checks if the map is empty.

isNotEmpty : Checks if the map is not empty.

length : Returns the number of key-value pairs in the map.

5. Transforming Maps

map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) :


Returns a new map with the
results of applying the transform function to each key-value pair.

:
Chapter 2 Flutter Basics 76
forEach(void action(K key, V value)) : Applies the function to each key value
pair in the map.

6. Getting Default Values

putIfAbsent(K key, V ifAbsent()) :


Returns the value for the specified key, or adds
the key with a value computed by ifAbsent() and returns that value.

Example Usage
Here's an example demonstrating some of these methods:
void main() {
Map<String, int> map = {'a': 1, 'b': 2, 'c': 3};

// Adding and updating elements


map['d'] = 4; // Add new key-value pair
map.putIfAbsent('e', () => 5); // Add if key is absent map.update('a', (value) =>
value + 1); // Update existin g value
map.updateAll((key, value) => value * 2); // Update all values

// 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

var newMap = map.map((key, value) => MapEntry(key, value * 10));


print(newMap); // Output: {a: 10, b: 20, c: 30}

// Getting default values


var value = map.putIfAbsent('d', () => 4);
print(value); // Output: 4
print(map); // Output: {a: 1, b: 2, c: 3, d: 4}

// Accessing keys and values


print(map.keys); // Output: (a, b, c, d)
print(map.values); // Output: (1, 2, 3, 4)

// 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

are used to add or update key-value pairs in the map.

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.

Getting Default Values: The putIfAbsent method is used to get default


values or add new key-value pairs if the key is absent.

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:

Uses // to comment a single line.

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:

Uses /* */ to comment multiple lines.

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:

Uses /// for single lines or /** */ for multiple lines.

Provide detailed explanations, often used for public APIs and generating
documentation.
Example:

/// This function prints a greeting message


void greet() {
print('Hello, world!');
}

/**
* 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.

Multi-line Comments: For commenting out blocks of code or providing


longer explanations.

Documentation Comments: For detailed descriptions and generating


documentation, typically for functions, classes, or complex logic.

:
Chapter 2 Flutter Basics 80

You might also like