before_after_slider
A production-ready Flutter widget for before/after comparison with smooth divider drag, zoom/pan gestures, and customizable labels and overlay.
Features
- Single universal widget:
BeforeAfter(beforeChild, afterChild) - Works with images and arbitrary widgets
- Controlled and uncontrolled progress modes
- Pinch zoom + pan on mobile
- Cmd/Ctrl + wheel zoom on desktop and web
- Optional double-tap zoom
- Grouped options API (
interaction,zoom,labels,overlay) - External
ZoomControllersupport - Platform-adaptive demo app (web/desktop/mobile)
Get Started
Installation
dependencies:
before_after_slider: ^3.0.0
flutter pub get
Quick Start
import 'package:before_after_slider/before_after_slider.dart';
BeforeAfter(
beforeChild: const Image(
image: AssetImage('assets/before.jpg'),
fit: BoxFit.cover,
),
afterChild: const Image(
image: AssetImage('assets/after.jpg'),
fit: BoxFit.cover,
),
)
API Design
BeforeAfter keeps top-level usage clean and groups behavior into dedicated options:
interactionOptionsfor dragging and hit zoneszoomOptionsfor zoom/pan/pointer settingslabelsOptionsfor label visibility and renderingoverlayOptionsfor style or custom overlay builder
Usage Recipes
Controlled slider
class _MyPageState extends State<MyPage> {
double progress = 0.5;
@override
Widget build(BuildContext context) {
return BeforeAfter(
beforeChild: const Image(image: AssetImage('assets/before.jpg'), fit: BoxFit.cover),
afterChild: const Image(image: AssetImage('assets/after.jpg'), fit: BoxFit.cover),
progress: progress,
onProgressChanged: (value) => setState(() => progress = value),
);
}
}
Full interactive setup
BeforeAfter(
beforeChild: const Image(image: AssetImage('assets/before.jpg'), fit: BoxFit.cover),
afterChild: const Image(image: AssetImage('assets/after.jpg'), fit: BoxFit.cover),
interactionOptions: const BeforeAfterInteractionOptions(
sliderOrientation: SliderOrientation.horizontal,
sliderDragMode: SliderDragMode.fullOverlay,
sliderHitZone: SliderHitZone(
minLineHalfWidth: 18,
minThumbRadius: 30,
),
),
zoomOptions: const BeforeAfterZoomOptions(
enabled: true,
pointer: PointerZoomOptions(
requiresModifier: true,
smoothing: 0.4,
),
enableDoubleTapZoom: true,
doubleTapZoomScale: 3.0,
),
labelsOptions: BeforeAfterLabelsOptions(
behavior: LabelBehavior.attachedToContent,
beforeBuilder: (_) => const Text('Before'),
afterBuilder: (_) => const Text('After'),
),
overlayOptions: const BeforeAfterOverlayOptions(
style: OverlayStyle(
dividerWidth: 2,
thumbSize: 40,
),
),
)
Vertical slider orientation
BeforeAfter(
beforeChild: ...,
afterChild: ...,
interactionOptions: const BeforeAfterInteractionOptions(
sliderOrientation: SliderOrientation.vertical,
),
)
Custom overlay
BeforeAfter(
beforeChild: ...,
afterChild: ...,
overlayOptions: BeforeAfterOverlayOptions(
builder: (size, position) {
return Stack(
children: [
Positioned(
left: position.dx,
top: 0,
bottom: 0,
child: const VerticalDivider(width: 2, color: Colors.white),
),
],
);
},
),
)
Auto viewport ratio from image
BeforeAfter(
autoViewportAspectRatioFromImage: true,
beforeChild: const Image(image: AssetImage('assets/before.jpg')),
afterChild: const Image(image: AssetImage('assets/after.jpg')),
)
Notes:
viewportAspectRatiohas higher priority than auto mode.- Auto mode currently reads ratio from direct
Imagechildren.
Programmatic zoom control
final zoomController = ZoomController();
BeforeAfter(
beforeChild: ...,
afterChild: ...,
zoomController: zoomController,
)
zoomController.reset();
Desktop and Web Controls
If PointerZoomOptions.requiresModifier = true:
- macOS: hold
Cmdand use wheel/scroll - Windows/Linux/Web: hold
Ctrland use wheel/scroll
Migration
2.x -> 3.x
3.x finalized grouped options in BeforeAfter.
Before:
BeforeAfter(
beforeChild: ...,
afterChild: ...,
overlayStyle: const OverlayStyle(...),
enableProgressWithTouch: true,
enableZoom: true,
)
After:
BeforeAfter(
beforeChild: ...,
afterChild: ...,
interactionOptions: const BeforeAfterInteractionOptions(
enableProgressWithTouch: true,
),
zoomOptions: const BeforeAfterZoomOptions(
enabled: true,
),
overlayOptions: const BeforeAfterOverlayOptions(
style: OverlayStyle(...),
),
)
1.x -> 2.x
- Removed
BeforeAfterImage - Removed
BeforeAfterLayout - Unified API in
BeforeAfter
Libraries
- before_after_slider
- A Flutter package for creating interactive before/after image comparison widgets.