Skip to content

Flutter - Introduction to Widgets

As established in the architecture chapter, widgets are the fundamental building blocks of any Flutter application. They describe the configuration and state of a part of the user interface. Flutter’s UI is essentially a tree of widgets.

This chapter delves deeper into the concept of widgets, their types, and introduces some basic, commonly used widgets.

In Flutter, a widget is an immutable description of a part of a user interface. ‘Immutable’ means that a widget’s properties (its configuration) cannot change after it’s created. If something needs to change in the UI, Flutter rebuilds the relevant part of the widget tree with new widget instances configured differently.

Widgets form a hierarchy or tree. A widget can contain other widgets (its children), creating a nested structure. For example, a Scaffold widget might contain an AppBar and a Column, and that Column might contain several Text and Padding widgets.

Every widget defines a build method. The framework calls this method when it needs to render the widget. The build method takes a BuildContext object as an argument (which provides information about the widget’s position in the tree) and must return a Widget (or a tree of widgets) that describes the UI for that part.

// Example structure of a StatelessWidget's build method
class MyCustomWidget extends StatelessWidget {
final String message;
const MyCustomWidget({Key? key, required this.message}) : super(key: key);
@override
Widget build(BuildContext context) {
// Returns the widget(s) that make up this custom widget's UI
return Container(
padding: const EdgeInsets.all(16.0),
color: Colors.lightBlueAccent,
child: Text(message), // Uses the 'message' property
);
}
}

When the state changes in a StatefulWidget, its build method is called again to get the updated widget description.

Widgets in Flutter can be grouped based on their purpose:

  • Layout Widgets: Help arrange other widgets (e.g., Row, Column, Stack, Padding, Center, Container). Covered in the Layout chapter.
  • State Management Widgets: Primarily StatelessWidget and StatefulWidget, which determine if a widget manages internal state. Covered in Architecture and State Management chapters.
  • Platform-Specific Widgets: Offer look-and-feel specific to a platform:
  • - **Material Widgets:** Implement Google's Material Design system (e.g., `Scaffold`, `AppBar`, `ElevatedButton`, `TextField`). Commonly used for Android-style apps.
  • - **Cupertino Widgets:** Implement Apple's Human Interface Guidelines (e.g., `CupertinoPageScaffold`, `CupertinoNavigationBar`, `CupertinoButton`, `CupertinoTextField`). Commonly used for iOS-style apps.
  • Basic/Platform-Agnostic Widgets: Core building blocks used across different designs (e.g., Text, Image, Icon, GestureDetector).
  • Animation & Interaction Widgets: Used for creating animations (AnimatedContainer) or handling specific interactions (GestureDetector, Draggable).

Let’s look at some essential widgets you’ll use constantly.

The Text widget displays a string of text with optional styling.

// Simple Text
const Text('Hello, Flutter Devs!');
// Text with styling
Text(
'Styled Text',
style: TextStyle(
color: Colors.purple,
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
letterSpacing: 1.5,
decoration: TextDecoration.underline,
),
);
// Text alignment and overflow handling
Container(
width: 200, // Constrain width to see overflow
child: Text(
'This is a very long line of text that will likely need to wrap or handle overflow.',
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis, // Show '...' if text exceeds maxLines
),
)

The style property takes a TextStyle object to control appearance. Other important properties include textAlign, maxLines, and overflow.

Text.rich allows displaying text with multiple styles within the same widget using TextSpan children:

Text.rich(
TextSpan(
text: 'Normal, ',
style: TextStyle(color: Colors.black),
children: <TextSpan>[
TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: ', and '),
TextSpan(text: 'italic.', style: TextStyle(fontStyle: FontStyle.italic, color: Colors.blue)),
],
),
)

The Image widget displays images. It supports loading images from various sources using different constructors:

  • Image.asset: Loads an image from the project’s assets folder. Requires configuration in pubspec.yaml.

  • Image.network: Loads an image from a URL.

  • Image.file: Loads an image from a local file path (requires path access, e.g., using path_provider).

  • Image.memory: Loads an image from raw bytes (Uint8List).

Common properties include width, height, fit (how the image should fit its box, e.g., BoxFit.cover, BoxFit.contain), and alignment.

The Icon widget displays a glyph from a font, typically the pre-bundled Material Icons font.

// Basic Icon
const Icon(Icons.favorite, color: Colors.red, size: 30.0);
// Different icon
const Icon(Icons.settings);
// Can be used in buttons, etc.
IconButton(
icon: const Icon(Icons.menu),
tooltip: 'Open navigation menu',
onPressed: () {
// Handle button press
},
)

You provide an IconData constant (like Icons.favorite) and can customize color and size.

These are fundamental structural widgets, especially for Material Design apps:

  • MaterialApp: The root widget for a Material app. Configures navigation, theme, locale, etc.
  • Scaffold: Implements the basic Material Design visual layout structure. Provides APIs for showing drawers, snack bars, bottom sheets, and contains slots for AppBar, body, FloatingActionButton, BottomNavigationBar, etc.
  • AppBar: The toolbar typically displayed at the top of a Scaffold. Contains title, actions, leading icons.

You saw these used together in the simple ‘Hello World’ example.

This introduction covers just a few core widgets. The Flutter framework offers a vast catalog, allowing you to build virtually any UI by combining and customizing them.