Irbisa · Cheatsheet

Basic Widgets

Core layout widgets: Container, Row, Column, Stack, ListView

Junior Developer · 24 questions

  1. 01

    What is the difference between Container, SizedBox, Padding and ColoredBox?

    SizedBox, Padding and ColoredBox each do one job.

  2. 02

    What happens when this Container is built, and how do you fix it?

    Container(  color: Colors.white,  padding: const EdgeInsets.all(16),  decoration: BoxDecoration(    borderRadius: BorderRadius.circular(12),  ),  child: const Text('Card'),)

    In debug it fails an assertion in the constructor: "Cannot provide both a color and a decoration".

  3. 03

    In Row and Column, what do mainAxisAlignment, crossAxisAlignment and mainAxisSize control?

    The main axis is the direction the children are laid out in (horizontal for Row, vertical for Column); the cross axis is perpendicular to it.

    Row(  mainAxisAlignment: MainAxisAlignment.spaceBetween,  crossAxisAlignment: CrossAxisAlignment.baseline,  textBaseline: TextBaseline.alphabetic, // required for baseline  children: [    Text('Total', style: Theme.of(context).textTheme.titleMedium),…
  4. 04

    What is the difference between Expanded and Flexible?

    Expanded is Flexible with fit: FlexFit.tight: the child is forced to fill exactly the share of free space it was given.

    // Expanded: both panels fill the row, 1/3 and 2/3Row(  children: [    Expanded(child: Container(color: Colors.red)),    Expanded(flex: 2, child: Container(color: Colors.blue)),  ],…
  5. 05

    What do AspectRatio, FittedBox and ConstrainedBox do, and when do you use each?

    All three change size rather than draw anything: AspectRatio picks a size with a fixed width-to-height ratio, FittedBox scales its child to fit the space, and ConstrainedBox adds min/max limits on top of the parent's constraints.

    // 16:9 box at any screen widthAspectRatio(  aspectRatio: 16 / 9,  child: Image.network(thumbnailUrl, fit: BoxFit.cover),)…
  6. 06

    How does Stack work with Positioned, and when do you use it instead of Row or Column?

    Stack paints its children on top of each other, the last one on top.

    // A caption over a photo: the image sets the Stack's sizeStack(  children: [    Image.asset('assets/cover.jpg'),    const Positioned.fill(      child: DecoratedBox(…
  7. 07

    What does Wrap do, and how is it different from a Row that overflows?

    Wrap fills a line with children and then starts a new one, like words in a paragraph; a Row has exactly one line, so too many children overflow it with yellow stripes.

    Wrap(  spacing: 8, // between chips in a line  runSpacing: 8, // between lines  children: [    for (final tag in tags) Chip(label: Text(tag)),  ],…
  8. 08

    This row works for short names but breaks on long ones. What error appears, and how do you fix it?

    Row(  children: const [    Icon(Icons.person),    SizedBox(width: 8),    Text('Konstantin Konstantinopolsky-Vasilevsky, Senior Software Engineer, Platform Team'),    Icon(Icons.chevron_right),  ],)

    "A RenderFlex overflowed by N pixels on the right", drawn as yellow-and-black stripes.

  9. 09

    What does SafeArea do, and where should you put it?

    SafeArea pads its child so it stays clear of the notch, the status bar, rounded corners and the home indicator.

  10. 10

    What is the difference between ListView(children: ...), ListView.builder and a Column in a SingleChildScrollView?

    ListView.builder creates rows on demand as they scroll into view, so ten thousand items cost about one screenful.

    // Data-driven list: rows are built only when they come into viewListView.builder(  itemCount: messages.length,  itemExtent: 72, // every row is 72 px: cheap jumps and scrollbar  itemBuilder: (context, index) => MessageTile(message: messages[index]),)…
  11. 11

    What is the difference between Visibility, Opacity and Offstage?

    They hide a widget at different levels: Visibility(visible: false) removes it from the tree, Opacity(opacity: 0) keeps it laid out and tappable but invisible, and Offstage keeps it alive but takes no space, paints nothing and ignores taps.

  12. 12

    What are the Material 3 button widgets, and when do you pick each?

    Material 3 buttons differ in emphasis, and you pick by how important the action is: FilledButton for the main action, OutlinedButton for a secondary one, TextButton for the quietest.

  13. 13

    Why does an InkWell inside a coloured Container show no ripple, and what do you use instead?

    InkWell paints its ripple on the nearest Material ancestor, and the Container colour is painted above that Material, covering the splash.

    // No visual feedback; opaque makes the whole padded box tappableGestureDetector(  behavior: HitTestBehavior.opaque,  onTap: _select,  child: const Padding(padding: EdgeInsets.all(12), child: Text('Tap me')),)…
  14. 14

    How do you show images from assets, the network, memory and a file, and how is Image.network different from NetworkImage?

    Image has a named constructor per source: Image.asset, Image.network, Image.memory and Image.file.

    // pubspec.yaml -> flutter: assets: [assets/images/]Image.asset('assets/images/logo.png', width: 96) Image.network(  'https://cdn.example.com/avatar.jpg',  width: 64,…
  15. 15

    How do you show a SnackBar, and what is ScaffoldMessenger for?

    Call ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: ...)).

    ScaffoldMessenger.of(context)  ..hideCurrentSnackBar()  ..showSnackBar(    SnackBar(      content: const Text('Message archived'),      behavior: SnackBarBehavior.floating,…
  16. 16

    How do you build tabs with TabBar, TabBarView and DefaultTabController?

    Wrap the screen in DefaultTabController(length: n), put a TabBar in AppBar.bottom and a TabBarView in the body.

    DefaultTabController(  length: 3,  child: Scaffold(    appBar: AppBar(      title: const Text('Orders'),      bottom: const TabBar(…
  17. 17

    Explain "constraints go down, sizes go up, parent sets position". Why is width: 300 on a Container sometimes ignored?

    Each parent passes its child min/max constraints, the child picks a size within them, and the parent decides where to place it.

    // wrong: SizedBox.expand forces the full size, so 300 is clampedSizedBox.expand(  child: Container(width: 300, height: 120, color: Colors.teal), // fills everything); // right: Center loosens the constraints, so the child may be smaller…
  18. 18

    Putting a ListView inside a Column throws a layout error. What causes it, and what are the fixes?

    A Column gives its children unbounded height, and a ListView tries to be as tall as its constraints allow: here, infinite.

    // wrong: Vertical viewport was given unbounded heightColumn(  children: [    const ProfileHeader(),    ListView.builder(itemCount: items.length, itemBuilder: _row),  ],…
  19. 19

    How does GridView decide a tile's height, and why do tiles overflow on a narrower phone?

    The grid delegate sets the tile size and the content gets no vote: with crossAxisCount, tile width = (available width − spacing) ÷ count, and height = width ÷ childAspectRatio.

    // wrong: height comes from width, so large text or a narrow phone overflowsGridView.builder(  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(    crossAxisCount: 2,    childAspectRatio: 0.72,  ),…
  20. 20

    Tapping this button throws "Scaffold.of() called with a context that does not contain a Scaffold". Why, and how do you fix it?

    class HomePage extends StatelessWidget {  const HomePage({super.key});   @override  Widget build(BuildContext context) {    return Scaffold(      drawer: const Drawer(child: Text('Menu')),      body: Center(        child: TextButton(          onPressed: () => Scaffold.of(context).openDrawer(),          child: const Text('Open menu'),        ),      ),    );  }}

    Scaffold.of(context) searches upward from context, and the context passed to HomePage.build belongs to HomePage, which sits above the Scaffold it creates.

  21. 21

    Find the bug: after switching to another bottom tab and back, the feed jumps to the top and loads its data again.

    class _HomeShellState extends State<HomeShell> {  int _index = 0;  static const _pages = [FeedPage(), SearchPage(), ProfilePage()];   @override  Widget build(BuildContext context) {    return Scaffold(      body: _pages[_index],      bottomNavigationBar: NavigationBar(        selectedIndex: _index,        onDestinationSelected: (i) => setState(() => _index = i),        destinations: _destinations,      ),    );  }}

    body: _pages[_index] puts a different widget into the same slot on every switch, so Flutter unmounts the old page and disposes its State together with the scroll position and the loaded data.

  22. 22

    What is the difference between implicit and explicit animations, and which should you reach for first?

    An implicit animation animates a property for you whenever its value changes.

    // Implicit: change the value, Flutter animates to itAnimatedContainer(  duration: const Duration(milliseconds: 250),  curve: Curves.easeOut,  width: _expanded ? 240 : 120,  color: _expanded ? Colors.teal : Colors.grey,…
  23. 23

    How does CustomPainter work, and when would you use it?

    CustomPainter gives you a Canvas to draw what widgets cannot express: charts, progress rings, signatures, custom shapes.

    import 'dart:math' as math; class RingPainter extends CustomPainter {  RingPainter({required this.progress, required this.color});   final double progress; // 0.0 to 1.0…
  24. 24

    Find the bug: this upload ring stays at its first value, although the parent calls setState and passes a new RingPainter(_progress).

    class RingPainter extends CustomPainter {  RingPainter(this.progress);  final double progress; // 0.0 to 1.0   @override  void paint(Canvas canvas, Size size) {    final paint = Paint()      ..style = PaintingStyle.stroke      ..strokeWidth = 8;    final rect = (Offset.zero & size).deflate(4);    canvas.drawArc(rect, -math.pi / 2, progress * 2 * math.pi, false, paint);  }   @override  bool shouldRepaint(RingPainter oldDelegate) => false;}

    shouldRepaint always returns false, so when the parent rebuilds with a new painter, the render object keeps the old picture and the ring stays stuck.