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

FlutterLabManual

This document certifies that G. Sri Sindhu has completed the Flutter Lab record for the academic year 2024-2025. It outlines various tasks and exercises related to Flutter and Dart programming, including installation, widget exploration, UI design, navigation, state management, and responsiveness. The document includes code examples and instructions for implementing these tasks.

Uploaded by

sarvavaishnavi4
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)
3 views

FlutterLabManual

This document certifies that G. Sri Sindhu has completed the Flutter Lab record for the academic year 2024-2025. It outlines various tasks and exercises related to Flutter and Dart programming, including installation, widget exploration, UI design, navigation, state management, and responsiveness. The document includes code examples and instructions for implementing these tasks.

Uploaded by

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

J.N.T.U.H.

UNIVERSITY COLLEGE OF ENGINEERING


SCIENCE AND TECHNOLOGY HYDERABAD, KUKATPALLY,
HYDERABAD – 500 085

This is to certify that G. Sri Sindhu of B. TECH III year I Semester bearing Hall-
ticket number 23015A6602 has fulfilled his/her FLUTTER LAB record for the
academic year 2024-2025.

Date of Examination:

Internal Examiner External Examiner

1
S.no programs Pg.no

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.

2
1. a) Install Flutter and Dart SDK

1. Download Android Studio from the Android Studio Download Page and install it on your
system by following the on-screen instructions.
2. Launch Android Studio and complete the setup wizard, ensuring you install the required
components, including the Android SDK and Android SDK Platform-Tools.
3. Visit the Flutter Install Page and download the Flutter SDK for your operating system.
4. Extract the downloaded Flutter SDK zip file to a preferred location on your computer,
such as C:\flutter on Windows or /Users/your-username/flutter on macOS or Linux.
5. Add the Flutter SDK to your system PATH. On Windows, open Environment Variables by
pressing Win + R, typing sysdm.cpl, and pressing Enter. Navigate to the Advanced tab, click
on Environment Variables, find the Path variable under System Variables, click Edit, and
add the path to the Flutter SDK’s bin directory (e.g., C:\flutter\bin). On macOS or Linux,
open the terminal and edit your shell configuration file (e.g., ~/.zshrc or ~/.bashrc), adding
the line export PATH="$PATH:/path-to-flutter-sdk/bin", then save and reload the terminal
by running source ~/.zshrc or source ~/.bashrc.
6. Open a terminal and verify the Flutter installation by running the command flutter doctor.
Follow the output to fix any issues, such as installing additional dependencies.
7. Open Android Studio, go to File > Settings > Plugins (Preferences > Plugins on macOS),
click on the Marketplace tab, search for "Flutter," and install the Flutter plugin. When
prompted, also install the Dart plugin.
8. Restart Android Studio to activate the plugins.
9. Run flutter doctor again to ensure the Flutter and Dart plugins are detected in Android
Studio.
10. Create a new Flutter project in Android Studio by navigating to File > New > New
Flutter Project, selecting "Flutter Application," and configuring the project details. Specify
the Flutter SDK path (e.g., C:\flutter), provide a project name, and select the desired project
location.
11. Enable desktop support by running flutter config --enable-windows-desktop (for
Windows), flutter config --enable-macos-desktop (for macOS), or flutter config --enable-
linux-desktop (for Linux) in the terminal. Then run flutter doctor to verify that desktop
support is enabled.
12. Build and run your Flutter project by clicking the green Run button in Android Studio.
Your Flutter app will launch as a desktop application.

b) Write a simple Dart program to understand the language basics.


import 'dart:io';
void main() {
// Printing to console
print("Hello, World!");

// Variables and Data Types


int age = 19;

3
double height = 165;
String name = "Sri Sindhu";
bool isStudent = true;

print("Name: $name, Age: $age, Height: $height, Is Student: $isStudent");

// Taking String input


print("Enter your name:");
String? frstname = stdin.readLineSync();

// Taking integer input


print("Enter your age:");
int? old = int.parse(stdin.readLineSync()!);

}
Output:

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


