Common Widgets
Layout widgets give your screen structure, but they're empty boxes without actual content inside
them. This lesson covers the small set of widgets you'll reach for constantly to fill that
structure: displaying text, images, and icons, giving users buttons to tap, and wrapping content
in a nicely elevated Card. By the end, you'll have everything needed to build a real,
complete piece of UI — which is exactly what the worked example at the end does.
1. Text
Text is how you display a string of text on screen. On its own it just renders using the surrounding theme's default style, but you'll almost always want to customize it with a TextStyle:
Example: Styled Text
Text(
'Flutter Widgets',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.deepPurple,
),
)
The three properties above — fontSize, fontWeight, and color
— cover the majority of everyday text styling. TextStyle also
supports letter spacing, line height, decoration (underline/strikethrough), and custom font
families, all through the same constructor.
2. Image
Flutter's Image widget has several named constructors depending on where the image data is coming from. Picking the right one matters — they're not interchangeable:
| Constructor | Use for |
|---|---|
Image.asset() | An image bundled inside your app (declared in pubspec.yaml) — the most common choice for logos, icons, and static illustrations |
Image.network() | An image loaded from a URL over the internet |
Image.file() | An image stored on the device's filesystem, e.g. one the user just picked from their camera or gallery |
Image.memory() | An image already loaded into memory as raw bytes |
Example: The Two Most Common Cases
Image.asset('assets/images/logo.png', width: 120)
Image.network(
'https://example.com/avatar.jpg',
width: 64,
height: 64,
fit: BoxFit.cover,
)
Setting up bundled assets correctly (declaring them in pubspec.yaml, organizing an
assets/ folder, handling different pixel densities) is its own topic — it's covered
in full detail in flutter-images-assets.php.
3. Icon
Flutter ships with the entire Material Icons set built in, accessible through the Icons
class. Wrap any of them in an Icon widget to display it:
Example: Icons With Custom Size and Color
Icon(Icons.favorite, color: Colors.red, size: 28)
Icon(Icons.settings)
Icon(Icons.arrow_forward_ios, size: 16)
4. The Button Family
Flutter deliberately gives you several distinct button widgets rather than one configurable button, because Material Design defines different levels of visual emphasis for different kinds of actions. Picking the right one communicates importance to the user without you needing to hand-roll custom styling:
| Widget | Emphasis | Typical use |
|---|---|---|
| ElevatedButton | High — filled background, shadow | The single primary action on a screen ("Submit", "Continue") |
| OutlinedButton | Medium — bordered, no fill | A secondary action alongside a primary one ("Cancel" next to "Save") |
| TextButton | Low — no fill, no border | Minor or dismissive actions ("Skip", "Learn more") |
| IconButton | N/A — icon only | Compact, icon-only actions, often in an AppBar (back, search, more) |
Example: All Four Button Types
ElevatedButton(onPressed: () {}, child: Text('Save'))
OutlinedButton(onPressed: () {}, child: Text('Cancel'))
TextButton(onPressed: () {}, child: Text('Skip'))
IconButton(onPressed: () {}, icon: Icon(Icons.share))
All four share the same core idea: an onPressed callback that runs when tapped
(setting it to null automatically disables the button and greys it out — a handy,
built-in way to represent "not available yet" without extra logic).
5. Card
Card is a simple container with rounded corners and a subtle drop shadow (elevation), matching Material Design's visual language for grouping related content. It's extremely common for list items, dashboard tiles, and content blocks — anywhere you want a piece of UI to visually read as "one unit."
Example: A Basic Card
Card(
elevation: 3,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: EdgeInsets.all(16),
child: Text('Card content goes here'),
),
)
6. Worked Example: A Simple Profile Card
Here's everything from this lesson combined into one realistic, self-contained widget — an avatar, name and subtitle text, and an action button, all grouped inside a Card:
Example: ProfileCard Widget
class ProfileCard extends StatelessWidget {
final String name;
final String subtitle;
const ProfileCard({super.key, required this.name, required this.subtitle});
@override
Widget build(BuildContext context) {
return Card(
elevation: 4,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Avatar: a circular clipped Image, with an Icon fallback style
CircleAvatar(
radius: 40,
backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
child: Icon(Icons.person, size: 32),
),
SizedBox(height: 12),
Text(name, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Text(subtitle, style: TextStyle(fontSize: 14, color: Colors.grey)),
SizedBox(height: 16),
ElevatedButton(
onPressed: () {},
child: Text('View Profile'),
),
],
),
),
);
}
}
// Using it:
const ProfileCard(name: 'Sonu Kumar Pandit', subtitle: 'Flutter Developer')
Notice how naturally the widgets from this lesson and the previous layout lesson slot together: Card for the container, Padding for inner spacing, Column to stack content vertically, SizedBox for gaps between sections, and Text/ ElevatedButton for the actual content. This kind of composition — small, well-understood widgets combined together — is how essentially all real Flutter UI gets built.