Undo/Redo in Flutter: Command Pattern Drawing App Guide

Two lists and two buttons can fake undo — until your strokes carry color, width and eraser state. Here's how to implement undo redo in a Flutter drawing app the command-pattern way: every stroke becomes an object with execute() and undo().

*Last updated: October 8, 2026* Most "undo in Flutter" tutorials tell you to keep two lists — strokes and undone strokes — and call it a day. That works for exactly one demo: black lines, one brush. The moment strokes carry color, width or opacity — or your eraser deletes instead of drawing — the two-list hack sprouts special cases. The command pattern is the honest version of the same idea, and this guide shows how to implement undo redo in flutter drawing app code the command-pattern way: instead of remembering what was drawn, you remember what was done. Each stroke becomes an object that knows how to execute itself and how to reverse itself. Same two buttons. Completely different ceiling. *Tested on Flutter 3.47 / Dart 3.13 (stable, October 2026). The core is pure Dart and runs with dart run ; the UI section uses only stable framework APIs.* What you&#x27;ll build and learn A DrawingCommand contract: every action knows execute() and undo() A two-stack CommandHistory manager with correct redo invalidation DrawStrokeCommand and EraseStrokeCommand — including undo for deletions Gesture → command wiring in a real drawing canvas A CustomPainter that repaints from the command-driven model Toolbar buttons that enable/disable from canUndo / canRedo Command vs memento: which undo strategy fits your app Why a hand-rolled undo list breaks down The typical tutorial approach looks like this: List<Stroke> strokes = []; List<Stroke> undoneStrokes = []; void undo() { if (strokes.isNotEmpty) undoneStrokes.add(strokes.removeLast()); } void redo() { if (undoneStrokes.isNotEmpty) strokes.add(undoneStrokes.removeLast()); } Fine — until reality arrives. An eraser stroke doesn&#x27;t add a stroke, it *removes* one; "undoing" it means restoring a deleted stroke, not popping a list. A…

Explore