Basic Widgets
Core layout widgets: Container, Row, Column, Stack, ListView
- 01
What is the difference between Container, SizedBox, Padding, and ColoredBox?
EasySizedBox, Padding and ColoredBox each do exactly one job; Container is a convenience wrapper that composes several of them at once.
// ── Lightweight options (prefer these) ──────────── const SizedBox(width: 16, height: 16) // spacer const SizedBox.expand() // fills available space const SizedBox.shrink() // 0×0 invisible Padding( … - 02
Explain Row, Column, and Stack with their key properties.
EasyRow lays its children out horizontally, Column vertically, and Stack overlaps them along the z-axis.
// Row Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ const Icon(Icons.star, color: Colors.amber), … - 03
What is the difference between ListView, GridView, and CustomScrollView?
MediumListView scrolls along a single axis, GridView lays out a scrollable 2D grid, and CustomScrollView stitches several sliver areas into one coordinated scroll.
// ListView.builder — for any dynamic list ListView.builder( itemCount: items.length, itemExtent: 72.0, // ✅ fixed height enables fast scrolling itemBuilder: (context, index) => ListTile( leading: CircleAvatar(child: Text('${index + 1}')), … - 04
How do you handle forms and validation in Flutter?
MediumA Form widget plus a
GlobalKey<FormState>coordinates validation and saving across every field inside it.class LoginForm extends StatefulWidget { const LoginForm({super.key}); @override State<LoginForm> createState() => _LoginFormState(); } class _LoginFormState extends State<LoginForm> { … - 05
How does CustomPainter work and when would you use it?
HardCustomPainter gives you direct access to a Canvas to draw anything — shapes, paths, gradients, charts — that built-in widgets cannot achieve.
class PieChartPainter extends CustomPainter { final List<double> values; final List<Color> colors; PieChartPainter({required this.values, required this.colors}); … - 06
What is the difference between Expanded and Flexible widgets?
MediumExpanded is the tight form of Flexible — it forces its child to fill exactly the space it was allotted.
// ── Basic Expanded ───────────────────────── Row( children: [ Expanded( child: Container(color: Colors.red), ), … - 07
How does LayoutBuilder work and when should you use it?
MediumLayoutBuilder provides parent constraints to build child widgets responsively.
// ── Basic LayoutBuilder ──────────────────── LayoutBuilder( builder: (context, constraints) { print('Max width: ${constraints.maxWidth}'); print('Max height: ${constraints.maxHeight}'); … - 08
What are the Material 3 button widgets and when do you pick each?
EasyMaterial 3 ships five button styles, each with a specific role on the page.
// Primary action — only one per screen FilledButton( onPressed: _signUp, child: const Text('Create account'), ); … - 09
How do you display images in Flutter — assets, network, memory, file?
EasyFlutter's
Imagewidget renders any image source via constructors that match the input.// Asset — instant, bundled Image.asset('assets/logo.png', width: 96, height: 96); // Declared in pubspec.yaml: // flutter: // assets: … - 10
How do you make an arbitrary widget tappable, and when is InkWell the better choice over GestureDetector?
EasyGestureDetector recognises the gesture but draws nothing, while InkWell adds the Material ripple plus hover and focus feedback.
GestureDetector( behavior: HitTestBehavior.opaque, // whole box, not just painted pixels onTap: _select, onLongPress: _showContextMenu, child: const Padding( padding: EdgeInsets.all(12), … - 11
What is the difference between implicit and explicit animations in Flutter, and which should you reach for first?
MediumAn implicit animation interpolates a property for you whenever its value changes, while an explicit one hands you an AnimationController that you drive yourself.
// ── Implicit: change the value, Flutter tweens it ── AnimatedContainer( duration: const Duration(milliseconds: 250), curve: Curves.easeOut, width: _expanded ? 240 : 120, padding: EdgeInsets.all(_expanded ? 24 : 8), … - 12
Putting a ListView inside a Column throws a layout error. What causes it and what are the fixes?
MediumA Column gives its children unbounded height on the main axis, and a ListView tries to fill whatever height it is given, so together they produce an infinite constraint.
// ❌ Vertical viewport was given unbounded height Column( children: [ const ProfileHeader(), ListView.builder(itemCount: items.length, itemBuilder: _row), ], … - 13
A row of tag chips overflows with yellow stripes as soon as the tags get long — which widget fixes it, and what does it cost?
EasyWrap lays children out on one run until the line is full, then starts a new run; a Row has exactly one line and overflows instead.
// ❌ Row has one line — RenderFlex overflowed by 68 pixels Row( children: [for (final t in tags) Chip(label: Text(t))], ); // ✅ Wrap starts a new run when the line is full … - 14
The bottom bar sits on top of the iPhone home indicator, and sprinkling SafeArea everywhere leaves double gaps — how does SafeArea actually work?
EasySafeArea is a Padding that reads
MediaQuery.padding, insets its child by it, and then hands down a MediaQuery with that padding removed — which is why a nested SafeArea adds nothing and why the order of widgets around it matters.// The AppBar already consumed the status bar — top: false avoids a second gap Scaffold( appBar: AppBar(title: const Text('Inbox')), body: SafeArea( top: false, child: ListView(children: rows), … - 15
You set width: 300 on a Container and it still fills the whole screen. What layout rule explains that, and how do you actually get 300?
MediumThe parent's constraints win: a widget may only choose a size the constraints allow, and a tight constraint allows exactly one.
// ❌ width ignored: the Scaffold body gives its child tight constraints Scaffold( body: Container(width: 300, color: Colors.teal), // fills the screen ); // ✅ Center loosens them, so the child may pick a smaller size … - 16
A notification badge positioned at the corner of an avatar is half cut off, and the visible half ignores taps. What is going on?
MediumA Stack clips to its own box and never hit-tests outside it, so whatever a
Positionedpushes past the edge is trimmed when painting and dead to pointers either way.// ❌ half the badge is clipped, and the half you can see is not tappable Stack( children: [ const Avatar(size: 48), Positioned( top: -6, … - 17
Grid tiles print BOTTOM OVERFLOWED BY 14 PIXELS on a tester's phone but look perfect on yours. What decides a tile's height?
MediumThe grid delegate decides it, from the column width and
childAspectRatio— the content never gets a vote, because each tile is laid out with tight constraints.// ❌ height is derived from the width; 1.3x text scale blows the tile apart GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 12, mainAxisSpacing: 12, … - 18
A login form throws "A RenderFlex overflowed by 137 pixels" the moment the keyboard opens. What is the right fix?
MediumThe keyboard shrinks the Scaffold body and a Column has nowhere to put the extra content, so the content has to become scrollable.
// ❌ overflows the moment the keyboard halves the body Scaffold( body: Column( children: const [Logo(), EmailField(), PasswordField(), SubmitButton()], ), ); … - 19
A reviewer flags IntrinsicHeight as expensive. What does it actually do at layout time, and when is it still the right call?
HardIt runs a speculative measurement pass over its subtree to ask how tall the children would like to be, and only then lays them out — so that subtree is walked twice, and the cost compounds with nesting.
// ✅ legitimate: the divider must match the taller card, whose height // nobody knows until the text is laid out IntrinsicHeight( child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: const [ … - 20
An expanded row in a long ListView collapses itself after you scroll it off screen and back. Why, and what do you do about it?
HardListView.builderunmounts any item that scrolls past the cache window and disposes its State, so anything the row kept in its own State is gone by the time it comes back.// ❌ the flag lives in the row's State, which is disposed on scroll-off class _ExpandableRowState extends State<ExpandableRow> { bool _open = false; // gone the moment the row leaves the cache window } // ✅ 1. hoist it — the row is stateless again and the list stays lazy …