KEMBAR78
UI Design Flutter For CSE | PDF | Icon (Computing) | Computing
0% found this document useful (0 votes)
36 views54 pages

UI Design Flutter For CSE

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
36 views54 pages

UI Design Flutter For CSE

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 54

Lab Manual

Course : UI Design-Flatter Lab


Course Code : 23CS517
Year & Semester : III B.Tech I Semester
Regulation : NR23

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING

NARASIMHA REDDY ENGINEERING COLLEGE


Approved by AICTE, New Delhi, accredited by NAAC & NBA, Affiliated to JNTUH, Maisammaguda, Kompally,
Secunderabad-500100, Telangana.

1
Regulation: NR23
Narsimha Reddy Engineering College III B.Tech. I
(Autonomous) Semester
Code: 23CS517 L T P
UI Design-Flutter Lab
Credits: 1 - - 2
Course Objectives:
• Learns to Implement Flutter Widgets and Layouts
• Understands Responsive UI Design and with Navigation in Flutter
• Knowledge on Widges and customize widgets for specific UI elements, Themes
• Understand to include animation apart from fetching data
Course Outcomes: At the end of the course, students will be able to:
• Implements Flutter Widgets and Layouts
• Responsive UI Design and with Navigation in Flutter
• Create custom widgets for specific UI elements and also Apply styling using themes and custom styles.
• Design a form with various input fields, along with validation and error handling
• Fetches data and write code for unit Test for UI components and also animation

List of Experiments: Students need to implement the following experiments


1. a) Install Flutter and Dart SDK.
b) Write a simple Dart program to understand the language basics.

2. a) Explore various Flutter widgets (Text, Image, Container, etc.).


b) Implement different layout structures using Row, Column, and Stack widgets.

3. a) Design a responsive UI that adapts to different screen sizes.


b) Implement media queries and breakpoints for responsiveness.

4. a) Set up navigation between different screens using Navigator.


b) Implement navigation with named routes.

5. a) Learn about stateful and stateless widgets.


b) Implement state management using set State and Provider.

6. a) Create custom widgets for specific UI elements.


b) Apply styling using themes and custom styles.

7. a) Design a form with various input fields.


b) Implement form validation and error handling.

8. a) Add animations to UI elements using Flutter's animation framework.


b) Experiment with different types of animations (fade, slide, etc.).

9. a) Fetch data from a REST API.


b) Display the fetched data in a meaningful way in the UI.

10.
a) Write unit tests for UI components.
b) Use Flutter's debugging tools to identify and fix issues.
TEXT BOOK: Marco L. Napoli, Beginning Flutter: A Hands-on Guide to App Development.
2
Lab Session 1:

a) Install flutter and Dart sdk

To install Flutter and the Dart SDK, you can follow these steps:
a) Download Flutter: Visit the Flutter website's Get Started page and download the Flutter SDK
b) for your operating system (Windows, macOS, or Linux).

c) Extract the Flutter SDK: After downloading, extract the contents of the compressed file

to a location on your computer where you want to store the Flutter SDK. For example, you

can extract it to C:\flutter on Windows, /Users/<your-username>/flutter on macOS, or ~/flutter


on Linux.

d) Add Flutter to your PATH: Update your system's PATH variable to include the Flutter bin directory.
This step allows you to execute Flutter commands from any directory in your terminal or command
prompt. The precise steps for updating the PATH vary depending on your operating system.

Windows:
From the Start search bar, type 'env' and select 'Edit the system environment variables'.Click on
'Environment Variables'.
Under 'System Variables', find the 'Path' variable, select it, and click 'Edit'.
Click 'New' and add the path to the bin directory inside the Flutter directory (e.g., C:\flutter\bin). Click
'OK' on all open dialogs to save your changes.

macOS and Linux:


Open a terminal window.
Run the following command to open the profile file associated with your terminal (.bash_profile, .
bashrc, .zshrc, or similar):
nano ~/.bash_profile
Add the following line at the end of the file:
export PATH="$PATH:/path/to/flutter/bin"
Press Ctrl + X to exit, then Y to save changes, and Enter to confirm.
e) Verify the Flutter installation: Open a new terminal window, and run the following command
f) to verify that Flutter is properly installed:
flutter --version
This command should display the Flutter version and other relevant information if the installation was
successful.

g) Install Flutter dependencies: Depending on your development environment, you may need to install
additional dependencies, such as Android Studio to fully set up your Flutter development environment.

h) Download Dart SDK (if not bundled with Flutter): Flutter comes with the Dart SDK bundled, so if
you've installed Flutter, you should have the Dart SDK as well. However, if you need to install Dart
separately, you can download it from the Dart "SDK archive".

b) Write a simple dart program to understand the language basics


// Define a main function, which is the entry point of a Dart program. void main() {
// Variables and data types int myNumber = 10; double myDouble = 3.14;
String myString = 'Hello World'; bool myBool = true;

3
// Printing variables
print('My number is: $myNumber');

print('My double is: $myDouble'); print('My string is: $myString'); print('My boolean is: $myBool');

// Basic arithmetic operationsint result = myNumber + 5; print('Result of addition: $result');

// Conditional statementsif (myBool) { print('myBool is true');


} else {
print('myBool is false');
}

// Loops
for (int i = 0; i < 5; i++) { print('Iteration $i');
}

// Lists
List<int> numbers = [1, 2, 3, 4, 5];
print('First element of the list: ${numbers[0]}'); print('Length of the list: ${numbers.length}');

// Maps
Map<String, int> ages = { 'Kiran': 30,
'Raj': 25,
'Alekya': 35,
};
print('Kiran\'s age: ${ages['Kiran']}');
}

Output:

4
Lab Session 2:

a) Explore various flutter widgets

Flutter provides a rich set of widgets to build user interfaces for mobile,web,and desktop
applications.These widgets help in creating visually appealing and interactive UIs. Here are some
of the commonly used Flutter widgets categorized by their functionalities:

