SessionPlans 750b8android3
SessionPlans 750b8android3
Development
CSE- 503
.
The Widget Inspector in Flutter is a powerful debugging tool that serves several important purposes:
Visual Debugging: It provides a visual representation of your app's widget tree. This allows you to
inspect the structure of your UI and how widgets are nested and composed.
Widget Exploration: You can use the Widget Inspector to explore and understand the hierarchy of
widgets in your app. This is especially useful for complex user interfaces.
Property Inspection: The Widget Inspector displays the properties of each widget, making it easy to
view and understand their configurations.
Interactive Debugging: You can interact with your app in real-time while using the Widget Inspector.
This means you can select widgets in the UI, view their properties, and make changes to see how they
affect the app's behavior.
Performance Profiling: The Widget Inspector is useful for identifying performance bottlenecks in
your Flutter app. It can show you which widgets are being rebuilt and help you optimize your app's
performance.
Accessibility Testing: You can use the Widget Inspector to check the accessibility of your app by
examining the semantics tree, making sure your app is usable by people with disabilities.
Hot Reload Integration: The Widget Inspector is tightly integrated with Flutter's hot reload feature.
You can make changes to your code and see the effects on the widget tree immediately
State Management
In simple words, what a user sees in the application is one state, and he clicks on the button, he
sees another UI screen. So now that screen is a state. So an application is made up of many states,
i.e. UI. And their states are managed by Navigation and route.
Local State : A lot of your data can be Self-contained within a Single widget known as a Local
State.
Global State: state that needs to be shared throughout the widget tree is called Global State.
State Object and setState()
setState is called inside a State class,
State is simply the information of a StatefulWidget.
Every StatefulWidget has a State Object.
This State Object keeps a track of the variables and functions that we define inside a
StatefulWidget.
Since StatefulWidget itself is immutable (cannot be modified), we use State Object to modify the
UI.
We tell this State Object to update our screen's UI using a function called setState().
Example State Object
class MyWidget extends StatefulWidget { // immutable Widget
@override
_MyWidgetState createState() => _MyWidgetState();
// creating State Object of MyWidget
}
pushAndRemoveUntil
popAll : Navigator.popUntil
ModalRoute.withName(‘/’)
Navigator and Route
Route: Apps are the new trend. The number of apps available in the Play Store nowadays is quite
a lot. The apps display their content in a full-screen container called pages or screens. In flutter,
the pages or screens are called Routes.
In android, these pages/screens are referred to as Activity and in iOS, it is referred to as
ViewController. But, in a flutter, routes are referred to as Widgets. In Flutter, a Page / Screen is
called a Route.
Creating routes: A route can be written in the form of a “Class” in Dart using object-oriented
concepts. Each route can be written as a separate class and has its own contents and UI.
Navigator: As the name suggests, Navigator is a widget that helps us to navigate (to find your
way) between the routes. The navigator follows stack method when dealing with the routes.
Based on the actions made by the user, the routes are stacked one over the other and when pressed
back, it goes to the most recently visited route. Navigator is a widget that follows a stack
discipline.
Defining Home: While navigating, the first thing that we need to do is to define or initialize the
“home page”. The home page can be any route according to our needs. The home usually will be
placed at the bottom of the navigator stack.
Navigator and Route
void main() {
runApp(MaterialApp(
home: HomeRoute(),
));
}
Navigating to a Page: Since we have defined our Home, all the remaining is to navigate from home to another route of
the app. For that the navigator widget has a method called Navigator.push(). This method pushes the route on top of the
home, thereby displaying the second route. The code for pushing a route into the stack is as follows:
// Within the `HomeRoute` widget
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SecondRoute()),
); }),
Navigator and Route
In Flutter, the Navigator class and the concept of MaterialApp(
routes are fundamental for navigating between
different screens or pages within your app. The routes: {
Navigator manages a stack of routes and allows
you to push and pop routes onto/from that stack. '/': (context) => HomeScreen(),
Each route represents a screen or page in your '/details': (context) => DetailsScreen(),
app.
// Add more routes here
Here's how you typically work with the Navigator
and routes in Flutter: },
Defining Routes: You define your routes by )
creating a Map of route names to builder
functions. These builder functions are used to
construct the widgets for each route. This is often
done in the MaterialApp widget's routes property:
Navigator and Route
Navigating to a Route: To navigate to a new screen, you Navigator.pushNamed(context, '/details');
can use the Navigator to push a new route onto the stack.
You typically do this in response to user interactions, such Navigator.pop(context);
as button presses or menu selections
Popping a Route: To go back to the previous screen, you Navigator.pushNamed(
can use Navigator.pop(context). This will remove the
current route from the stack context,
Named Routes: Using named routes (like /details in the '/details',
example) is a common practice as it makes navigation
more readable and maintainable. It also allows you to pass arguments: {
data to the new screen via route arguments.
Passing Data: You can pass data to a route when 'title': 'Details Screen',
navigating to it.
'description': 'This is a detailed view.',
In the target route, you can retrieve the data using
ModalRoute.of(context).settings.arguments. },
Nested Navigation: You can have nested navigators to
manage navigation within specific areas of your app, such );
as bottom navigation bars or tabs. Each nested navigator
can have its own set of routes.
Button
Trigger by user to perform any action.
Buttons are the graphical control element (graphical represented and majority is control by UI )
that provides a user to trigger an event such as taking actions, making choices, searching
things, and many more. They can be placed anywhere in our UI like dialogs, forms, cards,
toolbars, etc.
Buttons are the Flutter widgets, which is a part of the material design library. Flutter provides
several types of buttons that have different shapes, styles, and features.
Text Button (Flat Button)
Elevated Button (Raised Button)
Outlined Button (Outline Button)
Few Types of Button
Text Button (Flat Button)- It is a text label button that does not have much decoration and displayed without any
elevation. The flat button has two required properties that are: child and onPressed(). It is mostly used in toolbars,
dialogs, or inline with other content.
By default, the flat button has no color, and its text is black. But, we can use color to the button and text using color and
textColor attributes, respectively.
Elevated Button (Raised Button)- It is a button, which is based on the material widget and has a rectangular body. It
is similar to a flat button, but it has an elevation that will increases when the button is pressed. It adds dimension to the
UI along Z-axis. It has several properties like text color, shape, padding, button color, the color of a button when disabled,
animation time, elevation, etc.
This button has two callback functions.
onPressed(): It is triggered when the button is pressed.
onLongPress(): It is triggered when the button is long pressed.
It is to note that this button is in a disabled state if onPressed() and onLongPressed() callbacks are not specified.
Outline Button- It is similar to the flat button, but it contains a thin grey rounded rectangle border. Its outline border is
defined by the shape attribute.’
Row and Column
Row and column are the two essential widgets in Flutter that allows developers to align children
horizontally and vertically according to our needs. These widgets are very necessary when we
design the application user interface in Flutter.
Key Points
•Row and Column widgets are the most commonly used layout patterns in the Flutter application.
•Both may take several child widgets.
•A child widget can also be a row or column widget.
•We can stretch or constrain a particular children's widget.
•Flutter also allows developers to specify how child widgets can use row and column widgets'
available space.
Row Widget
This widget arranges its children in a horizontal direction on the screen.
In other words, it will expect child widgets in a horizontal array. If the child widgets need to fill the available
horizontal space, we must wrap the children widgets in an Expanded widget.
A row widget does not appear scrollable because it displays the widgets within the visible view. So it is
considered wrong if we have more children in a row which will not fit in the available space. If we want to
make a scrollable list of row widgets, we need to use the ListView widget.
•start: It will place the children from the starting of the main axis.
•end: It will place the children at the end of the main axis.
•center: It will place the children in the middle of the main axis.
•spaceBetween: It will place the free space between the children evenly.
•spaceAround: It will place the free space between the children evenly and half of that space before and after
the first and last children widget.
•spaceEvenly: It will place the free space between the children evenly and before and after the first and last
children widget.
Constructor of Row Widget
Key key: This is an optional parameter that allows you to provide a unique key to identify this widget.
Keys are often used for widget identification and efficient widget updates.
MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start: This parameter determines how the
Row( children (widgets) inside the Row should be aligned along the main axis. In this case, it's set to
MainAxisAlignment.start, which means the children will be aligned to the start of the main axis (typically
the left side in a horizontal row).
{Key key,
MainAxisSize mainAxisSize: MainAxisSize.max: This parameter specifies the constraints on the main
MainAxisAlignment mainAxisAlignment: axis size of the Row. Setting it to MainAxisSize.max means that the Row will try to occupy the maximum
MainAxisAlignment.start, available space along the main axis.
List<Widget> children: const <Widget>[]} List<Widget> children: const <Widget>[]: This is a list of child widgets that will be placed inside the
Row. By default, it's an empty list, but you can add any number of child widgets to create the desired
horizontal layout within a Flutter app.
)
Column Widget
This widget arranges its children in a vertical direction on the screen. In other words, it will
expect a vertical array of children widgets. If the child widgets need to fill the available vertical
space, we must wrap the children widgets in an Expanded widget.
A column widget does not appear scrollable because it displays the widgets within the visible
view. So it is considered wrong if we have more children in a column which will not fit in the
available space. If we want to make a scrollable list of column widgets, we need to use the
ListView Widget.
We can also control how a column widget aligns its children using the property
mainAxisAlignment and crossAxisAlignment. The column's cross-axis will run horizontally,
and the main axis will run vertically. The below visual representation explains it more clearly.
We can also control how a column widget aligns its children using the property
mainAxisAlignment and crossAxisAlignment. The column's cross-axis will run horizontally,
and the main axis will run vertically. The below visual representation explains it more clearly.
Constructor of Column Widget
Key key: This is an optional parameter that allows you to provide a unique key to identify this widget. Keys are
Column( often used for widget identification and efficient widget updates.
{Key key, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start: This parameter determines how the
children (widgets) inside the Column should be aligned along the main axis. In this case, it's set to
MainAxisAlignment.start, which means the children will be aligned to the start of the main axis (typically the top
MainAxisAlignment mainAxisAlignment: in a vertical column).
MainAxisAlignment.start,
MainAxisSize mainAxisSize: MainAxisSize.max: This parameter specifies the constraints on the main axis size
MainAxisSize mainAxisSize: of the Column. Setting it to MainAxisSize.max means that the Column will try to occupy the maximum available
MainAxisSize.max, space along the main axis.
CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center: This parameter determines how the
CrossAxisAlignment.center, children should be aligned along the cross-axis, which is perpendicular to the main axis. Here, it's set to
CrossAxisAlignment.center, indicating that the children will be centered along the cross-axis.
TextDirection textDirection,
TextDirection textDirection: This parameter is optional and allows you to specify the text direction for the
VerticalDirection verticalDirection: Column. It is typically used for localization and internationalization purposes.
VerticalDirection.down, VerticalDirection verticalDirection: VerticalDirection.down: This parameter specifies the direction in which the
children should be laid out along the vertical axis. VerticalDirection.down means the children will be stacked from
TextBaseline textBaseline, top to bottom.
List<Widget> children: const <Widget>[]} TextBaseline textBaseline: This is an optional parameter that lets you specify a text baseline for the Column. It is
commonly used when working with text and fonts.
)
List<Widget> children: const <Widget>[]: This is a list of child widgets that will be placed inside the Column.
By default, it's an empty list, but you can add any number of child widgets to create the layout you desire.
Drawbacks of Row and Column Widget
•Row widget in Flutter does not have horizontal scrolling. So if we have inserted a large number
of children in a single row that cannot be fit in that row, we will see the Overflow message.
•Column widget in Flutter does not have vertical scrolling. So if we have inserted a large number
of children in a single column whose total children size is not equal to the height of the screen, we
will see the Overflow message.
Syntax Row Widget
Create a row widget The Row widget arranges its children
in a horizontal line.
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Inside the Row, three Container widgets are added. Each container has a specified
color (red, green, or blue), a width and height of 100 pixels, and a Text widget with a
corresponding color name. The Center widget is used within each Container to
center the text vertically and horizontally.
Container(
color: Colors.red,
width: 100,
height: 100,
child: Center(
child: Text(
'Red',
style: TextStyle(color: Colors.white), ), ),
),
Flutter TextField Widget
A TextField or TextBox is an input element which holds the alphanumeric data, such as name,
password, address, etc. It is a GUI control element that enables the user to enter text information
using a programmable code.
It can be of a single-line text field (when only one line of information is required) or multiple-
line text field (when more than one line of information is required).
TextField in Flutter is the most commonly used text input widget that allows users to collect
inputs from the keyboard into an app. We can use the TextField widget in building forms,
sending messages, creating search experiences, and many more.
By default, Flutter decorated the TextField with an underline.
Retrieve the value of a TextField
We know that Flutter does not have an ID like in Android for the TextField widget. Flutter
allows the user to retrieve the text in mainly two ways: First is the onChanged method, and
another is the controller method. Both are discussed below:
onChanged method: It is the easiest way to retrieve the text field value. This method store the
current value in a simple variable and then use it in the TextField widget. String value = "";
TextField(
onChanged: (text) {
value = text;
},
)
Retrieve the value of a TextField
Controller method: It is a popular method to retrieve text field value
using TextEditingController. It will be attached to the TextField widget and then listen to
change and control the widget's text value.
TextEditingController mycontroller = TextEditingController();
TextField(
controller: mycontroller,
)
Prefix and suffix icon in text field
Some features of TextField
TextField expandable: Sometimes, we want to expand a TextField that means it can have more than one
line. Flutter can do this very easily by adding the attributes maxLines and set it to null, which is one by
default. We can also specify the exact value to expand the number of lines by default.
TextField( maxLines: 4, )
to control the size of TextField value: TextField widget also allows us to restrict the maximum number of
characters inside the text field. We can do this by adding the maxLength attributes as below:
TextField( maxLength: 10, ),
to obscure text field value: Obscure means to make the field not readable or not understandable easily. The
obscure text cannot visible clear. In Flutter, it is mainly used with a text field that contains a password. We
can make the value in a TextField obscure by setting the obscureText to true.
TextField(
obscureText: true, ),
Flutter Icons
An icon is a graphic image representing an application or any specific entity containing meaning
for the user. It can be selectable and non-selectable.
For example, the company's logo is non-selectable. Sometimes it also contains a hyperlink to go
to another page. It also acts as a sign in place of a detailed explanation of the actual entity.
Flutter provides an Icon Widget to create icons in our applications.
We can create icons in Flutter, either using inbuilt icons or with the custom icons. Flutter
provides the list of all icons in the Icons class.
To add an icon:
Icon(Icons.home)
To add multiple icons or a row of icons in Flutter, you need to identify in which alignment do you want
to show the icons in. In this example, we will be showing icons in horizontally. So we create a row of
icons like this:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Icon(Icons.home),
Icon(Icons.settings),
Icon(Icons.account_circle),
],
)
Icon Widget Properties
Icon class in Flutter is used to show specific icons in our app. Instead of creating an image for our
icon, we can simply use the Icon class for inserting an icon in our app. For using this class you must
ensure that you have set uses-material-design: true in the pubsec.yml file of your object.
Syntax:
Icon(
key key,
size,
color,
semanticLabel,
textDirection
)
Stateful Widget Lifecycle
createState()
initState()
didChangeDependencies()
build()
didUpdateWidget()
setState()
deactivate()
dispose()
Stateful Widget Lifecycle
Constructor: When a Stateful Widget is created, its constructor is called. You can provide initial data
and configurations here.
createState(): When Flutter is instructed to build a StatefulWidget, it immediately calls createState().
It will return an instance of state associated with it.
It is mandatory to call when StatefulWidget is defined
Syntax:
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
createState() Return an instance of a state.
Stateful Widget Lifecycle
initState(): This is the first method called when the widget is created
initState is called once and only once. It must also call super.initState().
This @override method is the best time to:
Initialize data that relies on the specific BuildContext for the created instance of the
widget.
Initialize properties that rely on this widgets 'parent' in the tree.
Syntax:
@override
initState() {
super.initState();
// Add listeners to this class
cartItemStream.listen((data) {
updateWidget(data); }); }
Stateful Widget Lifecycle
didChangeDependencies: The didChangeDependencies method is called immediately after
initState on the first time the widget is built.
• Initstate is called only once during the Stateful Widget Lifecycle but can be called multiple
times, the methods and variables under this can be run multiple times.
• It will also be called whenever an object that this widget depends on data from is called. For
example, if it relies on an InheritedWidget, which updates.
• Use: When we click inside TextField Keyboard appears and we click outside it disappears, for
this we can define function inside this function.
• If we want to use context outside build function (while using provider)
Stateful Widget Lifecycle
build(): This method is called often. It is a required, @override and must return a Widget.
didUpdateWidget(Widget oldWidget): This method is used when there is some changes in the
configuration by the parent widget.
It is called every time we hotreload the app for viewing the updates made to widget.
A typical case is when parent passes some variable to the children() widget via the constructor.
Syntax:
@override
void didUpdateWidget(Widget oldWidget) {
if (oldWidget.importantProperty != widget.importantProperty) {
_init(); } }
Stateful Widget Lifecycle
setState(): The 'setState()' method is called often from the Flutter framework itself and from the
developer.
• It is used to notify the framework that "data has changed", and the widget at this build
context should be rebuilt.
deactivate(): This is rarely used.
• 'deactivate()' is called when State is removed from the tree, but it might be reinserted before
the current frame change is finished (to remove the state temporarily). This method exists
basically because State objects can be moved from one point in a tree to another.
dispose(): 'dispose()' is called when the State object is removed, which is permanent.
This method is where to unsubscribe and cancel all animations, streams, etc.
Basic Program in Dart (to add two numbers)
class Addition {
int add(int a, int b) {
return a + b; } }
void main() {
Addition addition =Addition(); // Create an object of the Addition class
int num1 = 5;
int num2 = 7;
int result = addition.add(num1, num2); // Call the add method
print('The sum of $num1 and $num2 is $result’); }
Dart Parameters
Dart has three ways to declare parameters for a function.
You can use multiple types of parameters in the same function, but there is a strict rule on using
them.
Dart required positional parameters
This is the simplest form. Most programming language has
this kind of parameter. int sum(int a, int b) {
// 1
We declare required positional parameters with a type and return a + b;
name, e.g., int: a.
}
The name is for reference in the function, not at the call // 2
site. sum(1, 2);
You specify only the value without a parameter name when
calling a function. 1 a and b are use within the function.
2 At the call site, arguments are reference by
The term "required" in "required positional parameters" the position. In this case, the argument at the
doesn't mean it has to be non-nullable.
first position is a, the argument at the second
But it means that all arguments must be presented. If it is position is b,
nullable, you have to pass null explicitly
Dart required positional parameters
String greeting(String? name, int numberOfTimes) {
if (name != null) { 1, 2 You have to pass all the required
return 'Hello $name' * numberOfTimes; positional parameters.
} else { 3 Failing to do so would result in an
return 'Hi' * numberOfTimes; } } error.
// 1
greeting(‘abc', 3)
// 2
greeting(null, 3)
// 3
greeting(3);
// 2 positional argument(s) expected, but 1 found.
Dart Named Parameters
We define named parameters by listing them between
curly brackets {}, e.g., {int a, int b, …}. // 1
int namedSum({required int a, required int
Named parameters are optional unless they’re explicitly b}) {
marked as required. return a + b; }
When calling a function, you can specify named namedSum(a: 1, b: 1);
arguments using paramName: value.
1 Notice that parameters are wrapped
Here is the same sum function, but this time, we write it
with named parameters. inside curly brackets {}.