Widgets
The core concept of the Flutter framework is In Flutter, Everything is a widget. Widgets are basically user interface components used to create the user interface of the application. In Flutter, the application is itself a widget. The application is the top-level widget and its UI is built using one or more children (widgets), which again build using its children widgets. This composability feature helps us to create a user interface of any complexity.
Everything in Flutter is a widget, which is either:
- StatelessWidget: Immutable; does not depend on state.
- StatefulWidget: Mutable; maintains dynamic state.
In Flutter, everything is a widget. Widgets are the building blocks of a Flutter application, and you can create custom widgets to suit your app's needs. Here's an example of a basic widget implementation:
class HomePage extends StatelessWidget {
final String title;
// Constructor
HomePage({Key key, this.title})
: super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Text('Welcome to Flutter!'),
),
);
}
}
build method (level 1)
build method (level 2)
build method (level 3)
build method (level 3)
build method (level 4)
Types of Widgets
Flutter provides two main types of widgets:
Stateless Widgets:
- These widgets do not change their state once built.
- Examples: Text, Icon, Container.
Example:
import 'package:flutter/material.dart';
class MyStatelessWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Stateless Widget')),
body: Center(
child: Text('This is a Stateless Widget!'),
),
);
}
}
void main() {
runApp(MaterialApp(home: MyStatelessWidget()));
}
Stateful Widgets
Stateful widgets can change their state dynamically during runtime. Here are some examples of stateful widgets:
- Checkbox
- TextField
- Slider
Example:
import 'package:flutter/material.dart';
class MyStatefulWidget extends StatefulWidget {
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String message = "Initial State";
void changeMessage() {
setState(() {
message = "State Changed!";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Stateful Widget')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(message),
ElevatedButton(
onPressed: changeMessage,
child: Text('Change State'),
),
],
),
),
);
}
}
void main() {
runApp(MaterialApp(home: MyStatefulWidget()));
}
Widget Build Visualization
The Flutter widget build process revolves around a tree-like structure, where each widget builds its child widgets. This process ensures a consistent and efficient rendering of the UI.
In Flutter, widgets can be grouped into multiple categories based on their features, as listed below:
- Platform specific widgets
- Layout widgets
- State maintenance widgets
- Platform independent / basic widgets
Widget Tree Example
import 'package:flutter/material.dart';
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Widget Tree Visualization'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Hello, Flutter!'),
ElevatedButton(
onPressed: () {
print('Button Pressed');
},
child: Text('Click Me'),
),
],
),
),
);
}
}
void main() {
runApp(MaterialApp(home: MyHomePage()));
}
Platform specific widgets
Flutter allows you to create apps that look and feel native on different platforms (e.g., Android, iOS) using platform-specific widgets. These widgets adapt their appearance and behavior to match the target platform’s design guidelines.
Platform-Specific Widgets in Flutter
1: Material Design Widgets
- Follow Google's design principles called Material Design to make apps look good and work well.
- These widgets are mainly for Android apps but can also be used in iOS apps.
- Some examples of Material Design widgets are Scaffold, AppBar, FloatingActionButton, and SnackBar.
2:Cupertino Widgets
List of Flutter Widgets
Material Widgets:
- Scaffold
- AppBar
- BottomNavigationBar
- TabBar
- TabBarView
- ListTile
- RaisedButton
- FloatingActionButton
- FlatButton
- IconButton
- DropdownButton
- PopupMenuButton
- ButtonBar
- TextField
- Checkbox
- Radio
- Switch
- Slider
- Date and Time Pickers
- SimpleDialog
- AlertDialog
Cupertino Widgets:
- CupertinoButton
- CupertinoPicker
- CupertinoDatePicker
- CupertinoTimerPicker
- CupertinoNavigationBar
- CupertinoTabBar
- CupertinoTabScaffold
- CupertinoTabView
- CupertinoTextField
- CupertinoDialog
- CupertinoDialogAction
- CupertinoFullscreenDialogTransition
- CupertinoPageScaffold
- CupertinoPageTransition
- CupertinoActionSheet
- CupertinoActivityIndicator
- CupertinoAlertDialog
- CupertinoPopupSurface
- CupertinoSlider
Layout widgets
Layout widgets in Flutter help you arrange or position other widgets in your app. They are essential for structuring your user interface (UI) and creating responsive designs. These widgets allow you to define how widgets should be placed on the screen, either vertically, horizontally, or in more complex layouts.
Here's an explanation and example of some commonly used Layout Widgets:
- Used to arrange other widgets on the screen in different layouts.
- Help organize your UI by arranging elements in rows, columns, stacks, etc.
- Examples: Container, Row, Column, Stack, Center, and more.
Some of the popular layout widgets are as follows −
1:Container
A versatile widget that can hold a single child and allows you to customize its layout with properties like padding, margin, alignment, width, height, and more.
Container(
width: 100,
height: 100,
color: Colors.blue,
child: Text('Hello'),
);
2: Row
A widget that arranges its children horizontally.
Row(
children: [
Icon(Icons.star),
Text('Hello'),
],
);
3: Column
A widget that arranges its children vertically.
Row(
children: [
Icon(Icons.star),
Text('Hello'),
],
);
4: Stack
A widget that allows you to layer widgets on top of each other.
Stack(
children: [
Image.asset('background.png'),
Text('Overlay Text',
style: TextStyle(fontSize: 24),
),
],
);
5: Expanded
A widget that expands a child widget to fill available space in a Row, Column, or Flex.
Row(
children: [
Icon(Icons.star),
Expanded(
child: Text('This takes up remaining space'),
),
],
);
6: Align
A widget that aligns its child within itself.
Align(
alignment: Alignment.topRight,
child: Text('Hello'),
);
7: Padding
A widget that adds padding around a child widget.
Padding(
padding: EdgeInsets.all(16.0),
child: Text('Padded Text'),
);
8: Center
A widget that centers its child within itself.
Center(
child: Text('Centered Text'),
);
9: ListView
A scrollable list of widgets that can be either vertically or horizontally arranged.
ListView(
children: [
Text('Item 1'),
Text('Item 2'),
],
);
10: GridView
A scrollable grid of widgets, typically used to display items in a grid layout.
GridView.count(
crossAxisCount: 3,
children: [
Container(color: Colors.blue, height: 50),
Container(color: Colors.red, height: 50),
],
);
11: Flexible
A widget that allows a child of a Row, Column, or Flex to be flexible in size and grow to fill remaining space.
Row(
children: [
Flexible(child: Text('Flexible 1')),
Flexible(child: Text('Flexible 2')),
],
);
12: Wrap
A widget that automatically wraps its children into the next line when there is no more space available.
Wrap(
children: [
Chip(label: Text('Item 1')),
Chip(label: Text('Item 2')),
],
);
13: SizedBox
A widget that gives a fixed size to a child, and can also be used to add space between widgets.
SizedBox(
width: 100,
height: 50,
child: Container(color: Colors.blue),
);
14: FractionallySizedBox
A widget that sizes its child based on a fraction of its parent widget's size.
FractionallySizedBox(
alignment: Alignment.center,
widthFactor: 0.5,
child: Container(color: Colors.green),
);
15: Scaffold
A top-level container that holds the structure of a screen, typically including an app bar, body, floating action button, etc
A top-level container that holds the structure of a screen, typically including an app bar, body, floating action button, etc.
16: MaterialPageRoute
A widget that defines the screen transition for a route in a Material App.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewScreen(),
),
);
State maintenance widgets
In Flutter, all widgets are either derived from StatelessWidget or StatefulWidget. Widget derived from StatelessWidget does not have any state information but it may contain widget derived from StatefulWidget. The dynamic nature of the application is through interactive behavior of the widgets and the state changes during interaction. For example, tapping a counter button will increase / decrease the internal state of the counter by one and reactive nature of the Flutter widget will auto re-render the widget using new state information.
We will learn the concept of StatefulWidget widgets in detail in the upcoming State management chapter.
Platform Independent / Basic Widgets in Flutter
Flutter provides a rich set of platform-independent widgets that work seamlessly across Android, iOS, web, and desktop platforms. These widgets adhere to Flutter's core design principles, ensuring uniformity and performance regardless of the underlying platform.
Text
Displays a string of text with styling options.
Text(
'Hello, Flutter!',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
);
Image
Displays images from various sources like assets or the network.
// From assets
Image.asset('assets/image.png');
// From the network
Image.network('https://example.com/image.png');
Icon
Displays material design icons with customizable size and color.
Icon(
Icons.home,
size: 40,
color: Colors.blue,
);
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Text, Image, and Icon Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Text Widget
Text(
'Hello, Flutter!',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 20), // Add some spacing
// Image Widget (use your image path)
Image.asset('assets/image.png', width: 100, height: 100),
// Icon Widget
Icon(
Icons.home,
size: 40,
color: Colors.blue,
),
],
),
),
),
);
}
}
Row and Column
Layout widgets for arranging children horizontally (Row) or vertically (Column).
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text('Item 1'),
Text('Item 2'),
],
)
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Item A'),
Text('Item B'),
],
)
Switch
A widget for toggling between on and off states.
Switch(
value: true,
onChanged: (bool value) => print(value),
)
Switch(
value: true,
onChanged: (bool value) => print(value),
)
Slider
A widget for selecting a value from a range.
Slider(
value: 50,
min: 0,
max: 100,
onChanged: (value) => print(value),
)