Layout Widgets:
Container: A versatile widget that can contain other widgets and provides options for alignment,
padding,margin, and decoration.

Row and Column: Widgets that arrange their children in a horizontal or vertical line respectively.

Stack: Allows widgets to be stacked on top of each other, enabling complex layouts.

ListView and GridView: Widgets for displaying a scrollable list or grid of children, with support for
various layouts and scrolling directions.

Scaffold: Implements the basic material design layout structure, providing app bars, drawers, and
floatingaction buttons.

Text and Styling Widgets:


Text: Displays a string of text with options for styling such as font size, color, and alignment.

RichText: Allows for more complex text styling and formatting, including different styles within the
same text span.

TextStyle: A class for defining text styles that can be applied to Text widgets.

Input Widgets:
TextField: A widget for accepting user input as text, with options for customization and validation.

Checkbox and Radio: Widgets for selecting from a list of options, either through checkboxes or radio
buttons.

DropdownButton: Provides a dropdown menu for selecting from a list of options.

Button Widgets:
ElevatedButton and TextButton: Widgets for displaying buttons with different styles and
customizationoptions.

IconButton: A button widget that displays an icon and responds to user taps.

GestureDetector: A versatile widget that detects gestures such as taps, swipes, and drags, allowing for
custom interactions.

Image and Icon Widgets:


Image: Widget for displaying images from various sources, including assets, network URLs, and
memory.

5
Icon: Displays a Material Design icon.
Navigation Widgets:
Navigator: Manages a stack of route objects and transitions between different screens or pages in the
app.

PageRouteBuilder: A customizable widget for building page transitions and animations.

Animation Widgets:
AnimatedContainer: An animated version of the Container widget, with support for transitioning
properties over a specified duration.

AnimatedOpacity, AnimatedPositioned, AnimatedBuilder: Widgets for animating opacity,


position,and custom properties respectively.

Material Design Widgets:


AppBar: A material design app bar that typically contains a title, leading and trailing widgets, and
actions.

BottomNavigationBar: Provides a navigation bar at the bottom of the screen for switching betwee
different screens or tabs.

Card: Displays content organized in a card-like structure with optional elevation and padding.

Cupertino (iOS-style) Widgets:


CupertinoNavigationBar: A navigation bar in the iOS style. CupertinoButton: A button widget with the

iOS style.

CupertinoTextField: A text field widget with the iOS style.

These are just a few examples of the many widgets available in Flutter. Each widget comes with its

set of properties and customization options, allowing developers to create highly customizable and
responsive user interfaces.

b) User implement different layout structures using Row,Column,and Stack widgets

1. Row Layout: void main() { runApp(MyApp());


}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) { return MaterialApp(
home: Scaffold( appBar:
AppBar(
title: Text('Row Layout'),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,children:
<Widget>[ Container(
color: Colors.red,

6
width: 100,
height: 100,
),
Container(
color: Colors.green,

width: 100,
height: 100,
),

Container(
color: Colors.blue,width: 100,
height: 100,
),
],
),
),
);
}
}

Output:

2. Column Layout:

import 'package:flutter/material.dart'; void main() {


runApp(MyApp());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) { return MaterialApp(
home: Scaffold( appBar:
AppBar(
title: Text('Column Layout'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,children:
<Widget>[ Container(

color: Colors.red,width: 100,


height: 100,
),
7
Container(
color: Colors.green,width: 100,
height: 100,
),
Container(
color: Colors.blue,width: 100,
height: 100,
),
],
),
),
);
}
}

Output:

3. Stack Layout:
import 'package:flutter/material.dart'; void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) { return MaterialApp(
home: Scaffold( appBar:
AppBar(
title: Text('Stack Layout'),

),
body: Stack(
alignment: Alignment.center,children:
<Widget>[

Container(
color: Colors.red,width: 200,
height: 200,
8
),

Container(
color: Colors.green,width: 150,
height: 150,
),
Container(
color: Colors.blue,width: 100,
height: 100,
),

],
),
),
);
}
}

Output:

9
Lab Session 3:

a) Design a responsive UI that adapts to different screen sizes

import 'package:flutter/material.dart'; void main() {


runApp(MyApp());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) { return MaterialApp(
title: 'Responsive UI Demo', theme: ThemeData( primarySwatch: Colors.blue,
),
home: ResponsiveHomePage(),
);
}
}
class ResponsiveHomePage extends StatelessWidget { @override
Widget build(BuildContext context) { return Scaffold(
appBar: AppBar(
title: Text('Responsive UI Demo'),
),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {if (constraints.maxWidth < 600) {
return _buildNarrowLayout();
} else {
return _buildWideLayout();
}
},
),
);
}

Widget _buildNarrowLayout() { return Center(


child: Column(
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
FlutterLogo(size: 100), SizedBox(height: 20),Text( 'Narrow Layout',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20), ElevatedButton( onPressed: ()
{}, child: Text('Button'),
),
],
),
);
}

Widget _buildWideLayout() { return Center(


child: Row(
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
FlutterLogo(size: 100), SizedBox(width: 20),Column(
mainAxisAlignment: MainAxisAlignment.center,children:
10
<Widget>[ Text(
'Wide Layout',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20), ElevatedButton( onPressed: ()
{}, child: Text('Button'),
),
],
),
],
),
);
}
}

Output:

Mobile View:

Desktop View:

11
b) Implement media queries and breakpoints for responsiveness

import 'package:flutter/material.dart'; void main() {


runApp(MyApp());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) { return MaterialApp(
title: 'Responsive UI with Media Queries', theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ResponsiveHomePage(),
);
}
}

class ResponsiveHomePage extends StatelessWidget { @override


Widget build(BuildContext context) { return Scaffold(
appBar: AppBar(
title: Text('Responsive UI with Media Queries'),
),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {if (constraints.maxWidth < 600) {
return _buildMobileLayout();
} else if (constraints.maxWidth < 1200) {return
_buildTabletLayout();
} else {
return _buildDesktopLayout();
}
},
),
);
}