Text Widget
main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {

4
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Text Widget Example"),
),
body: Center(
child: Text(
"Hello, This is Text Widget Example!",
style: TextStyle(
fontSize: 24, // Text size
fontWeight: FontWeight.bold, // Text weight
color: Colors.blue, // Text color
letterSpacing: 2.0, // Space between letters
wordSpacing: 4.0, // Space between words
),
textAlign: TextAlign.center, // Center align text
),
),
),
);
}
}
Output

5
Image Widget
main.dart

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("Image Widget Example"),
),
body: Center(
child: Image.asset(
'assets/images/nature.jpg', // Path to your image file in the assets folder
width: 300, // Set the width of the image
height: 300, // Set the height of the image
fit: BoxFit.cover, // Specifies how the image should fit in the box
),
),
),
);
}
}
}
Output:

6
Container Widget
main.dart
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('Container Widget Example'),
),
body: Center(
child: Container(
width: 200,
height: 200,
padding: EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(10),

7
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3), // changes position of shadow
),
],
),
child: Center(
child: Text(
'Hello,This is a Container!',
style: TextStyle(color: Colors.white, fontSize: 18),
textAlign: TextAlign.center,
),
),
),
),
),
);
}
}
Output:

8
b) Implement different layout structures using Row, Column, and Stack widgets.
Row Widget
main.dart
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('Row Widget Example'),
),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center, // Align items horizontally
crossAxisAlignment: CrossAxisAlignment.center, // Align items vertically
children: <Widget>[
Container(
width:50,
height:50,
color:Colors.red,
),
SizedBox(width:20),
Container(
width:50,
height:50,
color:Colors.blue,
),
SizedBox(width:20),
Container(
width:50,
height:50,
color:Colors.green,
),
SizedBox(width:20),
],

9
),
),
),
);
}
}
Output:

Column Widget
main.dart
import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(

10
appBar: AppBar(
title: Text('Column Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center, // Align items horizontally
crossAxisAlignment: CrossAxisAlignment.center, // Align items vertically
children: <Widget>[
Container(
width:50,
height:50,
color:Colors.red,
),
SizedBox(height:20),
Container(
width:50,
height:50,
color:Colors.blue,
),
SizedBox(height:20),
Container(
width:50,
height:50,
color:Colors.green,
),
],
),
),
),
);
}
}

11
Output:

Stack Widget
main.dart
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 Widget Example'),
),
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
// Bottom layer: A container
12
Container(
width: 200,
height: 200,
color: Colors.blue,
),
// Middle layer: A circle
Container(
width: 150,
height: 150,
decoration: BoxDecoration(
color: Colors.green,

),
),
// Top layer: Text
Text(
'Hello, Stack!',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
);
}
}

13
Output:

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


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

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

class MyApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,

14
home: ResponsiveHomePage(),
);
}
}

class ResponsiveHomePage extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Responsive UI Example'),
),
body: LayoutBuilder(
builder: (context, constraints) {
// Use constraints to determine screen size
if (constraints.maxWidth < 600) {
return MobileLayout(); // Mobile layout
} else if (constraints.maxWidth >= 600 && constraints.maxWidth < 1200) {
return TabletLayout(); // Tablet layout
} else {
return DesktopLayout(); // Desktop layout
}
},
),
);
}
}

// Mobile Layout
Widget MobileLayout()
{
return Center(
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Mobile Layout',style:TextStyle(fontSize: 24)),
SizedBox(height:20),
Icon(Icons.phone_android,size:100),
],
)
);
}

// Tablet Layout
Widget TabletLayout()
{
return Center(
child:Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [

15
Icon(Icons.tablet_mac,size:100),
Text('Tablet Layout',style:TextStyle(fontSize: 28)),
SizedBox(width:20),

],
)
);
}
// Desktop Layout
Widget DesktopLayout()
{
return Center(
child:Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.laptop,size:100),
Text('Desktop Layout',style:TextStyle(fontSize: 32)),
SizedBox(width:20),

],
)
);
}

Output:

16
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(
home: ResponsiveUI(),
);
}
}

