Flutter Mobile App Development (1)
Flutter Mobile App Development (1)
(Flutter Framework)
Table of Contents
Dart Programming Language ........................................................................................................ 5
Simple Hello World App ...................................................................................................................... 5
Passing arguments through console ................................................................................................... 5
Variables ............................................................................................................................................. 5
Variable creation and initialization. ................................................................................................ 5
Changing value of variable. ............................................................................................................. 5
We use Object data type, we want to change data type of variable.............................................. 5
Explicit data types ........................................................................................................................... 6
Nullable type ................................................................................................................................... 6
Late variables .................................................................................................................................. 6
Final and Const ................................................................................................................................ 6
Constant .......................................................................................................................................... 7
Variable examples ........................................................................................................................... 7
Conditional expressions: ..................................................................................................................... 7
condition ? expr1 : expr2 ................................................................................................................ 7
expr1 ?? expr2................................................................................................................................. 8
Comments: .......................................................................................................................................... 8
Builtin-Types: ...................................................................................................................................... 8
Strings: ................................................................................................................................................ 8
String concatenation example: ....................................................................................................... 8
Multiline string: ............................................................................................................................... 8
Records ............................................................................................................................................... 9
Lists ................................................................................................................................................... 11
List of Records: .............................................................................................................................. 11
Sets .................................................................................................................................................... 11
Maps ................................................................................................................................................. 12
Objects in Dart resembling javascript objects .................................................................................. 14
List of map objects ............................................................................................................................ 14
Spread operators .............................................................................................................................. 14
Control-flow operators ..................................................................................................................... 15
Patterns ............................................................................................................................................. 16
Variable assignment.......................................................................................................................... 16
Switch statements and expressions.................................................................................................. 17
For and for-in loops........................................................................................................................... 18
Functions:.......................................................................................................................................... 18
Named parameters ....................................................................................................................... 19
Optional positional parameters .................................................................................................... 20
The main() function....................................................................................................................... 20
Functions as first-class objects...................................................................................................... 21
Anonymous functions ................................................................................................................... 21
Arrow notation:............................................................................................................................. 22
typdef functions ............................................................................................................................ 23
Error handling. .................................................................................................................................. 23
Classes ............................................................................................................................................... 24
Simple class example .................................................................................................................... 24
No argument constructor ............................................................................................................. 24
One argument generative constructor ......................................................................................... 24
Two argument generative constructor ......................................................................................... 25
Another example of two argument constructor........................................................................... 25
Calling a constructor from another constructor within same class. ............................................. 26
Named constructors...................................................................................................................... 26
Named arguments in a constructor. ............................................................................................. 27
Immutable objects ........................................................................................................................ 27
Optional arguments to a constructor ........................................................................................... 28
Array of objects ............................................................................................................................. 28
Printing elements in an array ........................................................................................................ 29
Looping through array of objects:................................................................................................. 30
Use continue to skip to the next loop iteration: ...................................................................... 30
Inheritance example. .................................................................................................................... 30
Using parent class constructor in child class................................................................................. 31
Calling named argument constructor from Child class of Parent class ........................................ 31
Flutter widgets........................................................................................................................... 32
runApp() function.............................................................................................................................. 33
MaterialApp Widget: ........................................................................................................................ 36
Scaffold Widget: ................................................................................................................................ 38
MaterialApp and Material Widget .................................................................................................... 40
StatelessWidget ................................................................................................................................ 43
Row widget. ...................................................................................................................................... 47
StatefulWidget .................................................................................................................................. 70
Example: Display message in Text field on button click ............................................................... 70
Example: A counter application .................................................................................................... 72
Example: Two counters ................................................................................................................. 74
Example: Two counters and their sum. ........................................................................................ 76
Example: Introducing separate widgets for counter increment and counter display: ................. 79
Example to take user input using onChanged method and display as Text field ......................... 81
Assigning value of one TextField to other on button click ............................................................ 83
Real-time update of one TextField through other ........................................................................ 84
Example of two TextFields using TextEditingController class and display with button ............... 85
An input form example ................................................................................................................. 87
Shopping Cart with single item: ........................................................................................................ 90
A shopping cart with multiple Items ................................................................................................. 93
Creating a layout ............................................................................................................................... 96
Creating a ListView.......................................................................................................................... 102
Creating a horizontal ListView ........................................................................................................ 103
Creating a Grid List .......................................................................................................................... 105
Create lists with different types of items........................................................................................ 107
List with spaced items ..................................................................................................................... 110
Work with long lists: ....................................................................................................................... 112
Theme based styling: ...................................................................................................................... 114
Add interactivity to our app ............................................................................................................ 122
Material Components .............................................................................................................. 122
Drag and Drop ................................................................................................................................. 122
Input & Forms ................................................................................................................................. 122
Create and style a text field: ....................................................................................................... 122
Retrieve the value of a text field ................................................................................................. 123
Handle changes to a text field .................................................................................................... 126
Manage focus in text fields ......................................................................................................... 127
Build a form with validation ........................................................................................................ 129
Navigation and Routing................................................................................................................... 131
Working with Tabs: ..................................................................................................................... 131
Navigate to new screen and back: .............................................................................................. 132
Navigation with CupertinoPageRoute ........................................................................................ 134
Send a string to a new screen ..................................................................................................... 135
Send a string to new screen using RouteSettings ....................................................................... 137
Send data shown in a list to a new screen .................................................................................. 138
Send data shown in a list to a new screen using RouteSettings ................................................. 141
Return data from a screen .......................................................................................................... 142
Add a drawer to a screen ............................................................................................................ 145
Create a login page in flutter ...................................................................................................... 148
Connecting Flutter with Firestore ............................................................................................. 151
Write and read document from Firestore database ....................................................................... 151
Custom objects ........................................................................................................................... 157
Update a document ........................................................................................................................ 161
Server Timestamp ....................................................................................................................... 161
Update elements in an array ...................................................................................................... 164
Increment a numeric value ......................................................................................................... 164
Delete fields .................................................................................................................................... 165
Get multiple documents from a collection ..................................................................................... 168
Connecting Flutter with local SQLite Database .......................................................................... 173
Flutter shared preferences ....................................................................................................... 177
Connecting with PHP and MySQL........................................................ Error! Bookmark not defined.
Connecting with PHP and making updates in MySQL using Flutter ............................................... 182
Communicate with WebSockets ............................................................................................... 200
Handling Camera in Flutter ....................................................................................................... 201
GPS tracking in Flutter.............................................................................................................. 204
Dart Programming Language
To pass the parameters to the above application using console, run the following command in
console:
Variables
Variable creation and initialization.
var name = 'Bob';
print(name);
Nullable type
String? name1; // Nullable type. Can be `null` or string.
print(name1); // null
// print(name2); // error
Late variables
When you mark a variable as late but initialize it at its declaration, then the initializer runs the first
time the variable is used. This lazy initialization is handy in a couple of cases:
You're initializing an instance variable, and its initializer needs access to this.
void main() {
description = 'Feijoada!';
print(description);
}
void main() {
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
print(name);
print(nickname);
Constant
void main() {
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere
}
Variable examples
void main() {
var name = 'Voyager I';
var year = 1977;
var antennaDiameter = 3.7;
var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune'];
var image = {
'tags': ['saturn'],
'url': '//path/to/saturn.jpg'
};
print(name);
print(year);
print(antennaDiameter);
print(flybyObjects);
print(image);
Conditional expressions:
condition ? expr1 : expr2
If condition is true, evaluates expr1 (and returns its value); otherwise,
evaluates and returns the value of expr2.
void main()
{
var isPublic = 'public';
var visibility = isPublic=='public' ? 'public' : 'private';
print(visibility);
}
expr1 ?? expr2
If expr1 is non-null, returns its value; otherwise, evaluates and returns the
value of expr2.
void main()
{
var var1 = null; // or simply write var var1; this defaults to null
var var2 = 10;
Comments:
// single line , /* multi line */, /// for documentation.
Builtin-Types:
Numbers, Strings, Booleans.
Strings:
String concatenation example:
void main() {
var s1 = 'String '
'concatenation'
" works even over line breaks.";
print(s1);
}
Multiline string:
void main() {
var s1 = '''
You can create
multi-line strings like this one.
''';
print(s1);
}
Records
Records are an anonymous, immutable, aggregate type. Like other collection types, they let
you bundle multiple objects into a single object. Unlike other collection types, records are
fixed-sized, heterogeneous, and typed.
Records are real values; you can store them in variables, nest them, pass them to and from
functions, and store them in data structures such as lists, maps, and sets.
Example:
void main() {
print(record);
print(record.a);
print(record.b);
dart
Example:
Here ‘first’, “hello”, ‘last’ are positional fields, and others are named.
void main() {
In a record type annotation, named fields go inside a curly brace-delimited section of type-
and-name pairs, after all positional fields. In a record expression, the names go before each
field value with a colon after:
The names of named fields in a record type are part of the record's type definition, or
its shape. Two records with named fields with different names have different types:
In a record type annotation, you can also name the positional fields, but these names are
purely for documentation and don't affect the record's type:
Example
Example
Lists
Perhaps the most common collection in nearly every programming language is the array, or ordered
group of objects. In Dart, arrays are List objects, so most people just call them lists.
Dart list literals are denoted by a comma separated list of expressions or values, enclosed in square
brackets ([]). Here's a simple Dart list:
void main() {
print(list[0]);
}
List of Records:
void main() {
Sets
#
A set in Dart is an unordered collection of unique items. Dart support for sets is provided by set
literals and the Set type.
void main() {
print(halogens.elementAt(0));
print(halogens.elementAt(1));
To create an empty set, use {} preceded by a type argument, or assign {} to a variable of type Set:
void main() {
void main() {
Maps
In general, a map is an object that associates keys and values. Both keys and values can be any type
of object. Each key occurs only once, but you can use the same value multiple times. Dart support
for maps is provided by map literals and the Map type.
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
Add a new key-value pair to an existing map using the subscript assignment operator ([]=):
Dart
Dart
void main() {
void main() {
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
Dart
void main() {
Add a new key-value pair to an existing map using the subscript assignment operator ([]=):
Dart
print(myObject1);
];
Spread operators
Dart supports the spread operator (...) and the null-aware spread operator (...?) in list, map, and set
literals. Spread operators provide a concise way to insert multiple values into a collection.
For example, you can use the spread operator (...) to insert all the values of a list into another list:
void main() {
void main() {
Control-flow operators
Dart offers collection if and collection for use in list, map, and set literals. You can use these
operators to build collections using conditionals (if) and repetition (for).
Here's an example of using collection if to create a list with three or four items in it:
void main() {
void main() {
print(nav);
}
Here's an example of using collection for to manipulate the items of a list before adding them to
another list:
void main() {
Patterns
Destructuring
When an object and pattern match, the pattern can then access the object's data and extract it in
parts. In other words, the pattern destructures the object:
void main() {
Variable assignment
A variable assignment pattern falls on the left side of an assignment. First, it destructures the
matched object. Then it assigns the values to existing variables, instead of binding new ones.
Use a variable assignment pattern to swap the values of two variables without declaring a third
temporary one:
void main() {
The values that a pattern destructures in a case become local variables. Their scope is only within
the body of that case.
void main() {
int obj = 3;
const first = 2;
const last = 4;
switch (obj) {
// Matches if 1 == obj.
case 1:
print('one');
default:
}
Guard clauses evaluate an arbitrary conditon as part of a case, without exiting the switch if the
condition is false (like using an if statement in the case body would cause).
void main() {
var pair=(20,10);
switch (pair) {
case (int a, int b):
if (a > b) print('First element greater');
// If false, prints nothing and exits the switch.
case (int a, int b) when a > b:
// If false, prints nothing but proceeds to next case.
print('First element greater');
case (int a, int b):
print('First element not greater');
}
}
This example uses object destructuring in a for-in loop to destructure the MapEntry objects that
a <Map>.entries call returns:
void main() {
Map<String, int> hist = {
'a': 23,
'b': 100,
};
Functions:
bool isNoble(int atomicNumber) {
return true;
}
Although Effective Dart recommends type annotations for public APIs, the function still works if you
omit the types:
isNoble(int atomicNumber) {
return true;
}
For functions that contain just one expression, you can use a shorthand syntax:
Named parameters
Named parameters are optional unless they're explicitly marked as required.
When defining a function, use {param1, param2, …} to specify named parameters. If you don't
provide a default value or mark a named parameter as required, their types must be nullable as their
default value will be null:
void main() {
print("Hello world");
print("$bold $hidden");
To define a default value for a named parameter besides null, use = to specify a default value. The
specified value must be a compile-time constant. For example:
void main() {
print("Hello world");
enableFlags(hidden: false);
}
print("$bold $hidden");
}
Optional positional parameters
Wrapping a set of function parameters in [] marks them as optional positional parameters. If you
don't provide a default value, their types must be nullable as their default value will be null:
void main() {
print("Hello world");
To define a default value for an optional positional parameter besides null, use = to specify a default
value. The specified value must be a compile-time constant. For example:
void main() {
say("Ali", "hello"); // calling with two arguments
}
The file dartapp.dart is in the bin folder. Run the app like this: dart run dartapp.dart 1
test
void main() {
void main() {
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
print(loudify("hello"));
}
Anonymous functions
Most functions are named, such as main() or printElement(). You can also create a
nameless function called an anonymous function, or sometimes a lambda or closure.
You might assign an anonymous function to a variable so that, for example, you can
add or remove it from a collection.
The following example defines an anonymous function with an untyped parameter, item,
and passes it to the map function. The function, invoked for each item in the list, converts
each string to uppercase. Then in the anonymous function passed to forEach, each
converted string is printed out alongside its length.
void main() {
(item)
{
return item.toUpperCase();
}
);
print(result);
result.forEach((item) {
print('$item: ${item.length}');
});
/*
// COMBINED FORM
list.map((item) {
return item.toUpperCase();
}).forEach((item) {
print('$item: ${item.length}');
});
*/
Arrow notation:
Example:
void main() {
Example:
void main() {
typdef functions
// 1. Define a typedef for a function that takes two numbers and returns their
sum
typedef SumFunction = int Function(int a, int b);
void main() {
// 3. Use the SumFunction type to declare a variable and assign the add
function
SumFunction sum = add;
// 4. Call the function using the variable with the SumFunction type
int result = sum(5, 3); // result will be 8
Error handling.
void main() {
misbehave();
void misbehave() {
try {
dynamic foo = true;
print(foo++);
} catch (e) {
print(e);
}
}
Classes
Simple class example
class Point {
double? x; // Declare instance variable x, initially null.
double? y; // Declare y, initially null.
}
void main() {
var point = Point();
point.x = 4; // Use the setter method for x.
print(point.x);
No argument constructor
class Car {
Car() {
print("no argument constructor called");
}
/*
//OR
Car();
*/
void main() {
Car c = Car();
class Point {
final double x;
final double y;
void main() {
Point p1 = Point(10, 20);
print("x: ${p1.x}, y: ${p1.y}");
Point p2 = Point(5, 10);
print(p2.distanceTo(p1));
}
class Car {
String? name;
int? age;
Car(name, age){
this.name = '$name' ' Ali';
this.age = age + 30;
}
}
void main() {
Car c = Car("Shahid", 45);
print('${c.name} ${c.age}');
Point(int a, int b) {
x = a;
y = b;
}
void main() {
var point1 = Point(3, 4);
var point2 = Point.fromOrigin();
print('${point1.x} ${point1.y}');
print('${point2.x} ${point2.y}');
}
Named constructors
class User {
User.none();
User.withId(this.id);
User.withName(this.name);
User.withidname(this.id, this.name);
}
void main() {
print('${user1.id} ${user1.name}');
print('${user2.id} ${user2.name}');
print('${user3.id} ${user3.name}');
print('${user4.id} ${user4.name}');
void main(){
Person person1 = Person(age: 25); // Specify age first, name is unknown
print('${person1.age} ${person1.name}');
Person person2 = Person(name: "Bob", age: 42); // Specify both in any order
print('${person2.age} ${person2.name}');
Immutable objects
By adding const, the created object is immutable, its content can’t be changed.
class Teacher {
const Teacher(this.name);
final String name;
}
void main() {
var teacher = const Teacher("Osman");
print(teacher.name);
void main() {
// Create a Person with name and age
var person1 = Person('Alice', age: 30);
print('${person1.name} ${person1.age}');
Array of objects
class Student {
String name;
int age;
// Constructor
Student(this.name, this.age);
void main() {
String name;
int age;
// Constructor
Student(this.name, this.age);
}
Looping through array of objects:
class Candidate {
final String name;
final int yearsExperience;
Candidate(this.name, this.yearsExperience);
void interview() {
print("$name is being interviewed...");
// Simulate the interview process
print("$name: Interview went well!");
}
}
void main() {
// List of candidates
List<Candidate> candidates = [
Candidate("Alice", 6),
Candidate("Bob", 3),
Candidate("Charlie", 8),
Candidate("David", 4),
];
Inheritance example.
class ParentClass {
void myfunction() {
print("This is parent class function");
}
}
class ChildClass extends ParentClass {
@override
void myfunction() {
super.myfunction();
print("This is child class function");
}
}
void main() {
ChildClass c = ChildClass();
c.myfunction();
}
class Person {
String? name;
int? age;
Person(this.name, this.age);
void main() {
Student student = Student("ABC123");
print(student.name); // Output: Ali
print(student.age); // Output: 34
print(student.regno); // Output: ABC123
}
void main(){
Student s = Student(id: "334", name:"Jamal", age:34);
print('${s.id} ${s.name} ${s.age}');
}
Flutter widgets
In flutter, widgets act like tags in html containing information/data. Each widget is
represented by class. Widgets call other widgets via class composition principles.
Example:
Here the Text wizard is acting as root widget.
NOTE: When MaterialApp widget is used, we don’t need to specify the text direction.
import 'package:flutter/material.dart';
void main() {
runApp(
const Text(
"hello world",
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 60,
color: Color.fromARGB(255, 31, 136, 248),
),
),
);
}
OUTPUT:
Why use const here?
The const keyword used with Text serves two main purposes:
1. Widget Tree Optimization: When you use const with a widget, it tells Flutter that the
widget and its sub-tree (children) are unlikely to change throughout the lifetime of
your app. This allows Flutter to perform some optimizations, such as caching the
widget's configuration and avoiding unnecessary rebuilds. This is particularly
beneficial for widgets that are expensive to create or render.
2. Immutability: Using const with a widget enforces immutability. This means that once
the widget is created, its state cannot be changed. This aligns well with the concept
of widgets in Flutter, which are supposed to represent a declarative UI state.
Key Points:
• The const keyword is most effective for widgets that are stateless and don't require
dynamic updates.
• For widgets that need to update based on user interaction or data changes,
using const might not be suitable. In such cases, you'd likely use
the StatefulWidget approach.
In summary:
Using const with MaterialApp in this example helps Flutter optimize the widget tree and
enforces immutability, which aligns with the principles of building UIs in Flutter.
Example:
To center align the Text, we use Center widget:
In this example, the widget tree consists of two widgets, the Center widget and its child, the
Text widget. The framework forces the root widget to cover the screen, which means the
text “Hello, world” ends up centered on screen.
import 'package:flutter/material.dart';
void main() {
runApp(
const Center(
child: Text(
'Hello, world!',
textDirection: TextDirection.ltr,
),
),
);
}
Output:
MaterialApp Widget:
Many Material Design widgets need to be inside of a MaterialApp to display properly, in
order to inherit theme data. Therefore, run the application with a MaterialApp.
In Flutter, MaterialApp represents a widget that implements the basic material design visual
layout structure. It's typically used as the root widget of a Flutter application. Here's what it
provides:
1. Material Design Components: MaterialApp provides the basic material design
components such as Scaffold, AppBar, Drawer, BottomNavigationBar, SnackBar, and
more. These components follow the Material Design guidelines for visual
appearance and behavior.
2. Text Style Warning: If your app lacks a Material ancestor for text widgets, MaterialApp
automatically applies an ugly red/yellow text style. This serves as a warning to developers
that they haven’t defined a default text style. Typically, the app’s Scaffold defines the text
style for the entire UI.
Example:
In this example, MaterialApp widget is made the root widget, and its ‘home’ property is
invoked, in which Text wizard is passed.
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
home: Text("Hello world"),
));
}
Output:
Scaffold Widget:
While MaterialApp provides the overall structure and theme for a Flutter app, the Scaffold
widget serves as a layout structure for individual screens or "pages" within the app. Here's
what the Scaffold widget provides:
1. App Bar: Scaffold allows you to easily add an app bar at the top of the screen using
the appBar property. The app bar typically contains a title, leading and/or trailing
actions, and may also include other widgets like tabs or a search bar.
2. Body Content: Scaffold's body property is where you place the main content of the
screen. This can be any widget or combination of widgets, such as text, images, lists,
grids, or custom widgets.
3. Navigation Drawer: If your app uses a side navigation drawer, Scaffold provides the
drawer property to easily add one to your screen. The drawer typically contains
navigation links or settings options.
4. Bottom Navigation Bar: For apps with multiple screens or sections, Scaffold allows
you to include a bottom navigation bar using the bottomNavigationBar property.
This allows users to switch between different sections of the app.
5. Floating Action Button: Scaffold provides the floatingActionButton property to add
a floating action button (FAB) to the screen. FABs are typically used for primary or
frequently-used actions, such as adding a new item or starting a new task.
6. Snackbar: Scaffold includes methods for displaying snackbars, which are lightweight
messages that appear at the bottom of the screen. This can be useful for showing
brief feedback or notifications to the user.
Overall, while MaterialApp provides the overall structure and theme for the entire app,
Scaffold provides a consistent layout structure for individual screens, making it easier to
build and organize the UI of your Flutter app.
Example
See how the Point No. 2 of MaterialApp is addressed here when we used Scaffold widget.
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
home: Scaffold(
body: Center(
child: Text("hello world")
)
)
));
}
MaterialApp and Material Widget
MaterialApp:
• Function: A widget that serves as the foundation for building apps that
follow Google's Material Design guidelines.
• Purpose: Provides a starting point for your app by configuring essential
elements like:
o Theme: Defines the overall look and feel of your app (colors,
fonts, etc.)
o Routing: Manages navigation between different screens in your
app.
o Localization: Enables support for different languages.
o Home: Sets the initial screen displayed when the app launches.
• Placement: Placed at the root of your app's widget tree. There should
typically be only one MaterialApp widget in your app.
Material:
• Function: A basic widget used for creating UI elements that adhere to
Material Design principles.
• Purpose: Defines properties related to the visual appearance and
behavior of individual UI components, such as:
o Elevation: Creates a shadow effect for a 3D-like feel.
o Shape: Defines the shape of the UI element (rounded corners,
etc.).
o Clipping: Controls how the widget's content is displayed within its
bounds.
• Placement: Used throughout your app's widget tree to build various UI
components like buttons, cards, app bars, etc.
Example:
Code snippet
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Scaffold( // Another Material widget for app structure
appBar: AppBar(
title: const Text('My Flutter App'), // Text widget (not directly
from Material)
backgroundColor: Colors.blue, // Defined in ThemeData (part of
MaterialApp)
),
body: Center(
child: Material( // Used for specific UI element
elevation: 4.0, // Material property
shape: RoundedRectangleBorder(borderRadius:
BorderRadius.circular(10.0)),
child: const Text('This is a Material widget'),
),
),
),
));
}
OUTPUT:
In this example:
• MaterialApp configures the app's theme (including the blue color) and
sets the Scaffold as the home screen.
• Scaffold is another Material widget that provides a basic layout structure
for most screens in a Material Design app.
• AppBar and Text are not directly from Material, but they can be styled
within the MaterialApp's theme.
• The Center widget positions the content in the center.
• Finally, the Material widget is used to create a specific button-like
element with elevation and rounded corners.
StatelessWidget
When writing an app, you’ll commonly author new widgets that are subclasses of either
StatelessWidget or StatefulWidget, depending on whether your widget manages any state.
A widget’s main job is to implement a build() function, which describes the widget in terms
of other, lower-level widgets.
Stateless widgets receive arguments from their parent widget, which they store
in final member variables. When a widget is asked to build(), it uses these stored values to
derive new arguments for the widgets it creates.
In Flutter, a StatelessWidget is a fundamental building block for user interfaces (UIs). It
represents a part of your app's UI that remains static throughout its lifetime. Here's a
breakdown of what it means:
Stateless:
• The key characteristic of a StatelessWidget is that it doesn't hold any internal state
that can change. This means its appearance is entirely determined by the
information passed to it when it's created, and it won't update dynamically on its
own.
Widget:
• Everything in Flutter is a widget. Widgets are like building blocks that you assemble
to create your app's UI. A StatelessWidget is a specific type of widget that specializes
in presenting a fixed UI element.
Building UIs:
• StatelessWidgets are ideal for UI elements whose appearance is based on a set of
properties or data provided to them when they are built. They describe how a part
of the UI should look at a given point in time.
Benefits:
• Simpler to create and understand compared to StatefulWidgets (which manage
state).
• More lightweight and efficient for static UI elements.
• Easier to reason about and test due to their predictable behavior.
Common Use Cases:
• Displaying text, icons, images, or simple layouts.
• Building UI elements that only depend on the data passed to them (e.g., displaying a
product name from a list).
• Creating reusable UI components that present a fixed appearance.
In this example, GreetingText is a StatelessWidget that displays the text "Hello World!" with
a specific font size and color. Its appearance remains constant, making it a suitable
candidate for a StatelessWidget.
When to Use StatelessWidgets:
• If a UI element doesn't need to change its appearance based on user interaction or
external data updates, use a StatelessWidget.
• It's a great choice for building simple and reusable UI components.
• For more complex UIs with dynamic behavior, consider using StatefulWidgets.
NOTE:
• Keys are unique identifiers for widgets in Flutter's widget tree.
• They help Flutter track changes to the UI and optimize performance.
Example.
In this example, GreetingText() is a custom defined widget.
• Naming Convention: In Flutter, custom widgets typically start with a capital letter to
differentiate them from built-in widgets provided by the Flutter framework (which
are usually in lowercase).
• The context object serves as a handle that pinpoints a widget's exact position within
the hierarchical structure of widgets that make up your app's UI (User Interface).
• Imagine your app's UI as an inverted tree, with MaterialApp at the root and all other
widgets branching out from it. Context tells a widget exactly where it sits on that
tree.
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
home: GreetingText(),
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Greeting'), // Add a title to the app bar
),
body: const Center( // Center the text within the body
child: Text(
'Hello World!',
style: TextStyle(
fontSize: 32.0,
color: Colors.blue,
),
),
),
);
}
}
Here's a detailed explanation of the code, focusing on the constructor const GreetingText
({super.key});:
1. Constructor Declaration:
• const GreetingText ({super.key}): This is the declaration of a constructor for
the GreetingText class. It has some distinct features:
o const Prefix: The const keyword indicates that this constructor creates an
immutable instance of the class. This means that once a GreetingText object
is created, its properties cannot be changed.
o Curly Braces: The curly braces {} enclose a single optional
parameter, super.key.
2. Forwarding Key to Superclass:
• super.key: This part of the constructor forwards a special parameter named key to
the superclass constructor. In this case, the superclass
is StatelessWidget (since GreetingText extends StatelessWidget).
• Key Importance: Keys are unique identifiers assigned to widgets in Flutter. They play
a crucial role in helping the framework efficiently manage the widget tree and
determine which widgets need to be rebuilt when the UI state changes.
• Forwarding Benefits: By forwarding the key to the superclass, GreetingText inherits
the key management capabilities of StatelessWidget, ensuring proper handling of its
identity and updates within the widget tree.
3. No Explicit Argument:
• You might be wondering why there's no explicit argument being passed to super.key.
This is because key is an optional parameter that can be specified when creating
a GreetingText widget. If a key is not provided, it will default to null.
4. Optional Parameter Syntax:
• The curly braces {} around super.key signify that it's an optional named parameter.
However, if you don't provide a key, it's perfectly valid to create it without any
arguments:
In summary:
• The constructor const GreetingText ({super.key}); allows for the creation of
immutable GreetingText widgets with optional keys.
• It forwards the key parameter to the superclass for proper widget management.
• Understanding this syntax and the role of keys is essential for effective Flutter
development.
OUTPUT:
Row widget.
A widget that displays its children in a horizontal array.
In Flutter, the Row widget is a fundamental layout widget used to arrange its child widgets
horizontally in a single row. It's a core building block for creating linear UI elements like:
• Navigation bars with buttons or icons displayed side-by-side.
• Forms with labels and input fields aligned horizontally.
• Layouts with multiple images or text elements displayed in a row.
Key Characteristics:
• Horizontal Arrangement: Child widgets are placed from left to right within the
available space.
• Fixed Size: The Row widget itself doesn't have an intrinsic size. Its size is determined
by the combined size of its child widgets and the available space from the parent
widget.
• Multiple Children: A Row can hold multiple child widgets, allowing you to create
complex horizontal layouts.
Customizing Layout:
While child widgets are placed horizontally by default, you can control their alignment and
distribution within the Row using two properties:
1. MainAxisAlignment: This property determines how the child widgets are positioned
along the main axis (horizontal in this case). Options include:
o MainAxisAlignment.start (default): Aligns child widgets to the left edge of the
Row.
o MainAxisAlignment.center: Centers child widgets horizontally within the
Row.
o MainAxisAlignment.end: Aligns child widgets to the right edge of the Row.
o MainAxisAlignment.spaceBetween: Distributes child widgets evenly with
spaces in between, except for the first and last ones, which are positioned at
the edges.
o MainAxisAlignment.spaceAround: Distributes child widgets evenly with
spaces around them.
o MainAxisAlignment.spaceEvenly: Distributes child widgets with equal space
between them, including the first and last ones.
2. CrossAxisAlignment: This property controls how the child widgets are positioned
along the cross-axis (vertically in this case). Options include:
o CrossAxisAlignment.start (default): Aligns the top edges of child widgets.
o CrossAxisAlignment.center: Centers child widgets vertically within the Row.
o CrossAxisAlignment.end: Aligns the bottom edges of child widgets.
o CrossAxisAlignment.stretch (stretches child widgets to fill the vertical space
of the Row).
Example:
Simple example of Row widget.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Row Example'),
),
body: const Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Item 1', style: TextStyle(color: Colors.black)),
Text('Item 2', style: TextStyle(color: Colors.black)),
Text('Item 3', style: TextStyle(color: Colors.black)),
],
),
),
),
);
}
}
Output:
Making Child Widgets Flexible:
If a Row has more child widgets than can fit comfortably in the available space, they might
overflow. To handle this, you can wrap child widgets with the Expanded widget. This allows
child widgets to flex and share the available horizontal space proportionally.
If the non-flexible contents of the row (those that are not wrapped
in Expanded or Flexible widgets) are together wider than the row itself, then the row is said
to have overflowed. When a row overflows, the row does not have any remaining space to
share between its Expanded and Flexible children. The row reports this by drawing a yellow
and black striped warning box on the edge that is overflowing. If there is room on the
outside of the row, the amount of overflow is printed in red lettering.
Example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Row Example'),
),
body: const Center(
child: Row(
children: <Widget>[
FlutterLogo(),
Text(
"Flutter's hot reload helps you quickly and easily
experiment, build UIs, add features, and fix bug faster. Experience sub-second
reload times, without losing state, on emulators, simulators, and hardware for
iOS and Android."),
Icon(Icons.sentiment_very_satisfied),
],
),
),
),
);
}
}
Output:
Example:
Controlling text direction in a row:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Row Example'),
),
body: const Center(
child: Row(
textDirection: TextDirection.rtl,
children: <Widget>[
FlutterLogo(),
Expanded(
child: Text(
"Flutter's hot reload helps you quickly and easily
experiment, build UIs, add features, and fix bug faster. Experience sub-second
reload times, without losing state, on emulators, simulators, and hardware for
iOS and Android."),
),
Icon(Icons.sentiment_very_satisfied),
],
),
),
),
);
}
}
Output:
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Row Example'),
),
body: const Center(
child: Row(
children: <Widget>[
Expanded(
child: Text('Deliver features faster',
textAlign: TextAlign.center),
),
Expanded(
child: Text('Craft beautiful UIs', textAlign:
TextAlign.center),
),
Expanded(
child: FittedBox(
child: FlutterLogo(),
),
),
],
),
),
),
);
}
}
Output:
Example of mainAxisAlignment using Text widget
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Row Example'),
),
body: const Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text("ITEM 1"),
Text("ITEM 2"),
Text("ITEM 3"),
],
),
),
),
);
}
}
Output:
Example of mainAxisAlignment and crossAxisAlignment using SizedBox and Text widget:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Row Example'),
),
body: const Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 20.0, // Approach 2: Set height of SizedBox
child: Text('ITEM 1'),
),
SizedBox(
height: 140.0, // Approach 2: Set height of SizedBox
child: Text('ITEM 2'),
),
SizedBox(
height: 20.0, // Approach 2: Set height of SizedBox
child: Text('ITEM 3'),
)
],
),
),
),
);
}
}
Output:
Example of mainAxisAlignment and crossAxisAlignment using Container Widget in Row
NOTE: If the heights of your container widgets are the same as the available space in the
Row, you will see no difference in the crossAxisAlignment behavior.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Row Example'),
),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 50,
height: 30,
color: Colors.blue,
),
const SizedBox(width: 20),
Container(
width: 50,
height: 70,
color: Colors.green,
),
const SizedBox(width: 20),
Container(
width: 50,
height: 50,
color: Colors.orange,
),
],
),
),
),
);
}
}
Output:
Column widget example
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Row Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 150,
height: 30,
color: Colors.blue,
),
const SizedBox(width: 20),
Container(
width: 80,
height: 70,
color: Colors.green,
),
const SizedBox(width: 20),
Container(
width: 40,
height: 50,
color: Colors.orange,
),
],
),
),
),
);
}
}
Example of combining different widgets
• The context object serves as a handle that pinpoints a widget's exact position within
the hierarchical structure of widgets that make up your app's UI (User Interface).
• Imagine your app's UI as an inverted tree, with MaterialApp at the root and all other
widgets branching out from it. Context tells a widget exactly where it sits on that
tree.
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
title: 'My app', // used by the OS task switcher
home: SafeArea(
child: MyScaffold(),
),
),
);
}
@override
Widget build(BuildContext context) {
// Material is a conceptual piece
// of paper on which the UI appears.
return Material(
// Column is a vertical, linear layout.
child: Column(
children: [
MyAppBar(
title: Text(
'Example title',
style: Theme.of(context) //
.primaryTextTheme
.titleLarge,
),
),
const Expanded(
child: Center(
child: Text('Hello, world!'),
),
),
],
),
);
}
}
@override
Widget build(BuildContext context) {
return Container(
height: 56, // in logical pixels
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(color: Colors.blue[500]),
Output:
Example: Using the MaterialApp and Scaffold Widget with a button
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
title: 'Flutter Tutorial',
home: TutorialHome(),
),
);
}
@override
Widget build(BuildContext context) {
// Scaffold is a layout for
// the major Material Components.
return Scaffold(
appBar: AppBar(
leading: const IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null,
),
title: const Text('Example title'),
actions: const [
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
// body is the majority of the screen.
body: const Center(
child: Text('Hello, world!'),
),
floatingActionButton: const FloatingActionButton(
tooltip: 'Add', // used by assistive technologies
onPressed: null,
child: Icon(Icons.add),
),
);
}
}
Explanation:
Notice that widgets are passed as arguments to other widgets. The Scaffold widget takes
a number of different widgets as named arguments, each of which are placed in
the Scaffold layout in the appropriate place. Similarly, the AppBar widget lets you pass in
widgets for the leading widget, and the actions of the title widget. This pattern recurs
throughout the framework and is something you might consider when designing your own
widgets.
Example: Adding a simple button and its function:
import 'package:flutter/material.dart';
void main() {
runApp( MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("This is title"),
centerTitle: true,
backgroundColor: Colors.blue,
),
body: Center(
child: Text("This is body") ),
floatingActionButton: FloatingActionButton(
onPressed:() => showHelloWorld(),
child: Text('Click'),
),
)
));
}
void showHelloWorld() {
print("Hello, World!");
// You can replace the print statement with any code to display "Hello,
World!" on the screen.
}
Example: Add a simple button and print message using print function
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: MyButton(),
),
),
),
);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('MyButton was tapped!');
},
child: Container(
height: 50,
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.lightGreen[500],
),
child: const Center(
child: Text('Engage'),
),
),
);
}
}
Output:
The output will be shown in blue text of debug console.
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: MyButton(),
),
),
),
);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('MyButton was tapped!'),
backgroundColor: Colors.blue,
),
);
},
child: Container(
height: 50,
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.lightGreen[500],
),
child: const Center(
child: Text('Engage'),
),
),
);
}
}
The GestureDetector widget doesn’t have a visual representation but instead detects
gestures made by the user. When the user taps the Container, the GestureDetector calls
its onTap() callback, in this case printing a message to the console. You can
use GestureDetector to detect a variety of input gestures, including taps, drags, and scales.
Output:
The blue band at below of screen is output
StatefulWidget
StatefulWidgets are special widgets that know how to generate State objects, which are
then used to hold state.
Example: Display message in Text field on button click
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: Display(),
),
),
),
);
}
class Display extends StatefulWidget {
const Display({super.key});
@override
State<Display> createState() => _DisplayState();
}
void _displayMessage() {
setState(() {
message = "Hello World"; // Update the message on button click
});
}
@override
Widget build(BuildContext context) {
return Row( // Modified to display the message
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _displayMessage, // Call the new function on button press
child: const Text('Display Message'), // Updated button text
),
const SizedBox(width: 16),
Text(message), // Display the message instead of the Display
],
);
}
}
Example: A counter application
import 'package:flutter/material.dart';
const Counter({super.key});
@override
State<Counter> createState() => _CounterState();
}
void _increment() {
setState(() {
// This call to setState tells the Flutter framework
// that something has changed in this State, which
// causes it to rerun the build method below so that
// the display can reflect the updated values. If you
// change _counter without calling setState(), then
// the build method won't be called again, and so
// nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called,
// for instance, as done by the _increment method above.
// The Flutter framework has been optimized to make
// rerunning build methods fast, so that you can just
// rebuild anything that needs updating rather than
// having to individually changes instances of widgets.
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _increment,
child: const Text('Increment'),
),
const SizedBox(width: 16),
Text('Count: $_counter'),
],
);
}
}
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: Counter(),
),
),
),
);
}
Output:
Example: Two counters
import 'package:flutter/material.dart';
const Counter({super.key});
@override
State<Counter> createState() => _CounterState();
}
void _increment1() {
setState(() {
_counter1++;
});
}
void _increment2() {
setState(() {
_counter2++;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _increment1,
child: const Text('Increment1'),
),
const SizedBox(width: 16),
Text('Count1: $_counter1'),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _increment2,
child: const Text('Increment'),
),
const SizedBox(width: 16),
Text('Count2: $_counter2'),
],
),
],
);
}
}
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: Counter(),
),
),
),
);
}
Output:
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: Counter(),
),
),
),
);
}
const Counter({super.key});
@override
State<Counter> createState() => _CounterState();
}
void _increment1() {
setState(() {
_counter1++;
});
}
void _increment2() {
setState(() {
_counter2++;
});
}
void _sumcounter() {
setState(() {
_sum = _counter1 + _counter2;
});
@override
Widget build(BuildContext context) {
return Column( // Use Column for vertical layout
mainAxisAlignment: MainAxisAlignment.center, // Center the content
vertically
children: <Widget>[
Row( // First row with a button and Text
mainAxisAlignment: MainAxisAlignment.center, // Center content in the
row
children: <Widget>[
ElevatedButton(
onPressed: _increment1,
child: const Text('Increment1'),
),
const SizedBox(width: 16), // Spacing between elements
Text('Count: $_counter1'),
],
),
const SizedBox(height: 16), // Spacing between rows
Row( // Second row with another button and Text
mainAxisAlignment: MainAxisAlignment.center, // Center content in the
row
children: <Widget>[
ElevatedButton(
onPressed: _increment2,
child: const Text('Increment2'),
),
const SizedBox(width: 16), // Spacing between elements
Text('Count: $_counter2'),
],
),
const SizedBox(height: 16), // Spacing between rows
Row( // Second row with another button and Text
mainAxisAlignment: MainAxisAlignment.center, // Center content in the
row
children: <Widget>[
ElevatedButton(
onPressed: _sumcounter,
child: const Text('Sum'),
),
const SizedBox(width: 16), // Spacing between elements
Text('Ans: $_sum'),
],
),
],
);
}
}
Output:
Example: Introducing separate widgets for counter increment and counter display:
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: Counter(),
),
),
),
);
}
@override
State<Counter> createState() => _CounterState();
}
void _increment() {
setState(() {
++_counter;
});
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CounterIncrementor(onPressed: _increment),
const SizedBox(width: 16),
CounterDisplay(count: _counter),
],
);
}
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
child: const Text('Increment'),
);
}
}
@override
Widget build(BuildContext context) {
return Text('Count: $count');
}
}
Output:
The output is same to the single counter app.
Example to take user input using onChanged method and display as Text field
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: InputDisplay(),
),
),
),
);
}
@override
State<InputDisplay> createState() => _InputDisplayState();
}
void _displayInput() {
setState(() {
message = userInput; // Update message with user input
});
}
@override
Widget build(BuildContext context) {
return Column( // Use Column for vertical layout
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField( // Text input field
onChanged: (value) => setState(() => userInput = value), // Update
userInput on change
decoration: const InputDecoration(
hintText: 'Enter your message', // Hint text for the user
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _displayInput, // Call the function to display input
child: const Text('Display Input'), // Updated button text
),
const SizedBox(height: 16),
Text(message), // Display the message
],
);
}
}
Output:
Assigning value of one TextField to other on button click
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
home: Scaffold(
body: Center(
child: InputDisplay(),
)
)
));
}
@override
State<InputDisplay> createState() => _InputDisplayState();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
onChanged: (value) => setState(() => userInput = value
),
decoration: const InputDecoration(
hintText: 'Enter your message'
),
),
() {
message = userInput;
message1 = userInput;
}
), child: Text("Press button")),
Text(message),
Text(message1),
TextField(
controller: TextEditingController(text: message),
decoration: const InputDecoration(
hintText: 'Enter your message'
),
),
],
);
}
void main() {
runApp(const MaterialApp(
home: Scaffold(
body: Center(
child: InputDisplay(),
)
)
));
}
@override
State<InputDisplay> createState() => _InputDisplayState();
}
TextField(
controller: TextEditingController(text: userInput.toUpperCase()),
Example of two TextFields using TextEditingController class and display with button
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// Controllers to store text from each box
final TextEditingController _textController1 = TextEditingController();
final TextEditingController _textController2 = TextEditingController();
String _displayText = ""; // Variable to store combined text
void _onPressed() {
// Combine text from controllers and update display text
setState(() {
_displayText = "${_textController1.text} - ${_textController2.text}";
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Text Input Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _textController1,
decoration: const InputDecoration(
hintText: 'Enter Text 1',
),
),
const SizedBox(height: 10),
TextField(
controller: _textController2,
decoration: const InputDecoration(
hintText: 'Enter Text 2',
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _onPressed,
child: const Text('Display Text'),
),
const SizedBox(height: 10),
Text(_displayText),
],
),
),
),
);
}
}
void main() {
runApp(const MaterialApp(
home: ResponsiveForm(),
));
}
@override
State<ResponsiveForm> createState() => _ResponsiveFormState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('User Information Form'),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(20.0),
child: LayoutBuilder(
builder: (context, constraints) {
return Row(
children: [
Expanded(
child: _buildForm(context),
),
],
);
},
),
),
);
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Form is submitted!'),
backgroundColor: Colors.blue,
),
);
}
}
Output:
void main() {
runApp(
MaterialApp(
home: Scaffold(
body: Center(
child: ShoppingListItem(
product: const Product(name: 'Chips'),
inCart: true,
onCartChanged: (product, inCart) {},
),
),
),
),
);
}
ShoppingListItem({
required this.product,
required this.inCart,
required this.onCartChanged,
}) : super(key: ObjectKey(product));
// The below two methods _getColor and _getTextStyle are related to styling
//
return inCart //
? Colors.black54
: Theme.of(context).primaryColor;
}
TextStyle? _getTextStyle(BuildContext context) {
if (!inCart) return null;
@override
Widget build(BuildContext context) {
return ListTile(
onTap: () {
onCartChanged(product, inCart);
},
leading: CircleAvatar(
backgroundColor: _getColor(context),
child: Text(product.name[0]),
),
title: Text(product.name, style: _getTextStyle(context)),
);
}
}
class Product {
const Product({required this.name});
void main() {
runApp(const MaterialApp(
title: 'Shopping App',
home: ShoppingList(
products: [
Product(name: 'Eggs'),
Product(name: 'Flour'),
Product(name: 'Chocolate chips'),
],
),
));
}
class Product {
const Product({required this.name});
return inCart //
? Colors.black54
: Theme.of(context).primaryColor;
}
@override
Widget build(BuildContext context) {
return ListTile(
onTap: () {
onCartChanged(product, inCart);
},
leading: CircleAvatar(
backgroundColor: _getColor(context),
child: Text(product.name[0]),
),
title: Text(
product.name,
style: _getTextStyle(context),
),
);
}
}
class ShoppingList extends StatefulWidget {
const ShoppingList({required this.products, super.key});
@override
State<ShoppingList> createState() => _ShoppingListState();
}
if (!inCart) {
_shoppingCart.add(product);
} else {
_shoppingCart.remove(product);
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Shopping List'),
),
body: ListView(
padding: const EdgeInsets.symmetric(vertical: 8),
children: widget.products.map((product) {
return ShoppingListItem(
product: product,
inCart: _shoppingCart.contains(product),
onCartChanged: _handleCartChanged,
);
}).toList(),
),
);
}
}
Creating a layout
To include images, add an assets tag to the pubspec.yaml file at the root directory
of your app. When you add assets, it serves as the set of pointers to the images
available to your code.
@@ -19,3 +19,5 @@
19
flutter:
19
20
uses-material-design: true
20
21 + assets:
22 + - images/lake.jpg
import 'package:flutter/material.dart';
@override
Widget build(BuildContext context) {
const String appTitle = 'Flutter layout demo';
return MaterialApp(
title: appTitle,
home: Scaffold(
appBar: AppBar(
title: const Text(appTitle),
),
body: const Center(
child: const SingleChildScrollView(
child: Column(
children: [
ImageSection(
image: 'images/lake.jpg',
),
TitleSection(
name: 'Oeschinen Lake Campground',
location: 'Kandersteg, Switzerland',
),
ButtonSection(),
TextSection(
description:
'Lake Oeschinen lies at the foot of the Blüemlisalp in the
'
'Bernese Alps. Situated 1,578 meters above sea level, it '
'is one of the larger Alpine Lakes. A gondola ride from '
'Kandersteg, followed by a half-hour walk through pastures
'
'and pine forest, leads you to the lake, which warms to 20
'
'degrees Celsius in the summer. Activities enjoyed here '
'include rowing, and riding the summer toboggan run.',
),
],
)),
),
),
);
}
}
class TitleSection extends StatelessWidget {
const TitleSection({
super.key,
required this.name,
required this.location,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(32),
child: Row(
children: [
Expanded(
/*1*/
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/*2*/
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text(
name,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
Text(
location,
style: TextStyle(
color: Colors.grey[500],
),
),
],
),
),
/*3*/
Icon(
Icons.star,
color: Colors.red[500],
),
const Text('41'),
],
),
);
}
}
@override
Widget build(BuildContext context) {
final Color color = Theme.of(context).primaryColor;
return SizedBox(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ButtonWithText(
color: color,
icon: Icons.call,
label: 'CALL',
),
ButtonWithText(
color: color,
icon: Icons.near_me,
label: 'ROUTE',
),
ButtonWithText(
color: color,
icon: Icons.share,
label: 'SHARE',
),
],
),
);
}
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(32),
child: Text(
description,
softWrap: true,
),
);
}
}
@override
Widget build(BuildContext context) {
return Image.asset(
image,
width: 600,
height: 240,
fit: BoxFit.cover,
);
}
}
Creating a ListView
import 'package:flutter/material.dart';
@override
Widget build(BuildContext context) {
const title = 'Basic List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: ListView(
children: const <Widget>[
ListTile(
leading: Icon(Icons.map),
title: Text('Map'),
),
ListTile(
leading: Icon(Icons.photo_album),
title: Text('Album'),
),
ListTile(
leading: Icon(Icons.phone),
title: Text('Phone'),
),
],
),
),
);
}
}
Output:
@override
Widget build(BuildContext context) {
const title = 'Horizontal List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: Container(
margin: const EdgeInsets.symmetric(vertical: 20),
height: 200,
child: ListView(
// This next line does the trick.
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
width: 160,
color: Colors.red,
),
Container(
width: 160,
color: Colors.blue,
),
Container(
width: 160,
color: Colors.green,
),
Container(
width: 160,
color: Colors.yellow,
),
Container(
width: 160,
color: Colors.orange,
),
],
),
),
),
);
}
}
Creating a Grid List
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
const title = 'Grid List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: GridView.count(
// Create a grid with 2 columns. If you change the scrollDirection
to
// horizontal, this produces 2 rows.
crossAxisCount: 2,
// Generate 100 widgets that display their index in the List.
children: List.generate(100, (index) {
return Center(
child: Text(
'Item $index',
style: Theme.of(context).textTheme.headlineSmall,
),
);
}),
),
),
);
}
}
Output:
Create lists with different types of items
import 'package:flutter/material.dart';
void main() {
runApp(
MyApp(
items: List<ListItem>.generate(
1000,
(i) => i % 6 == 0
? HeadingItem('Heading $i')
: MessageItem('Sender $i', 'Message body $i'),
),
),
);
}
@override
Widget build(BuildContext context) {
const title = 'Mixed List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: ListView.builder(
// Let the ListView know how many items it needs to build.
itemCount: items.length,
// Provide a builder function. This is where the magic happens.
// Convert each item into a widget based on the type of item it is.
itemBuilder: (context, index) {
final item = items[index];
return ListTile(
title: item.buildTitle(context),
subtitle: item.buildSubtitle(context),
);
},
),
),
);
}
}
/// The base class for the different types of items the list can contain.
abstract class ListItem {
/// The title line to show in a list item.
Widget buildTitle(BuildContext context);
HeadingItem(this.heading);
@override
Widget buildTitle(BuildContext context) {
return Text(
heading,
style: Theme.of(context).textTheme.headlineSmall,
);
}
@override
Widget buildSubtitle(BuildContext context) => const SizedBox.shrink();
}
MessageItem(this.sender, this.body);
@override
Widget buildTitle(BuildContext context) => Text(sender);
@override
Widget buildSubtitle(BuildContext context) => Text(body);
}
Output:
List with spaced items
import 'package:flutter/material.dart';
@override
Widget build(BuildContext context) {
const items = 4;
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
cardTheme: CardTheme(color: Colors.blue.shade50),
useMaterial3: true,
),
home: Scaffold(
body: LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: List.generate(
items, (index) => ItemWidget(text: 'Item $index')),
),
),
);
}),
),
);
}
}
@override
Widget build(BuildContext context) {
return Card(
child: SizedBox(
height: 100,
child: Center(child: Text(text)),
),
);
}
}
Output:
Work with long lists:
import 'package:flutter/material.dart';
void main() {
runApp(
MyApp(
items: List<String>.generate(10000, (i) => 'Item $i'),
),
);
}
@override
Widget build(BuildContext context) {
const title = 'Long List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: ListView.builder(
itemCount: items.length,
prototypeItem: ListTile(
title: Text(items.first),
),
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index]),
);
},
),
),
);
}
}
Output:
Theme based styling:
You can define app-wide themes. You can extend a theme to change a theme style
for one component. Each theme defines the colors, type style, and other parameters
applicable for the type of Material component.
After you define a Theme, use it within your own widgets. Flutter's Material widgets
use your theme to set the background colors and font styles for app bars, buttons,
checkboxes, and more.
This code includes the theme settings and applies them to the Container widget in the
MyHomePage. The GoogleFonts package is used to customize text themes. Make sure you have
the google_fonts package added in your pubspec.yaml:
dependencies:
flutter:
sdk: flutter
google_fonts: ^4.0.0
Example:
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
const appName = 'Custom Themes';
return MaterialApp(
title: appName,
theme: myTheme,
home: const MyHomePage(
title: appName,
),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title,
style: Theme.of(context).textTheme.titleLarge!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
)),
backgroundColor: Theme.of(context).colorScheme.primary,
),
body: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Center(
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 12,
),
color: Theme.of(context).colorScheme.secondary,
child: Text(
'Text with a background color',
// TRY THIS: change the Theme.of(context).textTheme
// to "displayLarge" or "displaySmall".
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
),
Text("Message 1",
style: TextStyle(
fontSize:
Theme.of(context).textTheme.displayLarge!.fontSize)),
Text("Message 2", style: Theme.of(context).textTheme.displayLarge),
Text("Message 3", style: Theme.of(context).textTheme.titleLarge),
Text(
"Message 4",
style: Theme.of(context).textTheme.displaySmall!.copyWith(
color: Theme.of(context).colorScheme.primary,
),
),
Theme(data: myTheme1, child: MyCustomWidget())
]),
floatingActionButton: Theme(
data: Theme.of(context).copyWith(
// TRY THIS: Change the seedColor to "Colors.red" or
// "Colors.blue".
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.pink,
brightness: Brightness.dark,
),
),
child: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
),
);
}
}
@override
Widget build(BuildContext context) {
return Text(
"Message 5",
style: Theme.of(context).textTheme.displayLarge!.copyWith(
color: Theme.of(context).colorScheme.primary,
),
);
}
}
1. **`color: Theme.of(context).colorScheme.primary,`**:
- **`Theme.of(context)`**: This fetches the current `ThemeData` from the closest `Theme`
ancestor in the widget tree. The `ThemeData` contains all the styling information defined in
the app's theme.
- **`colorScheme.primary`**: Within the `ThemeData`, `colorScheme` is an instance of
`ColorScheme` which holds a set of 13 colors that can be used in an app. `primary` is one of
these colors, typically used for key UI elements such as the app bar or buttons.
- **Result**: This line sets the background color of the `Container` to the primary color
defined in the theme.
3. **`style: Theme.of(context).textTheme.bodyMedium!.copyWith(color:
Theme.of(context).colorScheme.onPrimary)`**:
- **`Theme.of(context).textTheme.bodyMedium!`**: This fetches the `bodyMedium` text
style from the current theme's `TextTheme`. The `bodyMedium` style is typically used for
medium-sized body text.
- **`.copyWith(color: Theme.of(context).colorScheme.onPrimary)`**: The `copyWith`
method is used to create a copy of the `bodyMedium` text style with some modifications.
Here, it modifies the text color.
- **`color: Theme.of(context).colorScheme.onPrimary`**: This sets the text color to
`onPrimary`, a color from the `ColorScheme` that is meant to be used on top of the
`primary` color (to ensure good contrast and readability).
- **Result**: The text inside the `Text` widget will use the `bodyMedium` text style, but
with its color set to `onPrimary`.
### Summary:
- The `Container`'s background color is set to the primary color from the theme.
- The `Text` widget inside the `Container` displays text using the `bodyMedium` style from
the theme, with its color set to `onPrimary` to ensure it contrasts well against the primary
background color.
Add interactivity to our app
Please visit URL to understand working of these controls : https://docs.flutter.dev/ui/interactivity
Material Components
• Checkbox
• DropdownButton
• TextButton
• FloatingActionButton
• IconButton
• Radio
• ElevatedButton
• Slider
• Switch
• TextField
void main() {
runApp(MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter a search term',
),
)),
));
}
}
Output:
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Retrieve Text Input',
home: MyCustomForm(),
);
}
}
@override
State<MyCustomForm> createState() => _MyCustomFormState();
}
@override
void dispose() {
// Clean up the controller when the widget is disposed.
myController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Retrieve Text Input'),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: TextField(
controller: myController,
),
),
floatingActionButton: FloatingActionButton(
// When the user presses the button, show an alert dialog containing
// the text that the user has entered into the text field.
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
// Retrieve the text the that user has entered by using the
// TextEditingController.
content: Text(myController.text),
);
},
);
},
tooltip: 'Show me the value!',
child: const Icon(Icons.text_fields),
),
);
}
}
Output:
Handle changes to a text field
import 'package:flutter/material.dart';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Retrieve Text Input',
home: MyCustomForm(),
);
}
}
@override
State<MyCustomForm> createState() => _MyCustomFormState();
}
@override
void initState() {
super.initState();
@override
void dispose() {
// Clean up the controller when the widget is removed from the widget
tree.
// This also removes the _printLatestValue listener.
myController.dispose();
super.dispose();
}
void _printLatestValue() {
final text = myController.text;
print('Second text field: $text (${text.characters.length})');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Retrieve Text Input'),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
TextField(
onChanged: (text) {
debugPrint('FIRST: First text field: $text
(${text.characters.length})');
},
),
TextField(
controller: myController,
),
],
),
),
);
}
}
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Text Field Focus',
home: MyCustomForm(),
);
}
}
@override
State<MyCustomForm> createState() => _MyCustomFormState();
}
@override
void initState() {
super.initState();
myFocusNode = FocusNode();
}
@override
void dispose() {
// Clean up the focus node when the Form is disposed.
myFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Text Field Focus'),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
// The first text field is focused on as soon as the app starts.
const TextField(
autofocus: true,
),
// The second text field is focused on when a user taps the
// FloatingActionButton.
TextField(
focusNode: myFocusNode,
),
],
),
),
floatingActionButton: FloatingActionButton(
// When the button is pressed,
// give focus to the text field using myFocusNode.
onPressed: () => myFocusNode.requestFocus(),
tooltip: 'Focus Second Text Field',
child: const Icon(Icons.edit),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
@override
Widget build(BuildContext context) {
const appTitle = 'Form Validation Demo';
return MaterialApp(
title: appTitle,
home: Scaffold(
appBar: AppBar(
title: const Text(appTitle),
),
body: const MyCustomForm(),
),
);
}
}
@override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: ElevatedButton(
onPressed: () {
// Validate returns true if the form is valid, or false
otherwise.
if (_formKey.currentState!.validate()) {
// If the form is valid, display a snackbar. In the real
world,
// you'd often call a server or save the information in a
database.
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Submit'),
),
),
],
),
);
}
}
void main() {
runApp(const TabBarDemo());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: const TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
Tab(icon: Icon(Icons.directions_bike)),
],
),
title: const Text('Tabs Demo'),
),
body: const TabBarView(
children: [
Text("Car"),
Text("Bus"),
Text("Cycle")
],
),
),
),
);
}
}
Output:
void main() {
runApp(const MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('First Route'),
),
body: Center(
child: ElevatedButton(
child: const Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SecondRoute()),
);
},
),
),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Second Route'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
);
}
}
Output:
Navigation with CupertinoPageRoute
In Flutter you are not limited to Material design language, instead, you also have access
to Cupertino (iOS-style) widgets
import 'package:flutter/cupertino.dart';
void main() {
runApp(const CupertinoApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(
middle: Text('First Route'),
),
child: Center(
child: CupertinoButton(
child: const Text('Open route'),
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(builder: (context) => const SecondRoute()),
);
},
),
),
);
}
}
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(
middle: Text('Second Route'),
),
child: Center(
child: CupertinoButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
);
}
}
Output:
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(title: 'Passing Data', home: DataSender()),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Send Data'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
String data =
"This is some data!"; // Replace with your desired string
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DataReceiver(data: data),
),
);
},
child: const Text('Send'),
),
),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Received Data'),
),
body: Center(
child: Text(
'You sent: $data',
style: const TextStyle(fontSize: 20.0),
),
),
);
}
}
void main() {
runApp(
const MaterialApp(title: 'Passing Data', home: DataSender()),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Send Data'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
String data = "This is some data!"; // Replace with your
desired string
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DataReceiver(),
settings: RouteSettings(arguments: data),
),
);
},
child: const Text('Send'),
),
],
),
),
),
);
}
}
@override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as String;
return Scaffold(
appBar: AppBar(
title: const Text('Received Data'),
),
body: Center(
child: Text(
'You sent: $args',
style: const TextStyle(fontSize: 20.0),
),
),
);
}
}
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
title: 'Passing Data',
home: TodosScreen(
todos: List.generate(
20,
(i) => Todo(
'Todo $i',
'A description of what needs to be done for Todo $i',
),
),
),
),
);
}
class Todo {
final String title;
final String description;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Todos'),
),
body: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(todos[index].title),
// When a user taps the ListTile, navigate to the DetailScreen.
// Notice that you're not only creating a DetailScreen, you're
// also passing the current todo through to it.
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(todo: todos[index]),
),
);
},
);
},
),
);
}
}
class DetailScreen extends StatelessWidget {
// In the constructor, require a Todo.
const DetailScreen({super.key, required this.todo});
@override
Widget build(BuildContext context) {
// Use the Todo to create the UI.
return Scaffold(
appBar: AppBar(
title: Text(todo.title),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Text(todo.description),
),
);
}
}
Send data shown in a list to a new screen using RouteSettings
import 'package:flutter/material.dart';
class Todo {
final String title;
final String description;
void main() {
runApp(
MaterialApp(
title: 'Passing Data',
home: TodosScreen(
todos: List.generate(
20,
(i) => Todo(
'Todo $i',
'A description of what needs to be done for Todo $i',
),
),
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Todos'),
),
body: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(todos[index].title),
// When a user taps the ListTile, navigate to the DetailScreen.
// Notice that you're not only creating a DetailScreen, you're
// also passing the current todo through to it.
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DetailScreen(),
// Pass the arguments as part of the RouteSettings. The
// DetailScreen reads the arguments from these settings.
settings: RouteSettings(
arguments: todos[index],
),
),
);
},
);
},
),
);
}
}
@override
Widget build(BuildContext context) {
final todo = ModalRoute.of(context)!.settings.arguments as Todo;
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
title: 'Returning Data',
home: HomeScreen(),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Returning Data Demo'),
),
body: const Center(
child: SelectionButton(),
),
);
}
}
@override
State<SelectionButton> createState() => _SelectionButtonState();
}
// A method that launches the SelectionScreen and awaits the result from
// Navigator.pop.
Future<void> _navigateAndDisplaySelection(BuildContext context) async {
// Navigator.push returns a Future that completes after calling
// Navigator.pop on the Selection Screen.
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SelectionScreen()),
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Pick an option'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () {
// Close the screen and return "Yep!" as the result.
Navigator.pop(context, 'Yep!');
},
child: const Text('Yep!'),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () {
// Close the screen and return "Nope." as the result.
Navigator.pop(context, 'Nope.');
},
child: const Text('Nope.'),
),
)
],
),
),
);
}
}
import 'package:flutter/material.dart';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
@override
State<MyHomePage> createState() => _MyHomePageState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
leading: Builder(
builder: (context) {
return IconButton(
icon: const Icon(Icons.menu),
onPressed: () {
Scaffold.of(context).openDrawer();
},
);
},
),
),
body: Center(
child: _widgetOptions[_selectedIndex],
),
drawer: Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text('Drawer Header'),
),
ListTile(
title: const Text('Home'),
selected: _selectedIndex == 0,
onTap: () {
// Update the state of the app
_onItemTapped(0);
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
title: const Text('Business'),
selected: _selectedIndex == 1,
onTap: () {
// Update the state of the app
_onItemTapped(1);
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
title: const Text('School'),
selected: _selectedIndex == 2,
onTap: () {
// Update the state of the app
_onItemTapped(2);
// Then close the drawer
Navigator.pop(context);
},
),
],
),
),
);
}
}
Create a login page in flutter
import 'package:flutter/material.dart';
);
}
}
Output:
Connecting Flutter with Firestore
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if
request.time < timestamp.date(2024, 12, 30);
}
}
}
Then under the settings, add an app, and add flutter app, and follow the steps mentioned
about how to configure firestore with flutter.
At the end of the file, paste this code (this code is required to remove, if any, Kotlin errors
on compilation):
configurations.implementation {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}
lib/firebase_options.dart
(This file will not work on your system, you need to create your own file for your firestore
database, by going to settings, and adding a flutter app)
// ignore_for_file: type=lint
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// // ...
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
return macos;
case TargetPlatform.windows:
return windows;
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
dependencies:
flutter:
sdk: flutter
main.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Firestore Example')),
body: Center(
child: CitiesWidget(),
),
),
);
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
saveCity('Peshawar', 'Pakistan');
},
child: Text('Save City'),
),
ElevatedButton(
onPressed: () {
retrieveCity('BJ');
},
child: Text('Retrieve City'),
),
],
);
}
}
Custom objects
Using Map or Dictionary objects to represent your documents is often not very
convenient, so Cloud Firestore supports writing documents with custom classes.
Cloud Firestore converts the objects to supported data types.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
class City {
final String? name;
final String? state;
final String? country;
final bool? capital;
final int? population;
final List<String>? regions;
City({
this.name,
this.state,
this.country,
this.capital,
this.population,
this.regions,
});
factory City.fromFirestore(
DocumentSnapshot<Map<String, dynamic>> snapshot,
SnapshotOptions? options,
) {
final data = snapshot.data();
return City(
name: data?['name'],
state: data?['state'],
country: data?['country'],
capital: data?['capital'],
population: data?['population'],
regions:
data?['regions'] is Iterable ? List.from(data?['regions']) : null,
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Firestore Example')),
body: Center(
child: CitiesWidget(),
),
),
);
}
}
try {
final docRef = db
.collection("cities")
.withConverter(
fromFirestore: City.fromFirestore,
toFirestore: (City city, options) => city.toFirestore(),
)
.doc("LA");
await docRef.set(city);
debugPrint(docRef.data()!.name);
debugPrint(docRef.data()!.state);
debugPrint(docRef.data()!.country);
debugPrint("${docRef.data()!.capital}");
debugPrint("${docRef.data()!.population}");
debugPrint("${docRef.data()!.regions}");
} catch (e) {
debugPrint('Failed to retrieve city: $e');
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
saveCity();
},
child: Text('Save City'),
),
ElevatedButton(
onPressed: () {
retrieveCity('LA');
},
child: Text('Retrieve City'),
),
],
);
}
}
try {
db.collection("cities").doc("PK_LHR").set({"name": "Chicago"});
db.collection("cities").add(data).then((documentSnapshot) =>
debugPrint("Added Data with ID: ${documentSnapshot.id}"));
} catch (e) {
debugPrint('Failed to save city: $e');
}
}
In some cases, it can be useful to create a document reference with an auto-generated ID,
then use the reference later. For this use case, you can call doc():
Note:
Behind the scenes, .add(...) and .doc().set(...) are completely equivalent, so you can
use whichever is more convenient.
Update a document
To update some fields of a document without overwriting the entire document, use
the following language-specific update() methods:
Server Timestamp
You can set a field in your document to a server timestamp which tracks when the
server receives the update.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Firestore Example')),
body: Center(
child: CitiesWidget(),
),
),
);
}
}
} catch (e) {
debugPrint('Failed to save document: $e');
}
}
} catch (e) {
debugPrint('Failed to retrieve city: $e');
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
saveCity();
},
child: Text('Save document'),
),
ElevatedButton(
onPressed: () {
updateDocument('frank');
},
child: Text('Update document'),
),
],
);
}
}
db.collection("cities").doc("DC").delete().then(
(doc) => print("Document deleted"),
onError: (e) => print("Error updating document $e"),
);
Delete fields
To delete specific fields from a document, use the following language-
specific FieldValue.delete() methods when you update a document:
docRef.update(updates);
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Firestore Example')),
body: Center(
child: CitiesWidget(),
),
),
);
}
}
class City {
final String? name;
final String? state;
final String? country;
final bool? capital;
final int? population;
final List<String>? regions;
City({
this.name,
this.state,
this.country,
this.capital,
this.population,
this.regions,
});
factory City.fromFirestore(
DocumentSnapshot<Map<String, dynamic>> snapshot,
SnapshotOptions? options,
) {
final data = snapshot.data();
return City(
name: data?['name'],
state: data?['state'],
country: data?['country'],
capital: data?['capital'],
population: data?['population'],
regions:
data?['regions'] is Iterable ? List.from(data?['regions']) : null,
);
}
} else {
debugPrint("No such document.");
}
} catch (e) {
debugPrint('Failed to retrieve city: $e');
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
saveDocument();
},
child: Text('Save document'),
),
ElevatedButton(
onPressed: () {
getDocument('frank');
},
child: Text('Get document'),
),
],
);
}
}
db.collection("cities").doc("SF").collection("landmarks").get().then(
(querySnapshot) {
debugPrint("Successfully completed");
for (var docSnapshot in querySnapshot.docs) {
debugPrint('${docSnapshot.id} => ${docSnapshot.data()}');
}
},
onError: (e) => print("Error completing: $e"),
);
Compound Query
db.collection("cities")
.where("state", isEqualTo: "CA")
.where("population", isLessThan: 1000000).get().then(
(querySnapshot) {
debugPrint("Successfully completed");
for (var docSnapshot in querySnapshot.docs) {
debugPrint('${docSnapshot.id} => ${docSnapshot.data()}');
}
},
onError: (e) => debugPrint("Error completing: $e"),
);
} catch (e) {
debugPrint('Failed to retrieve city: $e');
}
}
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
const db = admin.firestore();
exportCollections().catch(console.error);
node exportSchema.js
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
const db = admin.firestore();
return subcollectionData;
}
exportCollections().catch(console.error);
This enhanced script handles both collections and subcollections recursively, ensuring a
more comprehensive export of your Firestore schema.
By following these steps, you can successfully export your Firestore schema using Node.js.
Connecting Flutter with local SQLite Database
https://docs.flutter.dev/cookbook/persistence/sqlite
https://pub.dev/packages/sqflite
import 'package:flutter/material.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
runApp(MyApp(db: database));
}
class Person {
final int id;
final String name;
final int age;
const Person({
required this.id,
required this.name,
required this.age,
});
// Convert a person into a Map. The keys must correspond to the names of the
// columns in the database.
Map<String, Object?> toMap() {
return {
'id': id,
'name': name,
'age': age,
};
}
// A method that returns all the persons from the persons table.
Future<List<Person>> getAllPersons() async {
// Get a reference to the database.
// the below code is (a) destructuring the person object, (b) creating a
list of person objects and returning
return [
for (final {
'id': id as int,
'name': name as String,
'age': age as int,
} in personMaps)
Person(id: id, name: name, age: age),
];
}
// A method that retrieves all the persons from the persons table.
Future<void> showPersons() async {
// Get a reference to the database.
// A method that retrieves all the persons from the persons table.
Future<void> showSelectivePersons() async {
// Get a reference to the database.
// Query the table for all the persons meeting the criteria.
final List<Map<String, Object?>> personMaps = await db.query("persons",
columns: ["id", "name"],
where: '$columnId = ?',
whereArgs: [personName]);
Output:
If you have a relatively small collection of key-values to save, you can use the shared_preferences
plugin.
Supported types
Although the key-value storage provided by shared_preferences is easy and convenient to use, it has
limitations:
• Only primitive types can be used: int, double, bool, String, and List<String>.
• It's not designed to store large amounts of data.
• There is no guarantee that data will be persisted across app restarts.
https://docs.flutter.dev/cookbook/persistence/key-value
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Shared preferences demo',
home: MyHomePage(title: 'Shared preferences demo'),
);
}
}
@override
State<MyHomePage> createState() => _MyHomePageState();
}
@override
void initState() {
super.initState();
_loadCounter();
}
/// Load the initial counter value from persistent storage on start,
/// or fallback to 0 if it doesn't exist.
Future<void> _loadCounter() async {
final prefs = await SharedPreferences.getInstance();
setState(() {
_counter = prefs.getInt('counter') ?? 0;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'You have pushed the button this many times: ',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
ElevatedButton(
onPressed: _incrementCounter, child: Text("Increment")),
ElevatedButton(
onPressed: _removeCounter, child: Text("Remove counter")),
],
),
),
);
}
}
flutterapp\android\app\src\main\AndroidManifest.xml
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
class Album {
final int userId;
final int id;
final String title;
const Album({
required this.userId,
required this.id,
required this.title,
});
@override
State<MyApp> createState() => _MyAppState();
}
@override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.title);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
--
-- Database: `mydb`
--
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
--
-- Dumping data for table `users`
--
--
-- Indexes for dumped tables
--
--
-- Indexes for table `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
COMMIT;
Create an app in php with the name: “phpapp”.
Add the following files in the app:
opendb.php
<?php
$servername = "localhost";
$username = "root";
$password = ""; // set this field "" (empty quotes) if you have not set any
password in mysql
$dbname = "mydb";
$e = "";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username,
$password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
?>
menu.php
<table>
<tr>
<td>
<a href="index.php">Home</a>
</td>
<td>
<a href="insertrecord.php">Insert</a>
</td>
</tr>
</table>
index.php
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
</head>
<body>
<?php
include("menu.php");
include("opendb.php");
<?php
while($row = $stmt->fetch())
{
?>
<tr>
<td><?php echo $row[0]; ?></td>
<td><?php echo $row[1]; ?></td>
<td><?php echo $row[2]; ?></td>
</tr>
<?php
}
?>
</table>
<?php
$conn = NULL;
?>
</body>
</html>
insertrecord.php
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Insert Record</title>
</head>
<body>
<?php
include("menu.php");
include("opendb.php");
if(isset($_POST['btnsave']))
{
$name = $_POST['txtname'];
$age = $_POST['txtage'];
try {
$query = "insert into users(uname, age) values(:uname, :age)";
$stmt = $conn -> prepare($query);
$stmt -> bindParam(':uname', $name);
$stmt -> bindParam(':age', $age);
$stmt -> execute();
}
catch(PDOException $e)
{
echo $e -> getMessage();
}
}
?>
<tr>
<td>Name</td>
<td>
<input type="text" name="txtname" id="txtname"></td>
</tr>
<tr>
<td>Age</td>
<td>
<input id="txtage" name="txtage" type="text" >
</td>
</tr>
<tr>
<td><input name="btnsave" type="submit" id="btnsave" title="Save"
value="Save"></td>
<td> </td>
</tr>
</table>
</form>
<?php
$conn = NULL;
?>
</body>
</html>
getsingleobject.php
<?php
$Message = "This is a response";
$data = array(
"userid" => 100,
"uname" => "Zahid Khan",
"age" => 45
);
echo json_encode($data);
//echo json_encode($Response);
?>
getsinglerecord.php
<?php
include("opendb.php");
$result = null;
$userid = 1;
try {
$query = "select * from users where userid = :userid";
$stmt = $conn -> prepare($query);
$stmt -> bindParam(':userid', $userid);
echo $result;
?>
getsinglerecordforinput.php
<?php
$EncodedData = file_get_contents('php://input');
$DecodedData = json_decode($EncodedData, true);
$userid = $DecodedData['userInput'];
include("opendb.php");
$result = null;
try {
$query = "select * from users where userid = :userid";
$stmt = $conn -> prepare($query);
$stmt -> bindParam(':userid', $userid);
$result = json_encode($stmt->fetch(PDO::FETCH_ASSOC));
}
catch(PDOException $e)
{
$result = $e -> getMessage();
}
$conn = NULL;
echo $result;
?>
getalldata.php
<?php
include("opendb.php");
$query = "select * from users";
$stmt = $conn -> prepare($query);
$stmt -> execute();
$resultJSON = json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
$conn = null;
echo $resultJSON;
?>
setdata.php
<?php
include("opendb.php");
$EncodedData = file_get_contents('php://input');
$DecodedData = json_decode($EncodedData, true);
$name = $DecodedData['name'];
$age = $DecodedData['age'];
$Response = null;
try {
$query = "insert into users(uname, age) values(:uname, :age)";
$stmt = $conn -> prepare($query);
$stmt -> bindParam(':uname', $name);
$stmt -> bindParam(':age', $age);
$stmt -> execute();
$Response = array("Code" => "Success", "Message" => "Record
inserted");
}
catch(PDOException $e)
{
$Message = $e -> getMessage();
$Response = array("Code" => "Failed", "Message" => $Message);
}
$conn = NULL;
echo json_encode($Response);
?>
updatedata.php
<?php
include("opendb.php");
$EncodedData = file_get_contents('php://input');
$DecodedData = json_decode($EncodedData, true);
$id = $DecodedData['id'];
$name = $DecodedData['name'];
$age = $DecodedData['age'];
try {
$query = "update users set uname = :uname, age = :age where userid
= :userid";
}
catch(PDOException $e)
{
$Message = $e -> getMessage();
$Response = array("Code" => "Success", "Message" => $Message);
$conn = NULL;
echo json_encode($Response);
?>
deletedata.php
<?php
include("opendb.php");
$EncodedData = file_get_contents('php://input');
$DecodedData = json_decode($EncodedData, true);
$id = $DecodedData['id'];
$Response = null;
try {
$query = "delete from users where userid = :userid";
$stmt = $conn -> prepare($query);
$stmt -> bindParam(':userid', $id);
$stmt -> execute();
$count = $stmt -> rowCount();
if($count > 0)
$Response = array("Code" => "Success", "Message" => "Record
deleted");
else
$Response = array("Code" => "NotFound", "Message" => "Record not
found");
}
catch(PDOException $e)
{
$Message = $e -> getMessage();
$Response = array("Code" => "Failed", "Message" => $Message);
}
$conn = NULL;
echo json_encode($Response);
?>
upload.php
<?php
if(!empty($_FILES['file_attachment']['name']))
{
$target_dir = "uploads/";
if (!file_exists($target_dir))
{
mkdir($target_dir, 0777);
}
$target_file =
$target_dir . basename($_FILES["file_attachment"]["name"]);
$imageFileType =
strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if file already exists
if (file_exists($target_file)) {
echo json_encode(
array(
"status" => 0,
"data" => array()
,"msg" => "Sorry, file already exists."
)
);
die();
}
// Check file size
if ($_FILES["file_attachment"]["size"] > 50000000) {
echo json_encode(
array(
"status" => 0,
"data" => array(),
"msg" => "Sorry, your file is too large."
)
);
die();
}
if (
move_uploaded_file(
$_FILES["file_attachment"]["tmp_name"], $target_file
)
) {
echo json_encode(
array(
"status" => 1,
"data" => array(),
"msg" => "The file " .
basename( $_FILES["file_attachment"]["name"]) .
" has been uploaded."));
} else {
echo json_encode(
array(
"status" => 0,
"data" => array(),
"msg" => "Sorry, there was an error uploading your file."
)
);
}
}
?>
main.dart file
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:file_picker/file_picker.dart';
import 'package:http/http.dart' as http;
class Data {
final int userid;
final String uname;
final int age;
const Data({
required this.userid,
required this.uname,
required this.age,
});
@override
State<MyApp> createState() => _MyAppState();
}
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var data = jsonDecode(response.body);
print(data);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var data =
Data.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
setState(() {
_uname = data.uname;
});
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load Data');
}
}
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var list = jsonDecode(response.body);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var data = Data.fromJson(jsonDecode(response.body));
if (response.statusCode == 200) {
var result = jsonDecode(response.body);
if (response.statusCode == 200) {
var result = jsonDecode(response.body);
print("${result["Code"]} ${result["Message"]}");
} else {
// If the server did not return a response,
// then throw an exception.
throw Exception('Failed .');
}
}
print("${result["Code"]}: ${result["Message"]}");
} else {
// If the server did not return a response,
// then throw an exception.
throw Exception('Failed .');
}
}
if (response.statusCode == 200) {
var result = jsonDecode(response.body);
print("${result["Code"]}: ${result["Message"]}");
} else {
// If the server did not return a response,
// then throw an exception.
throw Exception('Failed .');
}
}
if (result != null) {
setState(() {
_file = result;
});
}
}
if (response.statusCode == 200) {
// Handle success
print(response);
} else {
// Handle error
print('File upload failed');
}
setState(() {
_isUploading = false;
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: Column(children: [
ElevatedButton(
onPressed: fetchAlbum,
child: Text("Fetch Album - Testing Plugin")),
ElevatedButton(
onPressed: fetchData, child: Text("Fetch single object")),
Text(_uname),
ElevatedButton(
onPressed: fetchAllData, child: Text("Fetch All Records")),
ElevatedButton(
onPressed: fetchSingleData, child: Text("Fetch single data")),
ElevatedButton(
onPressed: () => fetchSingleDataAgainstValue("1"),
child: Text("Fetch single data against value")),
ElevatedButton(
onPressed: () => updateRecord("1", "Jawad Khan", "44"),
child: Text("Update Record for given userid")),
ElevatedButton(
onPressed: () => deleteRecord("2"),
child: Text("Delete Record for given userid")),
ElevatedButton(
onPressed: () => insertRecord("Majid Khan", "44"),
child: Text("Insert New Record")),
if (_file != null) Text('File selected:
${_file!.files.single.name}'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _pickFile,
child: Text('Pick File'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _isUploading ? null : _uploadFile,
child: _isUploading
? CircularProgressIndicator()
: Text('Upload File'),
),
])),
),
);
}
}
Output Window:
https://docs.flutter.dev/cookbook/plugins/picture-using-camera
You may also have to upgrade your api version in build.gradle file on this path:
flutterapp\android\app\build.gradle
android {
defaultConfig {
…..
minSdkVersion 23
targetSdkVersion 23
Example:
import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
runApp(
MaterialApp(
theme: ThemeData.dark(),
home: TakePictureScreen(
// Pass the appropriate camera to the TakePictureScreen widget.
camera: firstCamera,
),
),
);
}
@override
TakePictureScreenState createState() => TakePictureScreenState();
}
@override
void initState() {
super.initState();
// To display the current output from the Camera,
// create a CameraController.
_controller = CameraController(
// Get a specific camera from the list of available cameras.
widget.camera,
// Define the resolution to use.
ResolutionPreset.medium,
);
@override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Take a picture')),
// You must wait until the controller is initialized before displaying
the
// camera preview. Use a FutureBuilder to display a loading spinner
until the
// controller has finished initializing.
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
// Otherwise, display a loading indicator.
return const Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
// Provide an onPressed callback.
onPressed: () async {
// Take the Picture in a try / catch block. If anything goes wrong,
// catch the error.
try {
// Ensure that the camera is initialized.
await _initializeControllerFuture;
if (!context.mounted) return;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Display the Picture')),
// The image is stored as a file on the device. Use the `Image.file`
// constructor with the given path to display the image.
body: Image.file(File(imagePath)),
);
}
}
flutterapp\android\app\src\main\AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
If you get a Kotlin version error, see the latest version online and make changes here (see
the third line in below code in the following file):
\flutterapp\android\settings.gradle
plugins {
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
@override
void initState() {
super.initState();
_checkPermissions();
}
if (permission == LocationPermission.deniedForever) {
// Permissions are denied forever, handle appropriately
return;
}
void _startTrackingLocation() {
final positionStream = Geolocator.getPositionStream(
locationSettings: LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 10,
),
);
@override
void dispose() {
_positionStreamSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: _currentPosition == null
? Text('Getting location...')
: Text(
'Location: ${_currentPosition!.latitude},
${_currentPosition!.longitude}'),
);
}
}