Widget _buildMobileLayout() { return Center(


child: Column(
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
FlutterLogo(size: 100), SizedBox(height: 20),Text( 'Mobile Layout',
style: TextStyle(fontSize: 24),
),

12
SizedBox(height: 20), ElevatedButton( onPressed: ()
{}, child: Text('Button'),
),
],
),
);
}

Widget _buildTabletLayout() { return Center(


child: Row(
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
FlutterLogo(size: 100), SizedBox(width: 20),Column(
mainAxisAlignment: MainAxisAlignment.center,children:
<Widget>[ Text(
'Tablet Layout',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20), ElevatedButton( onPressed: ()
{}, child: Text('Button'),
),
],
),
],
),
);
}

Widget _buildDesktopLayout() { return Center(


child: Row(
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
FlutterLogo(size: 100), SizedBox(width: 20),Column(
mainAxisAlignment: MainAxisAlignment.center,children:
<Widget>[ Text(
'Desktop Layout',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20), ElevatedButton( onPressed: ()
{},
child: Text('Button'),

13
),

],
),
],
),
);
}
}

Output:

14
Lab Session 4:

a) Setup navigation between different screens using navigator

import 'package:flutter/material.dart'; void main() {


runApp(MyApp());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) { return MaterialApp(
title: 'Navigation Example', theme: ThemeData( primarySwatch:
Colors.blue,
),
home: FirstScreen(),
);
}
}

class FirstScreen extends StatelessWidget { @override


Widget build(BuildContext context) { return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: ElevatedButton( onPressed: () {
// Navigate to the second screen Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
},
child: Text('Go to Second Screen'),
),
),
);
}
}

class SecondScreen extends StatelessWidget { @override


Widget build(BuildContext context) { return Scaffold(
appBar: AppBar(
title: Text('Second Screen'),
),
body: Center(
child: ElevatedButton( onPressed: () {
// Navigate back to the first screen Navigator.pop(context);
},
child: Text('Go back to First Screen'),
),
),
);
}
15
}

Output:

b) Implement navigation with named routes

import 'package:flutter/material.dart'; void main() {


runApp(MyApp());
}

class MyApp extends StatelessWidget { @override

Widget build(BuildContext context) { return MaterialApp(


title: 'Named Routes Demo', initialRoute: '/',
routes: {
'/': (context) => HomeScreen(), '/second': (context) => SecondScreen(),'/third': (context)
16
=> ThirdScreen(),
},
);
}
}

class HomeScreen extends StatelessWidget { @override


Widget build(BuildContext context) { return Scaffold(
appBar: AppBar(
title: Text('Home Screen'),
),
body: Center(
child: ElevatedButton( onPressed: () {

Navigator.pushNamed(context, '/second');
},
child: Text('Go to Second Screen'),
),
),
);
}
}
class SecondScreen extends StatelessWidget { @override
Widget build(BuildContext context) { return Scaffold(
appBar: AppBar(
title: Text('Second Screen'),
),
body: Center(
child: ElevatedButton( onPressed: () {

Navigator.pushNamed(context, '/third');
},
child: Text('Go to Third Screen'),
),
),
);
}
}

class ThirdScreen extends StatelessWidget { @override


Widget build(BuildContext context) {
return Scaffold(

appBar: AppBar(
title: Text('Third Screen'),
),
body: Center(
child: ElevatedButton( onPressed: () {
Navigator.popUntil(context, ModalRoute.withName('/'));
},
child: Text('Go Back to Home'),
),
17
),
);
}
}

Output:

18
Lab Session 5:

a) Learn about stateful and stateless widgets


In Flutter, widgets can be categorized into two main types based on their behavior regarding
statemanagement: stateful widgets and stateless widgets.

Stateless Widgets:
Definition: Stateless widgets are widgets that do not have any mutable state. Once created, their
properties (configuration) cannot change.

Characteristics:
They are immutable and lightweight.
They only depend on their configuration and the build context provided during construction.Their
appearance (UI) is purely a function of their configuration.
They are ideal for UI elements that do not change over time, such as static text labels, icons, or simple
buttons.
import 'package:flutter/material.dart';

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


}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) { return MaterialApp(
home: Scaffold( appBar:
AppBar(
title: Text('Cards Example'),
),
body: CardList(),
),
);

}
}

class CardList extends StatelessWidget { @override


Widget build(BuildContext context) { return ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {return CardItem(
title: 'Card $index', subtitle: 'Subtitle $index',
);
},
);
}
}

class CardItem extends StatelessWidget { final String title;


final String subtitle;

const CardItem({ Key key, @required this.title, @required this.subtitle,


19
}) : super(key: key);

@override
Widget build(BuildContext context) { return Card(
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),child:
ListTile(
title: Text(title), subtitle:
Text(subtitle),leading:
CircleAvatar(
child: Text('${title.substring(0, 1)}'),
),
onTap: () {
// Handle card tap
},
),
);
}

Output:

b) Implement state management using set state and provider


Stateful Widgets:

Definition: Stateful widgets are widgets that maintain state, allowing them to change and update over
time in response to user actions, network events, or other factors.

Characteristics:
They have an associated mutable state that can change during the widget's lifetime.
The state is stored in a separate class that extends State and is associated with the stateful widget.Changes
to the state trigger a rebuild of the widget's UI, allowing dynamic updates.
They are ideal for UI elements that need to change or react to user interactions, such as input forms,
20
animations, or scrollable lists.
import 'package:flutter/material.dart';

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


}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) { return MaterialApp(
home: CounterApp(),
);
}
}

class CounterApp extends StatefulWidget { @override


_CounterAppState createState() => _CounterAppState();
}
class _CounterAppState extends State<CounterApp> {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( 'Counter:',
style: TextStyle(fontSize: 24),
),
Text( '$_counter',
style: TextStyle(fontSize: 36, fontWeight: FontWeight.bold),
),
],
),
),
floatingActionButton: FloatingActionButton( onPressed: _incrementCounter,
tooltip: 'Increment', child: Icon(Icons.add),
),
);
}
}
Output:

