Now that you know how to start and run a Flutter app, let's explore what makes the framework special.
Everything you see on the screen is made of widgets. A widget is a unit of the display. It can be a button, text, images, layout info, etc.
Widgets can contain other widgets. But every widget can only have one parent. They are organized in a tree. The root of the tree (the ultimate ancestor widget) is supplied to the runApp method in main.dart.
To avoid reinventing the wheel, Flutter has many widgets available. You need to read the docs to know what they do. Feel free to ask AI about which widget to use, but keep in mind the AI might not give you the latest info.
MaterialApp: A theme and design widget that makes all its children follow the Material design.Scaffold: A layout widget for commonly used locations (app bars, sliding menus, floating action buttons, etc.). Without this, you would need to implement everything withRowandColumnmanually.Center: This centers whatever comes next, in all directions.Text: A content widget for text.Image: A content widget for images. The path it points to must be listed inpubspec.yaml.Padding,Container,SizedBox: Layout widgets that surround its child widget with empty space, each in a different way.GestureDetector: A handler widget. It listens for taps and clicks by the user on its child widget. This is how you would make an image clickable and react to the clicking.TextButton,ElevatedButton,OutlinedButton: Button widgets. They each look and feel different but do the same thing. In a way, they are pre-made versions ofGestureDetector.
Most widgets fall into two kinds. Stateless and stateful.
Stateless widgets are immutable. They will not change themselves.
Stateful widgets can change and hold a state to track the changes. Stateful widgets are composed of two classes, unlike stateless widgets which only have one.
/// This is the public facing class of a [StatefulWidget].
/// In Dart, visibility is public or private. Everything is public by default.
/// Private things start with an underscore _ like _FavoriteWidgetState().
class FavoriteWidget extends StatefulWidget {
const FavoriteWidget({super.key});
@override
State<FavoriteWidget> createState() => _FavoriteWidgetState(); // constructor of a private class
}
/// This is the private class of a [StatefulWidget].
/// This holds the values of the state and the build method.
/// Flutter will call this build method whenever the state changes.
/// You trigger a state change with [setState()].
class _FavoriteWidgetState extends State<FavoriteWidget> {
bool _isFavorited = true;
int _favoriteCount = 41;
...
@override
Widget build(BuildContext context) {
...
void _toggleFavorite() {
/// [setState()] takes a void method as argument. This method
/// will modify the state variables. Then, a "refresh" is triggered
/// for the build method of the [StatefulWidget].
///
/// Keep in mind all child widgets under this [StatefulWidget] will be
/// "refreshed" as well. If you have a lot of widgets, this may cause lag!
setState(() {
if (_isFavorited) {
_favoriteCount -= 1;
_isFavorited = false;
} else {
_favoriteCount += 1;
_isFavorited = true;
}
});
}
}