17
class ResponsiveUI extends StatelessWidget{
@override
Widget build(BuildContext context){
double screenWidth = MediaQuery.of(context).size.width;

if (screenWidth < 600)


{
return Scaffold(
appBar: AppBar(
title: Text("MobileLayout"),
),
body: Center(
child: Container(
width: screenWidth * 0.8,
height: 150,
color: Colors.yellowAccent,
child: Center(
child: Text("MobileLayout"),
)
),
),
);
}
else if(screenWidth >=600 && screenWidth <1200){
return Scaffold(
appBar: AppBar(
title: Text("TabletLayout"),
),
body: Center(
child: Container(
width: screenWidth * 0.8,
height: 150,
color: Colors.blueAccent,
child: Center(
child: Text("TabletLayout"),
)
),
),
);
}
else{
return Scaffold(
appBar: AppBar(

18
title: Text("DesktopLayout"),
),
body: Center(
child: Container(
width: screenWidth * 0.8,
height: 150,
color: Colors.blueAccent,
child: Center(
child: Text("DesktopLayout"),
)
),
),
);
}
}
}

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


b) Implement navigation with named routes

import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
title: 'Navigation Example',
theme: ThemeData(primarySwatch: Colors.blue),
home: HomeScreen(),
));
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home Screen')),
body: Center(
child: ElevatedButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailsScreen()),
),
child: Text('Go to Details'),
),
),
);
}

19
}
class DetailsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Details Screen')),
body: Center(
child: ElevatedButton(
onPressed: () => Navigator.pop(context),
child: Text('Back to Home'),
),
),
);
}
}

5. a) Learn about stateful and stateless widgets


Stateless widget:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {


@override

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

class CounterScreen extends StatelessWidget {

@override
Widget build(BuildContext context) {
int _count = 0;
void _incrementCounter() {
}

return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Button pressed $_count times',
style: TextStyle(fontSize: 24),
),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment'),
),
],
),
);
}
}

21
Stateful Widget:

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('Stateful Widget Example')),
body: Counter(),
),
);
}
}

class Counter extends StatefulWidget {


@override
_CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {


int _count = 0; // Mutable state

void _incrementCounter() {
setState(() {
_count++; // Updating the state
});
}

22
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Button pressed $_count times',
style: TextStyle(fontSize: 24),
),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment'),
),
],
),
);
}
}

b. Implement state management using set State and Provider.

Pubspec.yaml

dependencies:
flutter:
sdk: flutter
provider: ^6.0.0
main.dart:

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

23
class GlobalCounter with ChangeNotifier {
int _counter = 0;
int get counter => _counter;
void increment() => _counter++;
void decrement() => _counter--;
}

void main() => runApp(


ChangeNotifierProvider(
create: (_) => GlobalCounter(),
child: MyApp(),
),
);

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


int _localCounter = 0;

@override
Widget build(BuildContext context) {
final globalCounter = Provider.of<GlobalCounter>(context);

return Scaffold(
appBar: AppBar(title: Text("State Management")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Local Counter: $_localCounter', style: TextStyle(fontSize: 24)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [

24
IconButton(icon: Icon(Icons.remove), onPressed: () => setState(() =>
_localCounter--)),
IconButton(icon: Icon(Icons.add), onPressed: () => setState(() =>
_localCounter++)),
],
),
SizedBox(height: 20),
Text('Global Counter: ${globalCounter.counter}', style: TextStyle(fontSize: 24)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(icon: Icon(Icons.remove), onPressed: globalCounter.decrement),
IconButton(icon: Icon(Icons.add), onPressed: globalCounter.increment),
],
),
],
),
),
);
}
}

output:

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

import 'package:flutter/material.dart';
class CustomButton extends StatelessWidget {
final String text;
final Function onPressed;
final Color buttonColor;
final Color textColor;
CustomButton({
required this.text,

25
required this.onPressed,
this.buttonColor = Colors.blue,
this.textColor = Colors.white,
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => onPressed(),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(buttonColor),
foregroundColor: MaterialStateProperty.all(textColor),
),
child: Text(text),
);
}
}
class CustomAlertDialog extends StatelessWidget {
final String title, message, positiveButtonText, negativeButtonText;
final Function onPositivePressed, onNegativePressed;
CustomAlertDialog({
required this.title,
required this.message,
required this.positiveButtonText,
required this.negativeButtonText,
required this.onPositivePressed,
required this.onNegativePressed,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(title),
content: Text(message),
actions: [
CustomButton(text: negativeButtonText, onPressed: () => onNegativePressed()),
CustomButton(text: positiveButtonText, onPressed: () => onPositivePressed()),
],
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override

26
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Custom Button Example')),
body: Center(
child: CustomButton(
text: 'Click Me',
onPressed: () {
print('Button Pressed');
},
),
),
),
);
}
}

b) Apply styling using themes and custom styles.

import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool _isDarkMode = false; // Track theme state
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: _isDarkMode ? ThemeData.dark() : ThemeData.light(),

27
home: Scaffold(
appBar: AppBar(
title: Text('Simple Theme Toggle'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Hello, World!',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
setState(() {
_isDarkMode = !_isDarkMode; // Toggle theme
});
},
child: Text(
_isDarkMode ? 'Switch to Light Theme' : 'Switch to Dark Theme',
),
),
],
),
),
),
);
}
}

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

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {


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

class FormPage extends StatefulWidget {


@override
_FormPageState createState() => _FormPageState();
}

class _FormPageState extends State<FormPage> {


final _formKey = GlobalKey<FormState>();
final _nameController = TextEditingController();
final _emailController = TextEditingController();

void _submitForm() {
if (_formKey.currentState!.validate()) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Form Submitted'),
content: Text('Name: ${_nameController.text}\nEmail: ${_emailController.text}'),
actions: [TextButton(onPressed: () => Navigator.pop(context), child: Text('OK'))],
),

29
);
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Simple Form')),
body: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _nameController,
decoration: InputDecoration(labelText: 'Name'),
validator: (value) => value!.isEmpty ? 'Please enter your name' : null,
),
SizedBox(height: 16),
TextFormField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
validator: (value) => value!.isEmpty ? 'Please enter your email' : null,
),
SizedBox(height: 16),
ElevatedButton(onPressed: _submitForm, child: Text('Submit')),
],
),
),
),
);
}
}

30
b) Implementation 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(
title: 'Flutter Form Validation',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _formKey = GlobalKey<FormState>();
final _usernameController = TextEditingController();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
void _submitForm() {
if (_formKey.currentState?.validate() ?? false) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Form
Validated')));
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Please fix the
errors')));

31
}
}
@override
void dispose() {
_usernameController.dispose();
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Form Validation')),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey, // Form key to validate
child: Column(
children: [
TextFormField(
controller: _usernameController,
decoration: InputDecoration(labelText: 'Username'),
validator: (value) {
if (value?.isEmpty ?? true) return 'Please enter a username';
return null;
},
),
SizedBox(height: 16),
TextFormField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value?.isEmpty ?? true) return 'Please enter an email address';
if (!RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-
Z]{2,4}$').hasMatch(value!))
return 'Invalid email format';
return null;
},
),
SizedBox(height: 16),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),

32
obscureText: true,
validator: (value) {
if (value?.isEmpty ?? true) return 'Please enter a password';
if (value!.length < 6) return 'Password must be at least 6 characters';
return null;
},
),
SizedBox(height: 16),
ElevatedButton(
onPressed: _submitForm,
child: Text('Submit'),
),
],
),
),
),
);
}}

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

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Animation Example',
home: AnimationExample(),
);
}
}

class AnimationExample extends StatefulWidget {


@override
_AnimationExampleState createState() => _AnimationExampleState();
}

class _AnimationExampleState extends State<AnimationExample> with


SingleTickerProviderStateMixin {
late final AnimationController _controller = AnimationController(duration: const
Duration(seconds: 2), vsync: this);
late final Animation<double> _animation = Tween<double>(begin: 0.0, end:
1.0).animate(_controller)..addListener(() => setState(() {}));

@override

34
void dispose() {
_controller.dispose();
super.dispose();
}

void _toggleAnimation() => _controller.isCompleted ? _controller.reverse() :


_controller.forward();

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Fade Animation Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Opacity(
opacity: _animation.value,
child: Container(
width: 200,
height: 200,
color: Colors.blue,
child: Center(child: Text('Fade Me!', style: TextStyle(color: Colors.white, fontSize: 24))),
),
),
SizedBox(height: 20),
ElevatedButton(onPressed: _toggleAnimation, child: Text('Toggle Fade')),
],
),
),
);
}
}

35
b) Experiment with different types of Animations
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: AnimationExperiment());
}
}

class AnimationExperiment extends StatefulWidget {


@override
_AnimationExperimentState createState() => _AnimationExperimentState();
}

class _AnimationExperimentState extends State<AnimationExperiment> with


TickerProviderStateMixin {
late final AnimationController _controller;
late final Animation<double> _fadeAnimation, _scaleAnimation,
_rotateAnimation;
late final Animation<Offset> _slideAnimation;

@override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 2));
_fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(_controller);
_scaleAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(_controller);
_slideAnimation =
Tween<Offset>(begin: Offset(1.0, 0.0), end: Offset.zero).animate(

36
_controller);
_rotateAnimation =
Tween<double>(begin: 0.0, end: 6.28).animate(_controller);
Future.delayed(Duration(milliseconds: 500), () => _controller.forward());
}

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

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Animation Experiment'), centerTitle: true),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FadeTransition(
opacity: _fadeAnimation, child: _buildText('Faded In Text')),
SizedBox(height: 20),
ScaleTransition(
scale: _scaleAnimation,
child: ElevatedButton(
onPressed: () {
_controller.forward(from: 0.0);
},
child: Text('Click to Fade Again'),
),
),
SizedBox(height: 20),
SlideTransition(
position: _slideAnimation,
child: _buildContainer('Slid In', Colors.green),
),
SizedBox(height: 20),
AnimatedBuilder(
animation: _rotateAnimation,
builder: (context, child) {
return Transform.rotate(
angle: _rotateAnimation.value, child: child);

37
},
child: Icon(Icons.refresh, size: 50, color: Colors.purple),
),
],
),
),
);
}

Widget _buildText(String text) {


return Text(
text, style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold));
}

Widget _buildContainer(String text, Color color) {


return Container(
width: 200,
height: 100,
color: color,
child: Center(child: Text(text, style: TextStyle(color: Colors.white))),
);
}
}

9.a) Fetch data from a REST API.


Pubspec.yaml:
dependencies:
flutter:

38
sdk: flutter
http: ^01.2.2

main.dart:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class User {
final int id;
final String name;
final String username;
final String email;

User({required this.id, required this.name, required this.username, required this.email});

factory User.fromJson(Map<String, dynamic> json) {


return User(
id: json['id'],
name: json['name'],
username: json['username'],
email: json['email'],
);
}
}

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

class MyApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data from API',
theme: ThemeData(primarySwatch: Colors.blue),
home: UserListScreen(),
);
}
}

class UserListScreen extends StatefulWidget {


@override
_UserListScreenState createState() => _UserListScreenState();

39
}

class _UserListScreenState extends State<UserListScreen> {


late Future<List<User>> _users;

@override
void initState() {
super.initState();
_users = fetchUsers();
}
Future<List<User>> fetchUsers() async {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users'));
if (response.statusCode == 200) {

List<dynamic> data = json.decode(response.body);


return data.map((userJson) => User.fromJson(userJson)).toList();
} else {
throw Exception('Failed to load users');
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('User List')),
body: FutureBuilder<List<User>>(
future: _users,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Center(child: Text('No users found'));
} else {

List<User> users = snapshot.data!;


return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(users[index].name),
subtitle: Text(users[index].email),
);

40
},
);
}
},
),
);
}
}

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


Pubspec.yaml:
dependencies:
flutter:
sdk: flutter
http: ^1.2.2
main.dart:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class User {
final int id;
final String name;
final String username;

41
final String email;
final String phone;
final String website;
final Address address;
final Company company;

User({
required this.id,
required this.name,
required this.username,
required this.email,
required this.phone,
required this.website,
required this.address,
required this.company,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
username: json['username'],
email: json['email'],
phone: json['phone'],
website: json['website'],
address: Address.fromJson(json['address']),
company: Company.fromJson(json['company']),
);
}
}
class Address {
final String street;
final String suite;
final String city;
final String zipcode;

Address({required this.street, required this.suite, required this.city, required this.zipcode});

factory Address.fromJson(Map<String, dynamic> json) {


return Address(
street: json['street'],
suite: json['suite'],
city: json['city'],
zipcode: json['zipcode'],
);

42
}
}

class Company {
final String name;
final String catchPhrase;
final String bs;

Company({required this.name, required this.catchPhrase, required this.bs});

factory Company.fromJson(Map<String, dynamic> json) {


return Company(
name: json['name'],
catchPhrase: json['catchPhrase'],
bs: json['bs'],
);
}
}

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

class MyApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'User Details',
theme: ThemeData(primarySwatch: Colors.blue),
home: UserListScreen(),
);
}
}

class UserListScreen extends StatefulWidget {


@override
_UserListScreenState createState() => _UserListScreenState();
}

class _UserListScreenState extends State<UserListScreen> {


late Future<List<User>> _users;

@override
void initState() {

43
super.initState();
_users = fetchUsers(); // Call the function to fetch data
}
Future<List<User>> fetchUsers() async {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users'));

if (response.statusCode == 200) {
List<dynamic> data = json.decode(response.body);
return data.map((userJson) => User.fromJson(userJson)).toList();
} else {
throw Exception('Failed to load users');
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('User Details')),
body: FutureBuilder<List<User>>(
future: _users,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Center(child: Text('No users found'));
} else {
List<User> users = snapshot.data!;
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return Card(
margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
elevation: 5,
child: ListTile(
contentPadding: EdgeInsets.all(16),
title: Text(
users[index].name,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

44
Text('Username: ${users[index].username}', style: TextStyle(color:
Colors.grey[600])),
Text('Email: ${users[index].email}', style: TextStyle(color:
Colors.grey[600])),
Text('Phone: ${users[index].phone}', style: TextStyle(color:
Colors.grey[600])),
Text('Website: ${users[index].website}', style: TextStyle(color:
Colors.grey[600])),
SizedBox(height: 8),
Text('Address:', style: TextStyle(fontWeight: FontWeight.bold)),
Text('${users[index].address.suite}, ${users[index].address.street},
${users[index].address.city}, ${users[index].address.zipcode}', style: TextStyle(color:
Colors.grey[600])),
SizedBox(height: 8),
Text('Company:', style: TextStyle(fontWeight: FontWeight.bold)),
Text('${users[index].company.name}', style: TextStyle(color:
Colors.grey[600])),
Text('${users[index].company.catchPhrase}', style: TextStyle(color:
Colors.grey[600])),
],
),
),
);
},
);
}
},
),
);
}
}

45
10.a) Write unit tests for UI components.
Unit tests are handy for verifying the behavior of a single function, method, or class. The
test package provides the core framework for writing unit tests, and the flutter_test package
provides additional utilities for testing widgets.
This recipe demonstrates the core features provided by the test package using the
following steps:
Add the test or flutter_test dependency.
Create a test file.
Create a class to test.
Write a test for our class.
Combine multiple tests in a group.
Run the tests.
For more information about the test package, see the test package documentation.
1. Add the test dependency The test package provides the
core functionality for writing tests in Dart. This is the best approach when writing packages
consumed by web, server, and Flutter apps.
To add the test package as a dev dependency, run flutter pub add: content_copy
flutter pub add dev:test
2. Create a test file In this example,
create two files: counter.dart and counter_test.dart.

46
The counter.dart file contains a class that you want to test and resides in the lib folder. The
counter_test.dart file contains the tests themselves and lives inside the test folder.
The counter.dart file contains a class that you want to test and resides in the lib folder. The
counter_test.dart file contains the tests themselves and lives inside the test folder.

In general, test files should reside inside a test folder located at the root of your Flutter
application or package. Test files should always end with _test.dart, this is the convention
used by the test runner when searching for tests.
When you’re finished, the folder structure should look like this:
content_copy
counter_app/
lib/
counter.dart
test/
counter_test.dart
3. Create a class to test Next, you need a “unit” to test.
Remember: “unit” is another name for a function, method, or class. For this example, create
a Counter class inside the lib/counter.dart file. It is responsible for incrementing and
decrementing a value starting at 0.
content_copy
class Counter {
int value = 0;
void increment() => value++;
void decrement() => value--;
}
Note: For simplicity, this tutorial does not follow the “Test Driven Development” approach.
If you’re more comfortable with that style of development, you can always go that route.
4. Write a test for our class
Inside the counter_test.dart file, write the first unit test. Tests are defined using the top-level
test function, and you can check if the results are correct by using the top- level expect
function. Both of these functions come from the test package.
content_copy
// Import the test package and Counter class import 'package:counter_app/counter.dart';
import 'package:test/test.dart';
void main() { test('Counter value should be incremented', () {
final counter = Counter();
counter.increment();
expect(Counter.value,1);
}); }
5. Combine multiple tests in a group
If you want to run a series of related tests, use the flutter_test package group function to
categorize the tests. Once put into a group, you can call flutter test on all tests in that group
with one command.
content_copy

47
import 'package:counter_app/counter.dart';
import 'package:test/test.dart';
void main() {
group('Test start, increment, decrement', () {
test('value should start at 0', () {
expect(Counter().value, 0); });
test('value should be incremented', () {
final counter = Counter();
counter.increment();
expect(counter.value, 1); });
test('value should be decremented', () {
final counter = Counter(); counter.decrement();
expect(counter.value, -1);
}); }); }
6. Run the tests Now that you have a Counter class with tests
in place, you can run the tests.
Run tests using IntelliJ or VSCode
The Flutter plugins for IntelliJ and VSCode support running tests. This is often the best
option while writing tests because it provides the fastest feedback loop as well as the ability
to set breakpoints.
IntelliJ
Open the counter_test.dart file
Go to Run > Run ‘tests in counter_test.dart’. You can also press the appropriate keyboard
shortcut for your platform.
VSCode

Open the counter_test.dart file


Go to Run > Start Debugging. You can also press the appropriatekeyboard shortcut
for your platform.
Run tests in a terminal
To run the all tests from the terminal, run the following command from the root of the
project:
content_copy
flutter test test/counter_test.dart
To run all tests you put into one group, run the following command from the root of the
project:
content_copy
flutter test --plain-name "Test start, increment, decrement"
This example uses the group created in section 5.
To learn more about unit tests, you can execute this command:

b) Use Flutter's debugging tools to identify and fix issues.


Flutter provides a set of debugging tools that can help you identify and fix issues in your
app. Here's a step-by-step guide on how to use these tools:

48
1. Flutter DevTools:
Run your app with the flutter run command. Open DevTools by running the following
command in your terminal:
Bash
flutter pub global activate devtools
flutter pub global run devtools
Open your app in a Chrome browser and connect it to DevTools by clicking on the "Open
DevTools" button in the terminal or by navigating to http://127.0.0.1:9100/. DevTools
provides tabs like Inspector, Timeline, Memory, and more.
2. Flutter Inspector: Use the Flutter Inspector in your
integrated development environment (IDE) like Android Studio or Visual Studio
Code. Toggle the Inspector in Android Studio with the shortcut Alt + Shift + D
(Windows/Linux) or Option + Shift + D. Inspect the widget tree, modify widget properties,
and observe widget relationships.
3. Hot Reload: Leverage Hot Reload to see the immediate
effect of code changes without restarting the entire app. Press R in the terminal or use the
"Hot Reload" button in your IDE.
4. Debugging with Breakpoints: Set breakpoints in your code
to pause execution and inspect variables. Use the debugger in your IDE to step through code
and identify issues.
5. Logging: Utilize the print function to log messages to the
console. print('Debugging message'); View logs in the terminal or the "Logs" tab in
DevTools.
6. Debug Paint: Enable debug paint to visualize the layout
and rendering of widgets. Use the debugPaintSizeEnabled and debugPaintBaselinesEnabled
flags.
void main() {
debugPaintSizeEnabled = true;
runApp(MyApp());
}
7. Memory Profiling: Use the "Memory" tab in DevTools to
analyze memory usage and identify potential memory leaks. Monitor object
allocations and deallocations.
8. Performance Profiling (Timeline): Analyze app
performance using the "Timeline" tab in DevTools. Identify UI jank, slow frames, and
performance bottlenecks.
9. Flutter Driver Tests:
Write automated UI tests using Flutter Driver.
Simulate user interactions and validate the correctness of your UI.

49

You might also like