21
Stateful widgets are composed of two classes: the stateful widget itself (which extends StatefulWidget)
and its corresponding state class (which extends State). The state class is responsible for maintaining the
widget's mutable state and updating the UI accordingly via the setState() method.

stateless widgets are static and immutable, while stateful widgets are dynamic and can change over time
by managing their internal state. Understanding the difference between these two types of widgets is
essential for designing and building efficient and responsive Flutter UIs.

State Management using setState():


import 'package:flutter/material.dart';

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


}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) { return MaterialApp(
home: CounterPage(),
);
}
}

class CounterPage extends StatefulWidget { @override


_CounterPageState createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> { int _counter = 0;

void _incrementCounter() { setState(() {


_counter++;
});
}

@override
Widget build(BuildContext context) { return Scaffold(
appBar: AppBar(
title: Text('Counter Example (setState)'),
),
body: Center( child:
22
Column(
mainAxisAlignment: MainAxisAlignment.center,children:
<Widget>[ Text(
'Counter Value:',
),
Text( '$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton( onPressed: _incrementCounter,
tooltip: 'Increment', child: Icon(Icons.add),
),
);
}
}

Output:

23
lOMoAR cPSD| 37701387

State Management using provider package:


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

import 'provider/movie_provider.dart'; import 'screens/home_screen.dart'; void

main() { runApp(ChangeNotifierProvider<MovieProvider>(child:
const MyApp(),
create: (_) => MovieProvider(), // Create a new ChangeNotifier object
));
}

class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {

return MaterialApp(
// Remove the debug banner debugShowCheckedModeBanner: false,title:
'State Management using provider',theme:
ThemeData(
primarySwatch: Colors.indigo,
),

home: const HomeScreen(),


);
}
}

create a model folder for models and create file movie.dart class Movie {
final String title;
final String? runtime; // how long this movie is (in minute)

Movie({required this.title, this.runtime});


}

Create a provider folder and create movie_provider.dart inside the provider folder
// provider/movie_provider.dart import 'package:flutter/material.dart';import 'dart:math';
import '../models/movie.dart';

// A list of movies
final List<Movie> initialData = List.generate( 50,
(index) => Movie( title: "Moview $index",
runtime: "${Random().nextInt(100) + 60} minutes"));

class MovieProvider with ChangeNotifier {


// All movies (that will be displayed on the Home screen) final List<Movie> _movies =
24
lOMoAR cPSD| 37701387

initialData;

// Retrieve all movies


List<Movie> get movies => _movies;

// Favorite movies (that will be shown on the MyList screen) final List<Movie> _myList = [];

// Retrieve favorite movies List<Movie> get myList => _myList;

// Adding a movie to the favorites list void addToList(Movie

movie) {
_myList.add(movie); notifyListeners();
}

// Removing a movie from the favorites list void removeFromList(Movie movie) {


_myList.remove(movie); notifyListeners();
}
}

Create a screens folder for screens


Create home_screen.dart for home screen page

// screens/home_screen.dart
import 'package:flutter/material.dart'; import 'package:provider/provider.dart';

import '../provider/movie_provider.dart'; import 'my_list_screen.dart';

class HomeScreen extends StatefulWidget {


const HomeScreen({Key? key}) : super(key: key);

@override
State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> { @override


Widget build(BuildContext context) {

var movies = context.watch<MovieProvider>().movies;var myList =


context.watch<MovieProvider>().myList;

return Scaffold( appBar: AppBar(


title: const Text('State Management using provider'),
),
body: Padding(
padding: const EdgeInsets.all(15),child:
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,children: [
ElevatedButton.icon( onPressed: () { Navigator.of(context).push( MaterialPageRoute(
25
lOMoAR cPSD| 37701387

builder: (context) => const MyListScreen(),


),
);
},
icon: const Icon(Icons.favorite),label:
Text(
"Go to my list (${myList.length})",style: const TextStyle(fontSize: 24),
),

style: ElevatedButton.styleFrom(primary: Colors.red,

padding: const EdgeInsets.symmetric(vertical: 20)),


),
const SizedBox(height:
15,
),
Expanded(
child: ListView.builder( itemCount: movies.length,itemBuilder: (_, index) {

final currentMovie = movies[index];return Card( key: ValueKey(currentMovie.title), color:


Colors.amberAccent.shade100,elevation: 4, child: ListTile(
title: Text(currentMovie.title),subtitle: Text(currentMovie.runtime ?? 'No information'),trailing:
IconButton(
icon: Icon( Icons.favorite,
color: myList.contains(currentMovie)
? Colors.red
: Colors.white,

size: 30,
),
onPressed: () {
if (!myList.contains(currentMovie)) {context
.read<MovieProvider>()
.addToList(currentMovie);
} else { context
.read<MovieProvider>()
.removeFromList(currentMovie);
}
},
),
),
);
}),
),
],
),
),
);
}
}
26
lOMoAR cPSD| 37701387

create my_list_screen.dart inside the screens folder

// screens/my_list_screen.dart
import 'package:flutter/material.dart'; import 'package:provider/provider.dart';

import '../provider/movie_provider.dart'; class MyListScreen extends StatefulWidget {


const MyListScreen({Key? key}) : super(key: key);

@override
State<MyListScreen> createState() => _MyListScreenState();
}

class _MyListScreenState extends State<MyListScreen> { @override


Widget build(BuildContext context) {
final myList = context.watch<MovieProvider>().myList; return Scaffold(
appBar: AppBar(
title: Text("My List (${myList.length})"),
),
body: ListView.builder( itemCount: myList.length, itemBuilder: (_, index) {
final currentMovie = myList[index];

return Card(
key: ValueKey(currentMovie.title),elevation:
4,

child: ListTile(
title: Text(currentMovie.title),
subtitle: Text(currentMovie.runtime ?? ''),trailing:
TextButton(
child: const Text('Remove',
style: TextStyle(color: Colors.red),
),
onPressed: () { context.read<MovieProvider>().removeFromList(currentMovie);
},
),
),
);
}),
);
}
}

Output:

27
lOMoAR cPSD| 37701387

we use the provider package to manage state. We define a Counter class that extends
ChangeNotifier, and the counter value is stored inside it. Whenever the counter is incremented,
we call notifyListeners() to informthe listeners about the change.

28
lOMoAR cPSD| 37701387

Lab Session 6:

a) Create custom widgets for specific UI elements


