flutter_flip_flap - a customizable split-flap / flip display for Flutter. Ideal for clocks, boards, counters, and any UI that needs mechanical card or 3D flip effects for text and widgets.
Features
- Text items and arbitrary widget items on the same rail (
FlipFlapTextItemandFlipFlapWidgetItem). - Two modes: mechanical flap (split) and 3D flip, with axis and direction control.
- Flexible symbol sets via
UnitTypeor your ownvalues, control of cards per pack, and direction. - Theming through
FlipFlapThemeor per-widgetDecoration/TextStyle. - Clock demo with mixed content in
example/lib/main.dart.
Live example
You can see example here: https://peterombodi.github.io/flutter_flip_flap/
Installation
flutter pub add flutter_flip_flap
or add to pubspec.yaml:
dependencies:
flutter_flip_flap: ^0.4.1
Quick start
Minimal text board:
import 'package:flutter_flip_flap/flutter_flip_flap.dart';
class SimpleBoard extends StatelessWidget {
const SimpleBoard({super.key});
@override
Widget build(BuildContext context) {
const text = 'HELLO';
const unit = BoxConstraints(minWidth: 42, minHeight: 72, maxHeight: 72);
return FlipFlapDisplay.fromText(
text: text,
unitConstraints: unit,
textStyle: const TextStyle(fontSize: 42, fontWeight: FontWeight.w700),
displayDecoration: const BoxDecoration(color: Colors.transparent),
unitDecoration: const BoxDecoration(
color: Color(0xFF1F1F1F),
borderRadius: BorderRadius.all(Radius.circular(6)),
),
);
}
}
Advanced usage
Mix widgets and text cards and tune animation:
Widget build(BuildContext context) {
return FlipFlapDisplay(
unitConstraints: const BoxConstraints(minWidth: 56, minHeight: 96, maxHeight: 96),
textStyle: const TextStyle(fontSize: 48, color: Colors.orangeAccent),
items: const [
// Mechanical flap
FlipFlapWidgetItem.flap(child: Icon(Icons.flight_takeoff, size: 48)),
FlipFlapTextItem.flap('A', unitType: UnitType.character, unitsInPack: 3),
// 3D flip (horizontal axis, backward direction)
FlipFlapWidgetItem.flip(
child: Icon(Icons.swap_horiz, size: 48),
flipAxis: Axis.horizontal,
flipDirection: FlipDirection.backward,
),
// Not limited by alphabet
FlipFlapTextItem.flap('12', unitType: UnitType.text),
// 3D flip for text (vertical axis)
FlipFlapTextItem.flip(
'B',
unitType: UnitType.character,
unitsInPack: 2,
flipAxis: Axis.vertical,
),
],
);
}
Key parameters
unitConstraints- required card sizing (minWidth/minHeight).unitsInPack- how many intermediate units the animation scrolls (>=2 adds rolling effect).unitType/values- allowed symbols or custom list.useShortestWay- pick shortest path on the circular alphabet or not.ItemType/flipAxis/flipDirection- choose mechanical flap or 3D flip and its orientation (works in factoryFlipFlapDisplay.fromTexttoo).duration/durationJitterMs- per item or per display animation timing.displayDecoration/unitDecoration/textStyle- per-widget styling or via theme.enableBounce/bounceOvershoot- toggle/adjust back-out overshoot for flap/flip animations.
Theming
Add FlipFlapTheme to ThemeData.extensions to reuse styles:
final theme = ThemeData(
extensions: const [
FlipFlapTheme(
unitDecoration: BoxDecoration(
color: Color(0xFF303030),
borderRadius: BorderRadius.all(Radius.circular(6)),
),
displayDecoration: BoxDecoration(color: Colors.transparent),
textStyle: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
);
If not provided, built-in light and dark presets are used.
Example app
Run the demo clock:
cd example
flutter run
Example code: example/lib/main.dart.
Feedback
Libraries
- flutter_flip_flap
- models/flip_flap_item
- split_flap_theme
- widgets/core/back_out_curves
- widgets/core/flap_animator
- widgets/core/flap_controller_mixin
- widgets/core/jitter_duration_mixin
- widgets/core/unit_base
- widgets/flap/flap_text_unit
- widgets/flap/flap_widget_unit
- widgets/flap/unit_tile
- widgets/flip/flip_text_unit
- widgets/flip/flip_widget_unit
- widgets/flip_flap_display