ResizableSplitter class Widget

A high-performance resizable splitter widget with robust pointer handling.

  • Smooth dragging, keyboard navigation, and accessible semantics.
  • Works with embedded platform views (e.g., WebViews) via an overlay shield to stop pointer events from being stolen.
  • Extensive customization via divider (SplitterDividerStyle): a state-dependent color, thickness, grab slop, and a custom grip builder.

If the incoming constraints along axis are unbounded or zero, the splitter cannot resize, so under the default UnboundedBehavior.shrinkToChildren it shows the two panels without the divider, sized to their content. Opt into UnboundedBehavior.useFallbackExtent (via ResizableSplitterTheme or the constructor) to give the handle a finite sandbox while preserving side panels.

Theme precedence: explicit constructor values override ResizableSplitterTheme, which in turn overrides Theme.of(context).extension<ResizableSplitterThemeData>(). Every theme field is nullable, so a partial override only replaces the fields it sets. When nothing is provided, colors fall back to the ambient ThemeData (via ColorScheme) and numeric values fall back to the defaults documented on each parameter.

Inheritance

Constructors

ResizableSplitter({required Widget start, required Widget end, Key? key, SplitterController? controller, Axis axis = Axis.horizontal, SplitterPosition initialPosition = const SplitterPosition.fraction(0.5), SplitterPaneConstraints startConstraints = const SplitterPaneConstraints(minExtent: 100), SplitterPaneConstraints endConstraints = const SplitterPaneConstraints(minExtent: 100), double minStartFraction = 0.0, double maxStartFraction = 1.0, SplitterDividerStyle? divider, ValueChanged<SplitterChangeDetails>? onChanged, ValueChanged<SplitterChangeDetails>? onChangeStart, ValueChanged<SplitterChangeDetails>? onChangeEnd, bool? enableKeyboard, bool? enableHaptics, double? keyboardStep, double? pageStep, String? semanticsLabel, SplitterSemanticsLabels? semantics, Color? dragBarrierColor, Widget dragBarrierBuilder(BuildContext context)?, bool? shieldPlatformViews, SplitterSnapBehavior? snap, bool holdScrollWhileDragging = false, bool deferredResize = false, double? doubleTapResetTo, bool resizable = true, VoidCallback? onHandleTap, VoidCallback? onHandleDoubleTap, SplitterConstraintPolicy constraintPolicy = SplitterConstraintPolicy.favorStart, SplitterSurplusPolicy surplusPolicy = SplitterSurplusPolicy.leaveGap, UnboundedBehavior? unboundedBehavior, double? fallbackExtent, bool? snapToPhysicalPixels, String? restorationId})
Builds a resizable splitter with the provided panels and configuration.
const

Properties