import

'package:flutter/material.d art';void main() {


runApp(MyApp());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) {return MaterialApp( home:
Scaffold( appBar:

AppBar(
title: Text('Custom Widget Example'),
),
body: Column( mainAxisAlignment:
MainAxisAlignment.center,children:
<Widget>[ Padding( padding: const
EdgeInsets.all(8.0),child: CustomTextField( hintText: 'Enter your name', onChanged: (value) {
print('Name changed:
$value');
},
),
),
SizedBox(height
: 20),Padding( padding: const
EdgeInsets.all(8.0),child: CustomTextField( hintText: 'Enter Email', onChanged: (value) {
print('Name changed:
$value');
},
),
),
SizedBox(height
: 20),Padding( padding: const
EdgeInsets.all(8.0),child: CustomTextField( hintText: 'Enter Roll Number', onChanged: (value) {
print('Name changed: $value');
},
),
),
SizedBox(height
: 20),
CustomButton( text: 'Press Me', onPressed: () {

print('Button pressed!');
},
),
],
29
lOMoAR cPSD| 37701387

),
),
);
}
}

class CustomButton extends StatelessWidget {final String? text;


final VoidCallback? onPressed;

const CustomBu tton({ Key? key, @required this.text,


@required this.onPressed,
}) : super(key: key); @override
Widget build(BuildContext context) {
return ElevatedButton( onPressed:
onPressed, child:
Text(text!),
);
}
}

class CustomTextField extends StatelessWidget {final String hintText;


final ValueChanged<String> onChanged;

const CustomTextF ield({Key? key,


required this.hintText, required this.onChange d,
}) : super(key: key);

@override Widget
build(BuildContext context) {return TextField( onChanged: onChanged, decoration:
InputDecoration( hintText: hintText,
border: OutlineInputBorder(),
),
);
}
}

Output:

30
lOMoAR cPSD| 37701387

b) Apply styling using themes and custom styles

In Flutter, you can apply styling to your widgets using themes and custom styles to maintain
consistency and make your UI morevisually appealing.

Import 'package:flutter/material.dart'; void


main()
{
runApp (MyAp p());
}

class MyApp extends @override StatelessWidget {


{
Widget build(BuildContext context) return
MaterialA pp( theme:
ThemeDat a(
// Define the overall theme of the appprimaryColor:
Colors.blue, accentColor: Colors.orange, fontFamily:
'Roboto',
textTheme: TextTheme(
headline1: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),bodyText1:
TextStyle(fontSize: 16),
),
elevatedButtonTheme: ElevatedButtonThemeData(style: ElevatedButton.styleFrom( primary:
Colors.blue,
textStyle: TextStyle(fontSize: 18),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),

),
),
),
home: HomePage(),
);
}
}

class HomePage extends StatelessWidget {@override


Widget build(BuildContext context) {

return Scaffol d( appBar:


AppBar (
title: Text('Styling Example'),
),
body: Center ( child: Colum n(
mainAxisAlignment: MainAxisAlignment.center,children:
<Widget>[ Text(
'Welcome to MyApp',
31
lOMoAR cPSD| 37701387

style: Theme.of(context).textTheme.headline1,
),
SizedBox(height
: 20),
ElevatedButton( onPressed: () {},
child: Text('Get Started'),
),
],
),
),
);
}
}

Output:

In this example:
We define a custom theme using ThemeData and apply it to the entire app using the theme
property ofMaterialApp.

The theme specifies primary and accent colors, a custom font family, and text styles for different
textelements (headline6 and bodyText2).

We customize the appearance of the elevated buttons using ElevatedButtonThemeData


andElevatedButton.styleFrom.

In the HomePage widget, we use Theme.of(context) to access the custom theme properties and
applythem to various widgets such as Text and ElevatedButton.
We also demonstrate custom styling for a Container widget with a custom background
color and borderradius.
Using themes and custom styles like this helps maintain a consistent visual identity throughout
your app and makes it easier to manage and update styling across multiple widgets.

32
lOMoAR cPSD| 37701387

Lab Session 7:

a) Design a form with various input fields

form with various input fields such as text fields, checkboxes, radio buttons, and a dropdown
menuimport 'package:flutter/material.dart';

void main()
{
runApp (MyAp p());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) {return MaterialApp(
title: 'Form Example',
theme: ThemeData( primarySwatch:
Colors.blue,
),
home: FormPage(),
);
}
}

class FormPage extends StatefulWidget {@override


_FormPageState createState() => _FormPageState();
}

class _FormPageState extends State<FormPage> {final _formKey = GlobalKey<FormState>();

St ri ng
_n a m e; St ri ng
_e m ail
;

bool
_subscribeToNewsletter
= false;String
_selectedCountry = 'USA'; @override Widget
build(BuildContext context) {return Scaffold( appBar: AppBar(
title: Text('Form Example'),
),
body: Padding( padding: EdgeInsets.all(20.0), child: Form(
key:
_formKe y,child:
Column( crossAxisAlignment:
CrossAxisAlignment.start,children:
<Widget>[ TextFormField(

decoration: InputDecoration(labelText: 'Name'),onSaved: (value) {


33
lOMoAR cPSD| 37701387

_name = value;
},
),
SizedBox(height:
20),
TextFormField(
decoration: InputDecoration(labelText: 'Email'),onSaved: (value) {
_email = value;
},
),
SizedBox(height:
20),Row(
children: <Widget>[ Checkbox(
value:
_subscribeToNewsletter, onChanged: (value) { setState(() {
_subscribeToNewsletter = value;
});
},
),
Text('Subscribe to Newsletter'),
],
),
SizedBox(height:
20),Row(
children: <Widget>[ Text('Country: '), SizedBox(width: 20), DropdownButton<String>( value:
_selectedCountry, onChanged: (value) { setState(() {
_selectedCountry = value;
}); },

items: <String>['USA', 'Canada', 'UK', 'Australia']


.map<DropdownMenuItem<String>>((String value) { return DropdownMenuItem<String>(
value: value, child:
Text(value),
);
}).toList(),
),
],

),
SizedBox(height:
20),
ElevatedButton( onPressed: () {
_formKey.currentState.save();
// Submit the form data print('Name:
$_name'); print('Email:
$_email');
print('Subscribe to Newsletter: $_subscribeToNewsletter'); print('Country: $_selectedCountry');
},
child: Text('Submit'),
),
34
lOMoAR cPSD| 37701387

],
),
),
),
);
}
}

Output:

b) Implement form validation and error handling


import 'package:flutter/material

.dart';void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) {return MaterialApp( home:
Scaffold( appBar:
AppBar(
title: Text('Form Example'),
),

body:
SingleChildScrollVie w(padding:
EdgeInsets.all(16), child: FormWidget(),
),
),
);
}
35
lOMoAR cPSD| 37701387

class FormWidget extends StatefulWidget {@override


_FormWidgetState createState() => _FormWidgetState();

class _FormWidgetState extends State<FormWidgt> { final _formKey =


GlobalKey<FormState>();

String_name;
String_emai l; String_pass word; String_phon e; String_addr ess;

@override Widget
build(BuildContext context) {return Form( key:
_form Key, child:
Colum n(
crossAxisAlignment: CrossAxisAlignment.start,children:
<Widget>[ TextFormField(
decoration: InputDecoration(labelText: 'Name'),validator: (value) {
if (value.isEmpty) {
return 'Please enter your name';
}
return null;
},
onSaved: (value) => _name = value,
),
SizedBox(heig ht: 16),
TextFormField (
decoration: InputDecoration(labelText: 'Email'),keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value.isEmpty) {
return 'Please enter your email';
}
// Add more complex email validation logic if neededreturn null;
},

onSaved: (value) => _email = value,


),
SizedBox(heig ht: 16),
TextFormField (
decoration: InputDecoration(labelText: 'Password'),obscureText: true, validator: (value) {
if (value.isEmpty) {

return 'Please enter a password';


}
// Add more complex password validation logic if neededreturn null;
},
onSaved: (value) => _password = value,
36
lOMoAR cPSD| 37701387

),
SizedBox(heig ht: 16),
TextFormField (
decoration: InputDecoration(labelText: 'Phone'),keyboardType: TextInputType.phone,
validator: (value) { if (value.isEmpty) {
return 'Please enter your phone number';
}
// Add more complex phone number validation logic if neededreturn null;
},
onSaved: (value) => _phone = value,
),
SizedBox(heig ht: 16),
TextFormField (
decoration: InputDecoration(labelText:
'Address'),maxLines: 3, validator: (value) {
if (value.isEmpty) {
return 'Please enter your address';
}
return null;
},
onSaved: (value) => _address = value,
),
SizedBox(height:
16),
ElevatedButton( onPressed:
_submitForm, child:
Text('Submit'),
),
],
),
);
}

void _submitForm() {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();

// Perform form submission with the saved form dataprint('Form submitted:'); print('Name:
$_name');

print('Email:
$_email'); print('Password:
$_password'); print('Phone:
$_phone'); print('Address:
$_address');
}
}
}

37
lOMoAR cPSD| 37701387

Output:

38
lOMoAR cPSD| 37701387

Lab Session 8:

a) Add animations to UI elements using flutter's animation framework

import 'package:flutter/material.d art';void main() {


runApp(MyApp());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) {return MaterialApp( home:
Scaffold( appBar:
AppBar(
title: Text('Animation Example'),
),
body: AnimationWidget(),
),
);
}
}

class AnimationWidget extends StatefulWidget {@override


_AnimationWidgetState createState() => _AnimationWidgetState();
}

class _AnimationWidgetState extends State<AnimationWidget>with


SingleTickerProviderStateMixin { AnimationController
_controller;
Animation<double>
_animation;

@override void
initSt ate() { super. initSt ate();
_controller = AnimationController( duration:
Duration(seconds: 1), vsync: this,
);
_animation = Tween<double>(begin: 0, end: 300).animate(_controller)
..addListener(() {
setState(() {}); // Trigger rebuild when animation value changes
});
}

@override Widget
build(BuildContext

39
lOMoAR cPSD| 37701387

context) {return Center( child: Column(


mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Container( width:
_animation.value, height:
_animation.value, color: Colors.blue,
child: FlutterLogo(size: 100),
),
SizedBox(heig ht: 20),
ElevatedButton ( onPressed: ()
{
if (_controller.status == AnimationStatus.completed) {
_controller.reverse();
} else {
_controller.forward();
}
},
child: Text(
_controller.status == AnimationStatus.completed
? 'Reverse Animation'
: 'Start Animation',
),
),
],
),
);
}

@override
void dispose() {
_controller
.dispose(); super.disp ose();
}
}
Output:

40
lOMoAR cPSD| 37701387

We define an Animation object with Tween to define the range of values for the animation.I
nside the initState() method, we initialize the animation controller and define the animation.We
use addListener() to trigger a rebuild when the animation value changes.

In the build method, we use the animated value _animation.value to control the size of the
Container, whichcontains the FlutterLogo.

The ElevatedButton toggles the animation between forward and reverse based on the status of the
animationcontroller.
You can customize the animation further by adjusting the duration, adding curves, or chaining
multipleanimations together.

b) Experiment with different types of animations like fade,slide,etc.


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

void main()
{
runApp (MyAp p());
}
class MyApp extends StatelessWidget { @override
Widget build(BuildContext context) {return MaterialApp( home:
Scaffold( appBar:
AppBar(
title: Text('Fade Animation Example'),
),
body: FadeAnimation(),
),
);
}
}
class FadeAnimation extends StatefulWidget {
@override
_FadeAnimationState createState() => _FadeAnimationState();
}

class _FadeAnimationState extends State<FadeAnimation>with SingleTickerProviderStateMixin


{ AnimationController _controller; Animation<double> _animation;

@override void
initSt ate() { super. initSt ate();
_controller = AnimationController( vsync: this,
duration: Duration(seconds: 2),
);
_animation = Tween<double>( begin: 0.0,

41
lOMoAR cPSD| 37701387

end: 1.0,
).animate(_controller);

_controller.forward();
}

@override Widget
build(BuildContext context) {return Center( child:
FadeTransiti on(opacity:
_animation, child:
Container( width: 200,
height: 200,
color: Colors.blue,
),
),
);
}

@override
void dispose() {
_controller
.dispose(); super.disp ose();
}
}

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

void main()
{
runApp (MyAp p());
}

class MyApp extends


StatelessWidget { @override Widget
build(BuildContext context) {return MaterialApp( home:
Scaffold( appBar:
AppBar(
title: Text('Slide Animation Example'),
),
body: SlideAnimation(),
),
);
}
}

class SlideAnimation extends StatefulWidget {@override


_SlideAnimationState createState() => _SlideAnimationState();
}
42
lOMoAR cPSD| 37701387

class _SlideAnimationState extends State<SlideAnimation>with SingleTickerProviderStateMixin


{ AnimationController _controller; Animation<Offset>
_animation;@override void
initSt ate() { super. initSt ate();
_controller = AnimationController( vsync: this,
duration: Duration(seconds: 2),
);
_animation = Tween<Offset>( begin: Offset(-1.0, 0.0),
end: Offset(0.0, 0.0),
).animate(_controller);
_controller.forward();}

@override Widget
build(BuildContext context) {return Center( child:
SlideTransiti on(position:
_animation, child:
Container( width: 200,
height: 200,
color: Colors.blue,
),
),
);
}

@override
void dispose() {
_controller
.dispose(); super.disp ose();
}
}

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

void main()
{
runApp (MyAp p());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) {return

43
lOMoAR cPSD| 37701387

MaterialApp( home:
Scaffold( appBar:
AppBar(
title: Text('Scale Animation Example'),
),
body: ScaleAnimation(),
),
);

}
}

class ScaleAnimation extends StatefulWidget {@override


_ScaleAnimationState createState() => _ScaleAnimationState();
}

class _ScaleAnimationState extends State<ScaleAnimation>with


SingleTickerProviderStateMixin { AnimationController _controller; Animation<double>
_animation;

@override void
initSt ate() { super. initSt ate();
_controller = AnimationController( vsync: this,
duration: Duration(seconds: 2),
);
_animation = Tween<double>( begin: 0.0,
end: 1.0,
).animate(_controller);
_controller.forward();
}

@override Widget build(BuildContext context) {return Center( child:


ScaleTransiti on(scale:
_animation, child: Container( width: 200,
height: 200,
color: Colors.blue,
),
),
);
}
@override
void dispose() {
_controller
.dispose(); super.disp ose();
}
}

44
lOMoAR cPSD| 37701387

Output:

45
lOMoAR cPSD| 37701387

Lab Session 9:

a) Fetch data from REST API


add dependancy in pubspec.yaml:
dependencies:
flutter:
sdk: flutterhttp:
^0.13.3
enable internet permissions in your AndroidManifest.xml file for Android apps like below.
<uses-permission android:name="android.permission.INTERNET"

import 'dart:convert'; import 'package:flutter/material. dart'; import 'package:http/http.dart' as http;

void main()
{
runApp (MyAp p());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) {return MaterialApp( home: HomePage(),
);
}
}

class HomePage extends StatefulWidget {@override

_HomePageState createState() => _HomePageState();


}
class _HomePageState extends State<HomePage> {List<dynamic>
_data = [];
@override void
initSt ate() { super. initSt ate();
_fetchDataFromApi();
}

Future<void> _fetchDataFromApi() async {


final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));

if (response.statusCode
== 200) {setState(() {
_data = json.decode(response.body);
});
} else {
throw Exception('Failed to load data');
}
}
@override Widget
build(BuildContext context) {return Scaffold( appBar: AppBar(

46
lOMoAR cPSD| 37701387

title: Text('API Data Example'),


),
body: ListView.builder( itemCount:
_data.length, itemBuilder: (context, index) {return ListTile(
title: Text(_data[index]['title']), subtitle: Text(_data[index]['body']),
);
},
),
);
}
Output:

b) Display the fetched data in a meaningful way in the UI


display the fetched data in a meaningful way in the UI, we can use a more structured layout
rather than justdisplaying the data in a list. We'll create a custom widget to represent each post
fetched from the API, and display them in a scrollable list.
import 'dart:convert'; import 'package:flutter/material. dart'; import 'package:http/http.dart' as http;

void main()
{
runAp p(My App()
);
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) {return MaterialApp( home: HomePage(),
);

47
lOMoAR cPSD| 37701387

}
}

class HomePage extends StatefulWidget {@override


_HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {List<dynamic>


_data = [];
bool _isLoading = false;

@override void
initSt ate() { super. initSt ate();
_fetchDataFromApi();
}

Future<void>
_fetchDataFromApi() async { setState(() {
_isLoading = true;
});

final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));if

(response.statusCode == 200) {
setState(() {
_data = json.decode(response.body);
_isLoading = false;
});
} else {
throw Exception('Failed to load data');

}
}

@override
Widget build(BuildContext context) {return Scaffold( appBar: AppBar(
title: Text('API Data Example'),
),
body: _isLoading
? Center(
child: CircularProgressIndicator(),
)
: ListView.builder( itemCount:
_data.length, itemBuilder: (context, index) {return PostCard( title: _data[index]['title'], body:
_data[index]['body'],
);
},
),

48
lOMoAR cPSD| 37701387

);
}
}

class PostCard extends StatelessWidget {final String title;


final String body;

const PostCard ({ Key key, @require d this.title,


@required this.body,
}) : super(key: key);

@override Widget
build(BuildContext context) {return Card(
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),child: Padding(

padding:

EdgeInsets.all(16),

child: Column( crossAxisAlignment:


CrossAxisAlignment.start,children:
<Widget>[ Text(title,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(heig ht: 8),Text( body,
style: TextStyle(fontSize: 16),
),
],

),
),
);
}
}

Output:

49
lOMoAR cPSD| 37701387

We've added a loading indicator (CircularProgressIndicator) to indicate when data is being


fetched.The fetched data is displayed as a list of PostCard widgets, each representing a post from
the API. The PostCard widget displays the title and body of each post in a structured
manner using a Card layout.

50
lOMoAR cPSD| 37701387

Lab Session 10:


a) Write unit tests for UI components
Unit tests for UI components in Flutter typically involves using the flutter_test package along
with the testpackage for writing tests.
Here's how we can write unit tests for the PostCard widget:

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


.dart';
import 'package:your_app/post_card.dart'; // Import your widget file void main() {
testWidgets('PostCard displays title and body', (WidgetTester tester) async {
// Build our widget and trigger a frame.await tester.pumpWidget( MaterialApp(
home:
PostCard( title: 'Test Title', body:
'Test Body',
),
),

);

// Verify that the title and body are displayed correctly.expect(find.text('Test Title'),
findsOneWidget); expect(find.text('Test Body'), findsOneWidget);
});

testWidgets('PostCard widget has correct styling', (WidgetTester tester) async {


// Build our widget and trigger a frame.await tester.pumpWidget( MaterialApp(
home: PostCard( title: 'Test Title', body: 'Test Body',
),
),
);

// Verify that the text styles are applied correctly. final titleText =
tester.widget<Text>(find.text('Test Title'));expect(titleText.style.fontSize, 18);
expect(titleText.style.fontWeight, FontWeight.bold);

final bodyText = tester.widget<Text>(find.text('Test Body')); expect(bodyText.style.fontSize,


16);
});
}

In this test:
We use the testWidgets function from the flutter_test package to define our test cases.

In the first test case, we ensure that the PostCard widget correctly displays the provided title and
body text.

In the second test case, we verify that the text styles applied to the title and body texts are as
expected. We use expect statements to assert that the expected UI elements are found on the
screen and that theirproperties match the expected values.
51
lOMoAR cPSD| 37701387

Make sure to replace your_app with the appropriate package name where your PostCard widget
resides.

Run the tests using the following command:


flutter test
This will execute all the tests defined in your project, including the ones written for the UI
components.

Make sure to provide different test scenarios and edge cases to ensure comprehensive test
coverage for yourUI components.

b) Use flutter's debugging tools to identify and fix issues?


demonstrate the use of Flutter's debugging tools, let's consider a scenario where we have a
simple counter app, but there's a bug where the counter is not incrementing when the "+" button
is pressed. We'll use Flutter's debugging tools to identify and fix this issue.
Here's the code for the counter app: import 'package:flutter/material.dart';

void main()
{
runApp (MyAp p());
}

class MyApp extends StatelessWidget { @override


Widget build(BuildContext context) {return MaterialApp(
home: CounterApp(),
);
}
}

class CounterApp extends StatefulWidget {@override


_CounterAppState createState() => _CounterAppState();
}

class _CounterAppState extends State<CounterApp> {int _counter = 0;

void _incrementCounter() {
_counter++;
}

@override Widget
build(BuildContext context) {return Scaffold( appBar: AppBar(
title: Text('Counter App'),
),
body:
Center ( child:
Colum n(

mainAxisAlignment: MainAxisAlignment.center, children:


<Widget>[ Text(
52
lOMoAR cPSD| 37701387

'Counter:',
style: TextStyle(fontSize: 24),
),
Text( '$_cou nter',
style: TextStyle(fontSize: 36, fontWeight: FontWeight.bold),
),
],
),
),
floatingActionButton:
FloatingActionButton(onPressed:
_incrementCounter, tooltip:
'Increment', child:
Icon(Icons.ad d),
),
);
}
}

Now, let's use Flutter's debugging tools to identify and fix the issue:
Widget Inspector: First, let's inspect the widget tree to see if the "+" button is correctly wired to
the
_incrementCounter method. We can do this by running the app in debug mode and enabling the
widget inspector. You can do this by clicking the "Open DevTools" button in your IDE (Android
Studio/IntelliJIDEA or Visual Studio Code) or running the following command in your terminal:
flutter run –debug

Once the app is running, click on the "Toggle Widget Inspector" button in the top-right corner of
your app. Then, select the FloatingActionButton widget representing the "+" button. Ensure that
the onPressedcallback is correctly set to _incrementCounter.
Debugging Console: If everything looks fine in the widget inspector, we can add some debug
print statements to the _incrementCounter method to see if it's being called when the button is
pressed. Modify the
_incrementCounter method as follows:void
_incrementCounter() { print('Incrementing counter');
_counter++;
}

53
lOMoAR cPSD| 37701387

Now, run the app again in debug mode and observe the console output when you press the "+"
button. If you don't see the "Incrementing counter" message in the console, it means the
incrementCounter method is not being called.

Breakpoints: As a final step, let's set a breakpoint in the _incrementCounter method and debug
the app to see if it's being hit. Add a breakpoint by clicking on the left margin of the
_incrementCounter method in your code editor. Then, run the app in debug mode and press the
"+" button. The app should pause at the breakpoint, allowing you to inspect the current state and
variables. You can step through the code to see if there are any issues with the execution flow.

By using Flutter's debugging tools, you should be able to identify the issue with the counter app
and fix it accordingly. In this case, if the debugging process reveals that the _incrementCounter
method is not being called, you can double-check the onPressed callback of the
FloatingActionButton to ensure it's correctly wired to the _incrementCounter method.

54

You might also like