On this page19 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. Stack — Layers on Top of Each Other
- 2. alignment
- 3. Positioned — Pin a Child to the Edges
- 4. Stretching Between Two Edges
- 5. Positioned.fill
- 6. Children That Stick Out
- 7. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 005 — Stack & Positioned
| Category | 2 — Layout Widgets |
| Lecture | 005 of 009 |
| Estimated video length | 14 min |
| Target | Flutter 3.44 · Dart 3.12 |
| Level | Beginner |
RowandColumncan only put widgets next to each other. A red badge on a cart icon, text over a banner, an avatar overlapping a cover — these need widgets on top of each other, and that is whatStackandPositioneddo.
Contents
Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways
Every screenshot and error message in this lecture is real. Each app was run on Flutter 3.44, and each error was produced by the code shown.
Prerequisites
Students should already understand, from Lectures 001–004:
Container,BoxDecoration, circles, gradients andTextStyleAlign/Alignment,SizedBoxandAspectRatioRow,Column,Expandedanddouble.infinity
Connection With Previous Lectures
Picture a shopping app's product card: a picture, a red SALE label in its top-left corner, a
heart in its top-right corner and the price along the bottom — all drawn over the picture. With
a Column, the label would sit above the picture and the price below it, never on it. We need a
layout where children share the same space and are painted one over another.
Learning Objectives
By the end of this lecture you will be able to:
- Layer widgets with
Stackand explain the order they are painted in - Align all unpositioned children with
Stack'salignment - Pin a child to the edges with
Positioned(top,left,right,bottom) - Stretch a child between two edges, or over the whole
StackwithPositioned.fill - Let children stick out of a
StackwithclipBehavior: Clip.none - Build badges, overlays and overlapping avatars
- Recognize the error for a
Positionedoutside aStack
1. Stack — Layers on Top of Each Other
Stack takes children like a Column, but it puts them all in the same place. The first
child is painted first, at the bottom; each later child is painted on top:
body: Stack(
children: [
Container(width: 200, height: 200, color: Colors.red.shade200),
Container(width: 140, height: 140, color: Colors.green.shade200),
Container(width: 80, height: 80, color: Colors.blue.shade200),
],
),
Analogy — a
Stackis a pile of paper on a desk. The first sheet is at the bottom; every new sheet goes on top and covers part of what is below.
By default every child starts at the top-left corner. The Stack itself is as big as its
biggest child — here the 200 × 200 red square.
2. alignment
alignment moves all the children (except Positioned ones) to the same point:
body: Stack(
alignment: Alignment.center,
children: [
Container(width: 200, height: 200, color: Colors.red.shade200),
Container(width: 140, height: 140, color: Colors.green.shade200),
Container(width: 80, height: 80, color: Colors.blue.shade200),
],
),
It takes the same Alignment values as Align: Alignment.bottomRight would line the squares
up on their bottom-right corners.
3. Positioned — Pin a Child to the Edges
Positioned places one child at a distance from the Stack's edges:
body: SizedBox(
width: double.infinity,
height: 240,
child: Stack(
children: [
Container(color: Colors.grey.shade200),
const Positioned(
top: 16,
left: 16,
child: Text('top: 16, left: 16'),
),
const Positioned(
bottom: 16,
right: 16,
child: Text('bottom: 16, right: 16'),
),
Positioned(
top: 80,
left: 120,
child: Container(width: 60, height: 60, color: Colors.orange),
),
],
),
),
top: 16, left: 16— 16 pixels from the top edge and the left edge.bottom: 16, right: 16— measured from the bottom-right corner instead.- A
Positionedchild does not affect theStack's size. That is why theStackneeds a size from somewhere — here aSizedBox, and the greyContainerfills it.
4. Stretching Between Two Edges
Give both left and right and the child's width is decided for you — everything between
the two distances:
body: SizedBox(
width: double.infinity,
height: 240,
child: Stack(
children: [
Container(color: Colors.grey.shade200),
Positioned(
left: 24,
right: 24,
bottom: 24,
child: Container(
height: 50,
color: Colors.indigo,
alignment: Alignment.center,
child: const Text(
'left: 24, right: 24 — no width needed',
style: TextStyle(color: Colors.white),
),
),
),
],
),
),
The same works vertically with top and bottom. Of left, right and width you may give
any two; the third is calculated.
5. Positioned.fill
Positioned.fill sets all four edges to 0, so the child covers the whole Stack. It is the
standard way to lay a dark, see-through layer over a picture so white text on it stays readable:
body: Padding(
padding: const EdgeInsets.all(16),
child: SizedBox(
height: 200,
child: Stack(
children: [
Container(color: Colors.teal),
Positioned.fill(
child: Container(
color: Colors.black.withValues(alpha: 0.4),
alignment: Alignment.center,
child: const Text(
'A dark layer over the whole Stack',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
),
],
),
),
),
6. Children That Stick Out
A badge usually hangs over the corner of its icon. Negative distances move a child outside the
Stack — but by default the Stack cuts off anything outside its edges:
body: Center(
child: Stack(
children: [
Container(width: 120, height: 120, color: Colors.indigo.shade100),
Positioned(
top: -10,
right: -10,
child: Container(
width: 36,
height: 36,
alignment: Alignment.center,
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: const Text('5', style: TextStyle(color: Colors.white)),
),
),
],
),
),
clipBehavior: Clip.none turns the clipping off:
body: Center(
child: Stack(
clipBehavior: Clip.none,
children: [
Container(width: 120, height: 120, color: Colors.indigo.shade100),
Positioned(
top: -10,
right: -10,
child: Container(
width: 36,
height: 36,
alignment: Alignment.center,
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: const Text('5', style: TextStyle(color: Colors.white)),
),
),
],
),
),
7. A Real-World Example
The product card from the start of the lecture. A gradient stands in for the product photo — in Lecture 006 we will put a real image there.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.pink),
home: const ProductScreen(),
);
}
}
class ProductScreen extends StatelessWidget {
const ProductScreen({super.key});
@override
Widget build(BuildContext context) {
String product = 'Wireless Headphones';
int price = 4500;
int salePrice = 3600;
return Scaffold(
appBar: AppBar(title: const Text('Shop')),
body: Padding(
padding: const EdgeInsets.all(16),
child: AspectRatio(
aspectRatio: 1,
child: Stack(
children: [
Container(
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFFF8BBD0), Color(0xFFCE93D8)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(20),
),
),
Positioned(
top: 16,
left: 16,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 4,
),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(8),
),
child: const Text(
'SALE',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
const Positioned(
top: 12,
right: 12,
child: Icon(Icons.favorite_border, size: 30),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.85),
borderRadius: const BorderRadius.vertical(
bottom: Radius.circular(20),
),
),
child: Row(
children: [
Expanded(
child: Text(
product,
style: const TextStyle(fontWeight: FontWeight.w600),
),
),
Text(
'Rs. $price',
style: const TextStyle(
color: Colors.grey,
decoration: TextDecoration.lineThrough,
),
),
const SizedBox(width: 8),
Text(
'Rs. $salePrice',
style: const TextStyle(
color: Colors.red,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
],
),
),
),
);
}
}
New details:
BorderRadius.vertical(bottom: Radius.circular(20))rounds only the two bottom corners, so the white strip fits the card's corners.TextDecoration.lineThroughcrosses out the old price.- The bottom strip is a
Positionedwithleft: 0, right: 0, bottom: 0— full width, stuck to the bottom — and inside it a normalRowwithExpanded. Layout widgets mix freely.
Code Examples
Example 1 — Text on a Circle
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Example 1')),
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 160,
height: 160,
decoration: const BoxDecoration(
color: Colors.amber,
shape: BoxShape.circle,
),
),
const Text(
'Ali',
style: TextStyle(fontSize: 36, fontWeight: FontWeight.bold),
),
],
),
),
);
}
}
Example 2 — Four Corners and the Center
Center is not Positioned, so it is laid out over the whole Stack like any other child.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Example 2')),
body: SizedBox(
width: double.infinity,
height: 200,
child: Stack(
children: [
Container(color: Colors.blueGrey.shade100),
const Positioned(top: 8, left: 8, child: Text('top left')),
const Positioned(top: 8, right: 8, child: Text('top right')),
const Positioned(bottom: 8, left: 8, child: Text('bottom left')),
const Positioned(bottom: 8, right: 8, child: Text('bottom right')),
const Center(child: Text('center')),
],
),
),
);
}
}
Example 3 — Notification Badge
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Notifications')),
body: Center(
child: Stack(
clipBehavior: Clip.none,
children: [
const Icon(Icons.notifications, size: 56),
Positioned(
top: -4,
right: -4,
child: Container(
padding: const EdgeInsets.all(6),
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: const Text(
'12',
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
),
],
),
),
);
}
}
Example 4 — Course Banner
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.deepPurple),
home: const BannerScreen(),
);
}
}
class BannerScreen extends StatelessWidget {
const BannerScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Course')),
body: Padding(
padding: const EdgeInsets.all(16),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Stack(
children: [
Positioned.fill(
child: Container(
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Colors.deepPurple, Colors.blue],
),
borderRadius: BorderRadius.circular(16),
),
),
),
const Positioned(
left: 20,
bottom: 20,
right: 20,
child: Text(
'Flutter Essential Widgets\n9 lectures · 3 hours',
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
),
const Positioned(
top: 12,
right: 12,
child: Icon(
Icons.play_circle_fill,
color: Colors.white,
size: 40,
),
),
],
),
),
),
);
}
}
Example 5 — Debit Card
Five layers: the card, a chip, a label, the owner's name and the balance.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const CardScreen(),
);
}
}
class CardScreen extends StatelessWidget {
const CardScreen({super.key});
@override
Widget build(BuildContext context) {
String owner = 'Zayan';
double balance = 25000;
return Scaffold(
appBar: AppBar(title: const Text('Debit Card')),
body: Padding(
padding: const EdgeInsets.all(16),
child: AspectRatio(
aspectRatio: 1.6,
child: Stack(
children: [
Positioned.fill(
child: Container(
decoration: BoxDecoration(
color: Colors.indigo.shade900,
borderRadius: BorderRadius.circular(20),
),
),
),
Positioned(
top: 24,
left: 24,
child: Container(
width: 44,
height: 32,
decoration: BoxDecoration(
color: Colors.amber.shade300,
borderRadius: BorderRadius.circular(6),
),
),
),
const Positioned(
top: 24,
right: 24,
child: Text(
'DEBIT',
style: TextStyle(color: Colors.white70, letterSpacing: 2),
),
),
Positioned(
left: 24,
bottom: 24,
child: Text(
owner,
style: const TextStyle(color: Colors.white, fontSize: 18),
),
),
Positioned(
right: 24,
bottom: 24,
child: Text(
'Rs. $balance',
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
);
}
}
Example 6 — Overlapping Circles
The second circle is 80 % opaque, so the first one shows through where they overlap.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Example 6')),
body: Center(
child: SizedBox(
width: 220,
height: 120,
child: Stack(
children: [
Positioned(
left: 0,
child: Container(
width: 120,
height: 120,
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
),
),
Positioned(
right: 0,
child: Container(
width: 120,
height: 120,
decoration: BoxDecoration(
color: Colors.amber.withValues(alpha: 0.8),
shape: BoxShape.circle,
),
),
),
],
),
),
),
);
}
}
Common Beginner Mistakes
1. Positioned outside a Stack
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Oops')),
body: const Column(
children: [Positioned(top: 20, left: 20, child: Text('Where am I?'))],
),
);
}
}
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞════════════════════════
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget Positioned(left: 20.0, top: 20.0) wants to
apply ParentData of type StackParentData to a RenderObject, which
has been set up to accept ParentData of incompatible type
FlexParentData.
Usually, this means that the Positioned widget has the wrong
ancestor RenderObjectWidget. Typically, Positioned widgets are
placed directly inside Stack widgets.
The offending Positioned is currently placed inside a ColumnPositioned only works as a direct child of a Stack — just like Expanded only works in a
Row or Column.
2. Too many values on one axis
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Stack(
children: [
Positioned(top: 0, bottom: 0, height: 100, child: Text('Ali')),
],
),
),
),
);
}error • Evaluation of this constant expression throws an exception • lib/main.dart:9:13 • const_eval_throws_exceptiontop, bottom and height describe the same direction; three values can contradict each
other, so Flutter accepts at most two. The same goes for left, right and width.
3. A Stack with only Positioned children
Positioned children do not give a Stack its size. If every child is Positioned, the
Stack takes the biggest size it is allowed and your children may end up somewhere unexpected.
Give it a size with a SizedBox, an AspectRatio, or one normal child, as all the examples do.
4. A badge cut in half
The Stack clips by default (section 6). Add clipBehavior: Clip.none.
Best Practices
- Use a
Stackonly for real overlap. If things sit next to each other, aRoworColumnis simpler and adapts better. - Give every
Stacka clear size: a sized background child, aSizedBoxor anAspectRatio. - Put a dark see-through layer (
Positioned.fill) under white text on pictures or bright gradients. - Prefer
left+rightover a fixedwidthfor bars and captions, so they fit every screen. - Keep the painting order in mind: background first, badges and captions last.
Mini Challenge
Build a weather banner for Lahore: a 16 : 9 card with an orange-to-deep-orange diagonal gradient and 20-pixel rounded corners, with:
Lahore(white, 20 pixels) in the top-left corner- a white rounded
Sunnychip in the top-right corner 30°C(white, 56 pixels, bold) in the bottom-left corner
Try it yourself before opening the solution.
Show solution
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.orange),
home: const WeatherScreen(),
);
}
}
class WeatherScreen extends StatelessWidget {
const WeatherScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Weather')),
body: Padding(
padding: const EdgeInsets.all(16),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Stack(
children: [
Positioned.fill(
child: Container(
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Colors.orange, Colors.deepOrange],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(20),
),
),
),
const Positioned(
top: 20,
left: 20,
child: Text(
'Lahore',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
Positioned(
top: 16,
right: 16,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 4,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
child: const Text('Sunny'),
),
),
const Positioned(
left: 20,
bottom: 12,
child: Text(
'30°C',
style: TextStyle(
color: Colors.white,
fontSize: 56,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
);
}
}
How it works
AspectRatiogives theStackits size;Positioned.fillmakes the gradient cover it.- Each label is a
Positionedmeasured from the nearest corner. - The chip is a
Containerwith padding and a largeborderRadius— a pill shape.
Practice Questions
Beginner
- Stack a 100 × 100 yellow square on a 200 × 200 blue square.
- Do the same, but line both squares up on their bottom-right corners.
- In a full-width, 200-pixel-tall light-green area, show
Hello, Sara20 pixels from the top and the left.
Application
- Over a 180-pixel-tall purple box, lay a 50 % black layer with the white 24-pixel text
Coming soonin the center. - Draw Sara's 100 × 100 indigo avatar with a white
S, and a green "online" dot with a white border at its bottom-right. - Build a 140-pixel light-blue rounded card with
Karachiat the top-left and a bold, 44-pixel34°Cat the bottom-right. - Put a red
3badge onIcons.shopping_cart(size 56), overlapping its corner.
Challenge
- Build Zayan's profile header: a 160-pixel teal-to-green cover, a 100 × 100 avatar circle with
a white border that hangs halfway below the cover, and under it his name and
Flutter student.
Practice Answers
Question 1 — Solution
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Question 1')),
body: Stack(
children: [
Container(width: 200, height: 200, color: Colors.blue),
Container(width: 100, height: 100, color: Colors.yellow),
],
),
);
}
}
Question 2 — Solution
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Question 2')),
body: Stack(
alignment: Alignment.bottomRight,
children: [
Container(width: 200, height: 200, color: Colors.blue),
Container(width: 100, height: 100, color: Colors.yellow),
],
),
);
}
}
Question 3 — Solution
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Question 3')),
body: SizedBox(
width: double.infinity,
height: 200,
child: Stack(
children: [
Container(color: Colors.green.shade100),
const Positioned(top: 20, left: 20, child: Text('Hello, Sara')),
],
),
),
);
}
}
Question 4 — Solution
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Question 4')),
body: Padding(
padding: const EdgeInsets.all(16),
child: SizedBox(
height: 180,
child: Stack(
children: [
Container(color: Colors.purple),
Positioned.fill(
child: Container(
color: Colors.black.withValues(alpha: 0.5),
alignment: Alignment.center,
child: const Text(
'Coming soon',
style: TextStyle(color: Colors.white, fontSize: 24),
),
),
),
],
),
),
),
);
}
}
Question 5 — Solution
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Question 5')),
body: Center(
child: Stack(
children: [
Container(
width: 100,
height: 100,
alignment: Alignment.center,
decoration: const BoxDecoration(
color: Colors.indigo,
shape: BoxShape.circle,
),
child: const Text(
'S',
style: TextStyle(color: Colors.white, fontSize: 40),
),
),
Positioned(
right: 4,
bottom: 4,
child: Container(
width: 22,
height: 22,
decoration: BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 3),
),
),
),
],
),
),
);
}
}
Question 6 — Solution
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Question 6')),
body: Padding(
padding: const EdgeInsets.all(16),
child: SizedBox(
height: 140,
child: Stack(
children: [
Positioned.fill(
child: Container(
decoration: BoxDecoration(
color: Colors.lightBlue.shade100,
borderRadius: BorderRadius.circular(16),
),
),
),
const Positioned(
top: 16,
left: 16,
child: Text('Karachi', style: TextStyle(fontSize: 18)),
),
const Positioned(
right: 16,
bottom: 8,
child: Text(
'34°C',
style: TextStyle(fontSize: 44, fontWeight: FontWeight.bold),
),
),
],
),
),
),
);
}
}
Question 7 — Solution
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.indigo),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Question 7')),
body: Center(
child: Stack(
clipBehavior: Clip.none,
children: [
const Icon(Icons.shopping_cart, size: 56),
Positioned(
top: -6,
right: -6,
child: Container(
width: 24,
height: 24,
alignment: Alignment.center,
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: const Text('3', style: TextStyle(color: Colors.white)),
),
),
],
),
),
);
}
}
Question 8 — Solution
bottom: -50 moves the 100-pixel avatar half outside the Stack, so clipBehavior: Clip.none
is needed. The Stack is still only as tall as the cover, so the Column adds a 60-pixel gap
before the name to make room for the hanging half.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.teal),
home: const ProfileScreen(),
);
}
}
class ProfileScreen extends StatelessWidget {
const ProfileScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Profile')),
body: Column(
children: [
Stack(
clipBehavior: Clip.none,
alignment: Alignment.bottomCenter,
children: [
Container(
height: 160,
decoration: const BoxDecoration(
gradient: LinearGradient(colors: [Colors.teal, Colors.green]),
),
),
Positioned(
bottom: -50,
child: Container(
width: 100,
height: 100,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.teal.shade700,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 4),
),
child: const Text(
'Z',
style: TextStyle(color: Colors.white, fontSize: 40),
),
),
),
],
),
const SizedBox(height: 60),
const Text(
'Zayan',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const Text('Flutter student'),
],
),
);
}
}
Quick Revision
- Which child of a
Stackis painted on top? - How big is a
Stackwhose children are notPositioned? - What does
Stack'salignmentaffect? - What do
left: 0, right: 0do to aPositionedchild? - What is
Positioned.fillshort for? - Why might a badge with
top: -10be cut off, and how do you fix it? - Where must a
Positionedwidget be placed? - How many of
top,bottomandheightcan you give at once?
Key Takeaways
Stacklayers its children in the same space; later children are painted on top.- Unpositioned children follow the
Stack'salignment, and decide its size. Positionedpins a child by distances from the edges; two opposite edges set the size.Positioned.fillcovers the wholeStack— ideal for dark overlays.clipBehavior: Clip.nonelets badges and avatars stick out.Positionedmust be a direct child of aStack.
What's Next?
Lecture 006 — Images, Icons & Buttons. Our cards use gradients where pictures should be, and our buttons do nothing. Next we show real images from the app and the internet, use the full Material icon set, and build every kind of button — and make them react when tapped.