axis Axis
The axis along which to split (horizontal or vertical).
final
constraintPolicy SplitterConstraintPolicy
Policy applied when both panes cannot meet their minimums at once (a shortage).
final
controller SplitterController?
Optional controller for programmatic control and persistence.
final
deferredResize bool
Defers the resize until the drag is released. While dragging, the panes keep their committed size and a lightweight preview line tracks the pointer; on release the panes settle to the final position once. Useful when the panes contain expensive subtrees. Defaults to false (live resize).
final
divider SplitterDividerStyle?
Divider appearance and grab configuration: thickness, a state-dependent color, the SplitterDividerStyle.interactiveExtent grab target, and a custom grip SplitterDividerStyle.builder. Unset fields fall back to ResizableSplitterTheme, then to the built-in defaults.
final
doubleTapResetTo double?
Optional ratio to jump to on double-tap.
final
dragBarrierBuilder Widget Function(BuildContext context)?
Builds the visual of the drag barrier shown while dragging. The shield itself is kept regardless - an opaque hit blocker plus an always-painted base layer that composites a Flutter surface above platform views so they can't swallow the pointer release and strand the drag. This only customizes what is drawn on top of that base (the default is a dragBarrierColor fill, or nothing). Only used when shieldPlatformViews is enabled.
final
dragBarrierColor Color?
The drag barrier's fill color while dragging. Ignored if dragBarrierBuilder is set. Leave it null for the default: the shield still paints an imperceptible base layer (so it composites above platform views and the OS can't route the release to a native view), just with no visible tint.
final
enableHaptics bool?
Whether haptic feedback fires on drag start and keyboard adjustments.
final
enableKeyboard bool?
Whether to enable keyboard navigation with arrow keys. Defaults to true.
final
end Widget
The widget to display in the end position (right/bottom).
final
endConstraints SplitterPaneConstraints
Pixel sizing limits for the end (right/bottom) pane. Defaults to a 100px minimum.
final
fallbackExtent double?
Extent in pixels to use when unboundedBehavior is UnboundedBehavior.useFallbackExtent. Defaults to 500.
final
hashCode int
The hash code for this object.
no setterinherited
holdScrollWhileDragging bool
Whether to temporarily hold the nearest Scrollable's position while dragging.
final
initialPosition SplitterPosition
Initial split position if no controller is provided. Use SplitterPosition.startPixels / SplitterPosition.endPixels to pin a pane to a pixel width that survives container resizes, or SplitterPosition.fraction for a ratio. Defaults to a centered fraction.
final
key Key?
Controls how one widget replaces another widget in the tree.
finalinherited
keyboardStep double?
Step applied with Arrow keys (e.g., 0.01 = 1%). Defaults to 0.01.
final
maxStartFraction double
Highest fraction of the available space the start pane may take (0.0-1.0).
final
minStartFraction double
Lowest fraction of the available space the start pane may take (0.0-1.0).
final
onChanged ValueChanged<SplitterChangeDetails>?
Called as the divider moves through an interaction or a collapse, with both the request and the resolved layout plus the SplitterChangeSource.
final
onChangeEnd ValueChanged<SplitterChangeDetails>?
Called when a drag gesture ends, balancing every onChangeStart with exactly one end so a consumer can pair them (e.g. to clear a "dragging" flag). SplitterChangeDetails.end reports how it ended: SplitterChangeEnd.committed for a normal release (the source is SplitterChangeSource.snap when a snap point claimed it) or SplitterChangeEnd.canceled for a system cancel (nothing is committed). The one unbalanced case is a drag force-ended by reconfiguring or disposing the splitter mid-gesture, which fires no end.
final
onChangeStart ValueChanged<SplitterChangeDetails>?
Called when a drag gesture starts, with the position at that moment - the real request, which may be a pixel pin.
final
onHandleDoubleTap VoidCallback?
Called when the divider is double-tapped.
final
onHandleTap VoidCallback?
Called when the divider is tapped.
final
pageStep double?
Step applied with PageUp/PageDown keys (e.g., 0.1 = 10%). Defaults to 0.1.
final
resizable bool
Whether the divider responds to drag gestures.
final
restorationId String?
Restoration id for persisting the divider position across app restarts.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
semantics SplitterSemanticsLabels?
Localizable semantics strings and value formatting. Unset fields fall back to ResizableSplitterTheme, then to the built-in English defaults. Set it app-wide via the theme to localize every splitter at once.
final
semanticsLabel String?
Accessibility label for the divider. Overrides the label resolved from semantics (or the ambient theme) when set, leaving the value formatting intact - a quick way to relabel a single splitter without supplying a full SplitterSemanticsLabels.
final
shieldPlatformViews bool?
Whether the protective overlay is used while dragging. Defaults to true.
final
snap SplitterSnapBehavior?
Optional snap behavior for the divider, or null for no snapping.
final
snapToPhysicalPixels bool?
Floors the leading panel size to whole physical pixels to avoid anti-alias gaps. Defaults to false.
final
start Widget
The widget to display in the start position (left/top).
final
startConstraints SplitterPaneConstraints
Pixel sizing limits for the start (left/top) pane. Defaults to a 100px minimum. Set SplitterPaneConstraints.maxExtent to cap the pane, or SplitterPaneConstraints.collapsible to allow collapsing.
final
surplusPolicy SplitterSurplusPolicy
Policy applied when both panes' maximums are too small to fill the space (a surplus). Defaults to SplitterSurplusPolicy.leaveGap, which keeps SplitterPaneConstraints.maxExtent a true maximum (the leftover becomes a gap between the panes rather than overflowing one past its maximum).
final
unboundedBehavior UnboundedBehavior?
Fallback layout behavior when constraints are unbounded along the main axis. Defaults to UnboundedBehavior.shrinkToChildren.
final

Methods

createElement() StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() State<ResizableSplitter>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
override
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a one-line detailed description of the object.
inherited
toStringShort() String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited