III I Ui Design Flutter Lab Programs 2
III I Ui Design Flutter Lab Programs 2
ENGINEERING
UI DESIGN-
FLUTTER LAB
MANUAL
Prepared by
b) Implement different layout structures using Row, Column, and Stack widgets.
TEXT BOOK:
1. Marco L. Napoli, Beginning Flutter: A Hands-on Guide to App Development
1.a) Install Flutter and Dart SDK.
Ans) Dart SDK is a pre-compiled version so we have to download and extract it
only. For this follow the below-given instructions: Step 1: Download Dart SDK.
Download Dart SDK from the Dart SDK archive page. The URL
is: https://dart.dev/tools/sdk/archive
Click on DART SDK to download SDK for Windows 64-Bit Architecture. The
download will start and a zip file will be downloaded. Note: To download SDK for
any other OS select OS of your choice. Step 2: Extract the downloaded zip file.
Extract the contents of downloaded zip file and after extracting contents of zip file
will be as shown:
Step 3: Running Dart. Now open bin folder and type “cmd” as given below:
Command Prompt will open with our desired path of bin folder and now type dart”.
And now we are ready to use dart through bin folder but setting up the path in environment variables
will ease our task of Step3 and we can run dart from anywhere in the file system using command
prompt.
Step 4: Setting up path in environment variables. Open Environment Variables from
advanced system settings and add Path in System Variables as depicted in image:
Now we are done to use Dart from anywhere in the file system.
Step 5: Run Dart Using cmd
void main() {
int num1 = 10; //declaring number1
int num2 = 3; //declaring number2
// Calculation
int sum = num1 + num2;
int diff = num1 - num2;
int mul = num1 * num2;
double div = num1 / num2; // It is double because it outputs number with
decimal.
Output:
The sum is 13
The diff is 7
The mul is 30
The div is 3.3333333333333335
Output: When we run this application in the emulator or device, we should get the UI similar to the
below screenshot:
Image Widget:
import 'package:flutter/material.dart';
Output:
Container Widget:
import 'package:flutter/material.dart';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyContainerWidget(),
);
}
}
Output:
2.b) Implement different layout structures using Row, Column, and Stack widgets
Row widgets:
import 'package:flutter/material.dart';
Output:
When we run this app, we should get the UI as the below screenshot.
Column widgets:
import 'package:flutter/material.dart';
void main() { runApp(MyApp()); }
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage()
);
}
}
import 'package:flutter/material.dart';
home: MyStackWidget(),
);
}
}
Positioned(
top: 30,
left: 20,
child: Container(
height: 100,
width: 150,
color: Colors.orange,
child: Center(
child: Text(
'Bottom Widget',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
)
),
],
),
)
),
);
}
}
Output:
When we run the app, we should get the UI of the screen similar to the below screenshot:
3.a) Implement Design a responsive UI that adapts to different screen sizes Flutter.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Responsive UI Example',
home: ResponsiveHome(),
);
}
}
class ResponsiveHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Responsive UI')),
body: LayoutBuilder(
builder: (context, constraints) {
// Determine screen size
bool isWideScreen = constraints.maxWidth > 600;
return Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Responsive Image
Container(
width: isWideScreen ? 300 : 150,
height: isWideScreen ? 300 : 150,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://via.placeholder.com/300'),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.circular(15),
),
),
SizedBox(height: 20),
// Responsive Text
Text(
'Welcome to Responsive Flutter UI!',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: isWideScreen ? 24 : 18,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 20),
// Responsive Button
ElevatedButton(
onPressed: () {},
child: Text('Click Me'),
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(
horizontal: isWideScreen ? 30 : 15,
vertical: isWideScreen ? 15 : 10,
),
),
),
],
),
);
},
),
);
}
}
Output:
return Scaffold(
appBar: AppBar(title: Text('Responsive UI')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Header
Container(
width: double.infinity,
padding: EdgeInsets.all(16),
color: Colors.blueAccent,
child: Text(
'Responsive Header',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: isDesktop ? 28 : isTablet ? 24 : 20,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(height: 20),
// Content Area
Expanded(
child: Row(
children: [
// Left Column
Expanded(
child: Column(
children: [
Container(
margin: EdgeInsets.symmetric(vertical: 10),
height: isDesktop ? 200 : isTablet ? 160 : 120,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://via.placeholder.com/300'),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.circular(10),
),
),
Text(
'Image 1',
style: TextStyle(fontSize: isDesktop ? 18 : isTablet ? 16 : 14),
),
SizedBox(height: 20),
Container(
margin: EdgeInsets.symmetric(vertical: 10),
height: isDesktop ? 200 : isTablet ? 160 : 120,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://via.placeholder.com/300'),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.circular(10),
),
),
Text(
'Image 2',
style: TextStyle(fontSize: isDesktop ? 18 : isTablet ? 16 : 14),
),
],
),
),
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
@override
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomeScreen(),
);
}
// Home Screen
@override
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
);
},
),
),
);
// Second Screen
@override
return Scaffold(
appBar: AppBar(title: Text('Second Screen')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
);
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
);
// Third Screen
@override
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
),
SizedBox(height: 20),
ElevatedButton(
},
),
],
),
),
);
Home Screen:
Second Screen:
Third Screen:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
Output:
5.a) Learn about statefull and stateless widgets.
1.Stateful Widget Example:
import 'package:flutter/material.dart';
class MyStatefulWidget extends StatefulWidget {
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stateful Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SetState Example',
home: CounterScreen(),
);
}
}
class CounterScreen extends StatefulWidget {
@override
_CounterScreenState createState() => _CounterScreenState();
}
Output:
After pressing the button once:
Counter Value: 1
After pressing it three times:
Counter Value: 3
void increment() {
_counter++;
notifyListeners(); // Notifies listeners to rebuild
}
}
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter using Provider')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Counter Value: ${Provider.of<Counter>(context).counter}'),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Provider.of<Counter>(context, listen: false).increment();
},
child: Text('Increment'),
),
],
),
),
);
}
}
Output:
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.blueAccent, // Background color
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
onPressed: onPressed,
child: Text(
text,
style: TextStyle(fontSize: 18, color: Colors.white),
),
);
}
}
// Main App
void main() {
runApp(MyApp());
}
OUTPUT:
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).buttonTheme.buttonColor,
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
shape: Theme.of(context).buttonTheme.shape,
),
onPressed: onPressed,
child: Text(
text,
style: TextStyle(color: Colors.white, fontSize: 16),
),
);
}
}
OUTPUT:
7. a) Design a form with various input fields.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
@override
void dispose() {
_nameController.dispose();
_emailController.dispose();
_phoneController.dispose();
_dateController.dispose();
super.dispose();
}
void _submitForm() {
if (_formKey.currentState!.validate()) {
print("Name: ${_nameController.text}");
print("Email: ${_emailController.text}");
print("Phone: ${_phoneController.text}");
print("Date of Birth: ${_dateController.text}");
print("Gender: $_selectedGender");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Form Submitted Successfully!')),
);
}
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: ListView(
children: [
TextFormField(
controller: _nameController,
decoration: InputDecoration(labelText: 'Name'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your name';
}
return null;
},
),
TextFormField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
} else if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
return 'Please enter a valid email';
}
return null;
},
),
TextFormField(
controller: _phoneController,
decoration: InputDecoration(labelText: 'Phone Number'),
keyboardType: TextInputType.phone,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your phone number';
}
return null;
},
),
TextFormField(
controller: _dateController,
decoration: InputDecoration(
labelText: 'Date of Birth',
suffixIcon: Icon(Icons.calendar_today),
),
readOnly: true,
onTap: () => _selectDate(context),
),
DropdownButtonFormField(
value: _selectedGender,
items: _genders.map((String gender) {
return DropdownMenuItem(
value: gender,
child: Text(gender),
);
}).toList(),
onChanged: (newValue) {
setState(() {
_selectedGender = newValue as String;
});
},
decoration: InputDecoration(labelText: 'Gender'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _submitForm,
child: Text('Submit'),
),
],
),
),
);
}
}
7b) Implement form validation and error handling.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
void _submitForm() {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Form Submitted Successfully!')),
);
print("Name: ${_nameController.text}");
print("Email: ${_emailController.text}");
print("Phone: ${_phoneController.text}");
}
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: ListView(
children: [
TextFormField(
controller: _nameController,
decoration: InputDecoration(labelText: 'Name'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your name';
}
return null;
},
),
TextFormField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
} else if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
return 'Please enter a valid email';
}
return null;
},
),
TextFormField(
controller: _phoneController,
decoration: InputDecoration(labelText: 'Phone Number'),
keyboardType: TextInputType.phone,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your phone number';
} else if (!RegExp(r'^\d{10}$').hasMatch(value)) {
return 'Enter a valid 10-digit phone number';
}
return null;
},
),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your password';
} else if (value.length < 6) {
return 'Password must be at least 6 characters long';
}
return null;
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _submitForm,
child: Text('Submit'),
),
],
),
),
);
}
}
OUTPUT:
8. a) Add animations to UI elements using Flutter's animation framework.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
void _toggleContainer() {
setState(() {
_isExpanded = !_isExpanded;
});
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedContainer(
width: _isExpanded ? 200.0 : 100.0,
height: _isExpanded ? 200.0 : 100.0,
decoration: BoxDecoration(
color: _isExpanded ? Colors.blue : Colors.red,
borderRadius: BorderRadius.circular(_isExpanded ? 0 : 50),
),
duration: Duration(seconds: 1),
curve: Curves.easeInOut,
child: Center(
child: Text(
'Tap Me!',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _toggleContainer,
child: Text('Animate Container'),
),
],
),
);
}
}
OUTPUT:
8b) Experiment with different types of animations (fade, slide, etc.).
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget
{ @override
Widget build(BuildContext context)
{ return MaterialApp(
title: 'Fade Animation
Example', theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FadeAnimationWidget(),
);
}
}
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 10),
);
_animationController.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Fade Animation Example'),
),
body: Center(
child: FadeTransition(
opacity: _opacityAnimation,
child: Container(
width: 200,
height: 200,
color: Colors.blue,
child: Center(
child: Text(
'Fade Animation',
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
),
),
),
),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
Output:
Fade Animation
Slide Animation:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
_slideAnimation =
Tween<Offset>( begin: Offset(-
1.0, 0.0),
end: Offset(0.0, 0.0),
).animate( CurvedA
nimation(
parent: _animationController,
curve: Curves.easeInOut,
),
);
_animationController.forward();
}
@override
Widget build(BuildContext context)
{ return Scaffold(
appBar: AppBar(
title: Text('Slide Animation Example'),
),
body: SlideTransition(
position: _slideAnimation,
child: Container(
width: 200,
height: 200,
color: Colors.blue,
child: Center(
child: Text(
'Slide Animation',
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
),
),
),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
Output:
Slide Animation
Scale Animation:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget
{ @override
Widget build(BuildContext context)
{ return MaterialApp(
title: 'Scale Animation Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ScaleAnimationWidget(),
);
}
}
class ScaleAnimationWidget extends StatefulWidget
{ @override
_ScaleAnimationWidgetState createState() => _ScaleAnimationWidgetState();
}
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
_animationController.forward();
}
@override
Widget build(BuildContext context)
{ return Scaffold(
appBar: AppBar(
title: Text('Scale Animation Example'),
),
body: ScaleTransition(
scale: _scaleAnimation,
child: Container(
width: 200,
height: 200,
color: Colors.blue,
child: Center(
child: Text(
'Scale Animation',
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
),
),
),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
Output:
void main() {
runApp(MyApp());
}
if (response.statusCode == 200) {
setState(() {
post = json.decode(response.body);
});
} else {
throw Exception('Failed to load post');
}
}
@override
void initState() {
super.initState();
fetchPost();
}
@override
Widget build(BuildContext context) {
return Center(
child: post == null
? CircularProgressIndicator()
: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Title: ${post!['title']}',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text('Body: ${post!['body']}'),
],
),
),
);
}
}
OUTPUT:
9b) Display the fetched data in a meaningful way in the UI.
9b
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(MyApp());
}
if (response.statusCode == 200) {
setState(() {
post = json.decode(response.body);
});
} else {
throw Exception('Failed to load post');
}
}
@override
void initState() {
super.initState();
fetchPost();
}
@override
Widget build(BuildContext context) {
return Center(
child: post == null
? CircularProgressIndicator()
: Padding(
padding: const EdgeInsets.all(16.0),
child: Card(
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Author ID: ${post!['userId']}',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.grey[700]),
),
SizedBox(height: 10),
Text(
'Title: ${post!['title']}',
style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text(
'Body:',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
),
SizedBox(height: 5),
Text(
post!['body'],
style: TextStyle(fontSize: 16),
),
],
),
),
),
),
);
}
}
OUTPUT:
void _changeText() {
setState(() {
buttonText = "Pressed!";
});
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _changeText,
child: Text(buttonText),
);
}
}
import 'package:flutter/material.dart';
void _incrementCounter() {
setState(() {
_counter++; // Intentional bug: Incrementing without any condition
});
}
void _decrementCounter() {
setState(() {
_counter--; // Intentional bug: Decrementing without validation
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Debugging Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Button pressed this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment'),
),
ElevatedButton(
onPressed: _decrementCounter,
child: Text('Decrement'),
),
ElevatedButton(
onPressed: () {
// Intentional bug: Dividing by zero
int result = _counter ~/ 0;
print('Result: $result'); // This will cause an exception
},
child: Text('Cause Error'),
),
],
),
),
);
}
}