GlassSegmentedControl class
A glass morphism segmented control following Apple's design patterns.
GlassSegmentedControl provides a sophisticated segmented control with an animated glass indicator, jelly physics, and smooth transitions between segments. It matches iOS's UISegmentedControl appearance and behavior.
Key Features
- Animated Glass Indicator: Smoothly animates between segments
- Jelly Physics: Organic squash and stretch effects during movement
- Drag Support: Swipe between segments with velocity-based snapping
- Sharp Text: Selected text stays sharp above the glass
- Flexible Sizing: Automatically sizes segments evenly
- Customizable Appearance: Full control over colors, sizes, and effects
Performance Note
When placing inside glass containers (GlassCard) with blur, use one of these approaches for best performance:
- Set parent container to
quality: GlassQuality.premium(no BackdropFilter) - Or set parent settings to
blur: 0(skips BackdropFilter) - Or place outside glass containers (like bottom bars)
Standard quality glass containers with blur may show minor flicker during indicator animations due to BackdropFilter recomposition.
Usage
Basic Usage
int selectedIndex = 0;
GlassSegmentedControl(
segments: const [
GlassSegment(label: 'Daily'),
GlassSegment(label: 'Weekly'),
GlassSegment(label: 'Monthly'),
],
selectedIndex: selectedIndex,
onSegmentSelected: (index) {
setState(() => selectedIndex = index);
},
)
Within LiquidGlassLayer (Grouped Mode)
AdaptiveLiquidGlassLayer(
settings: LiquidGlassSettings(
thickness: 30,
blur: 3,
refractiveIndex: 1.59,
),
child: Column(
children: [
GlassSegmentedControl(
segments: const [
GlassSegment(label: 'One'),
GlassSegment(label: 'Two'),
GlassSegment(label: 'Three'),
],
selectedIndex: _selectedIndex,
onSegmentSelected: (index) {
setState(() => _selectedIndex = index);
},
),
],
),
)
Standalone Mode
GlassSegmentedControl(
segments: const [
GlassSegment(label: 'Option A'),
GlassSegment(label: 'Option B'),
],
selectedIndex: _selectedIndex,
onSegmentSelected: (index) {
setState(() => _selectedIndex = index);
},
useOwnLayer: true,
settings: LiquidGlassSettings(
thickness: 30,
blur: 3,
),
)
Icons and labels
GlassSegmentedControl(
segments: const [
GlassSegment(icon: Icon(Icons.photo), label: 'Photos'),
GlassSegment(icon: Icon(Icons.videocam), label: 'Videos'),
GlassSegment(icon: Icon(Icons.music_note),label: 'Music'),
],
selectedIndex: _selectedIndex,
onSegmentSelected: (index) =>
setState(() => _selectedIndex = index),
height: 56,
)
Custom Styling
GlassSegmentedControl(
segments: const [
GlassSegment(label: 'Small'),
GlassSegment(label: 'Medium'),
GlassSegment(label: 'Large'),
],
selectedIndex: _selectedIndex,
onSegmentSelected: (index) =>
setState(() => _selectedIndex = index),
height: 36,
borderRadius: 18,
selectedTextStyle: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: CupertinoColors.white,
),
unselectedTextStyle: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: CupertinoColors.white.withOpacity(0.6),
),
)
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatefulWidget
- GlassSegmentedControl
Constructors
-
GlassSegmentedControl({required List<
GlassSegment> segments, required int selectedIndex, required ValueChanged<int> onSegmentSelected, Key? key, double height = GlassDefaults.heightControl, double borderRadius = GlassDefaults.borderRadius, EdgeInsetsGeometry padding = const EdgeInsets.all(2), TextStyle? selectedTextStyle, TextStyle? unselectedTextStyle, Color? backgroundColor, Color? indicatorColor, LiquidGlassSettings? indicatorSettings, double indicatorPinchStrength = 0.4, EdgeInsetsGeometry indicatorExpansion = const EdgeInsets.symmetric(horizontal: 12, vertical: 8), LiquidGlassSettings? settings, bool useOwnLayer = false, GlassQuality? quality, GlobalKey<State< ? backgroundKey, GlassInteractionBehavior interactionBehavior = GlassInteractionBehavior.full, Color? glowColor, double glowRadius = 1.5, bool isScrollable = false, double iconSize = 24.0, EdgeInsetsGeometry labelPadding = const EdgeInsets.symmetric(horizontal: 16), Color? selectedIconColor, Color? unselectedIconColor, MaskingQuality maskingQuality = MaskingQuality.high, DividerSettings? dividerSettings, List<StatefulWidget> >BoxShadow> ? indicatorShadow}) -
Creates a fixed-width glass segmented control (iOS UISegmentedControl).
const
-
GlassSegmentedControl.scrollable({required List<
GlassSegment> segments, required int selectedIndex, required ValueChanged<int> onSegmentSelected, Key? key, double height = 44.0, double borderRadius = GlassDefaults.borderRadius, EdgeInsetsGeometry padding = const EdgeInsets.all(2), TextStyle? selectedTextStyle, TextStyle? unselectedTextStyle, Color? backgroundColor, Color? indicatorColor, LiquidGlassSettings? indicatorSettings, double indicatorPinchStrength = 0.4, EdgeInsetsGeometry indicatorExpansion = const EdgeInsets.symmetric(horizontal: 12, vertical: 8), LiquidGlassSettings? settings, bool useOwnLayer = false, GlassQuality? quality, GlobalKey<State< ? backgroundKey, double iconSize = 24.0, EdgeInsetsGeometry labelPadding = const EdgeInsets.symmetric(horizontal: 16), Color? selectedIconColor, Color? unselectedIconColor, MaskingQuality maskingQuality = MaskingQuality.high, DividerSettings? dividerSettings, List<StatefulWidget> >BoxShadow> ? indicatorShadow}) -
Creates a scrollable glass segmented control that 100% mimics
GlassTabBar
(isScrollable: true)from the original API.const
Properties
- backgroundColor → Color?
-
Background color of the segmented control.
final
-
backgroundKey
→ GlobalKey<
State< ?StatefulWidget> > -
Optional background key for Skia/Web refraction.
final
- borderRadius → double
-
Border radius of the segmented control.
final
- dividerSettings → DividerSettings?
-
Optional divider settings between segments. Scrollable mode only.
final
- glowColor → Color?
-
Colour of the press/drag glow on the indicator pill.
final
- glowRadius → double
-
Spread radius of the glow relative to the indicator's shorter dimension.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- height → double
-
Height of the segmented control.
final
- iconSize → double
-
Icon size in logical pixels. Used in scrollable mode only.
Defaults to 24.0 — matching GlassTabBar.
final
- indicatorColor → Color?
-
Color of the indicator when not being dragged.
final
- indicatorExpansion → EdgeInsetsGeometry
-
Expansion padding applied to the active indicator pill during interaction.
final
- indicatorPinchStrength → double
-
Maximum concave lens pinch strength for the sliding indicator pill.
final
- indicatorSettings → LiquidGlassSettings?
-
Glass settings for the draggable indicator.
final
-
indicatorShadow
→ List<
BoxShadow> ? -
Optional box shadows on the pill indicator. Scrollable mode only.
final
- interactionBehavior → GlassInteractionBehavior
-
Controls which iOS 26 interaction effects are active on the indicator.
final
- isScrollable → bool
-
Whether this control scrolls horizontally.
final
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- labelPadding → EdgeInsetsGeometry
-
Horizontal padding inside each tab label cell. Scrollable mode only.
final
- maskingQuality → MaskingQuality
-
Masking quality for the dual-layer icon rendering. Scrollable mode only.
final
-
onSegmentSelected
→ ValueChanged<
int> -
Called when a segment is selected.
final
- padding → EdgeInsetsGeometry
-
Padding around the indicator inside the background.
final
- quality → GlassQuality?
-
Rendering quality for the glass effect.
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
-
segments
→ List<
GlassSegment> -
List of segments to display.
final
- selectedIconColor → Color?
-
Icon color for the selected segment. Scrollable mode only.
Defaults to the primary label color.
final
- selectedIndex → int
-
Index of the currently selected segment.
final
- selectedTextStyle → TextStyle?
-
Text style for the selected segment.
final
- settings → LiquidGlassSettings?
-
Glass effect settings (only used when useOwnLayer is true).
final
- unselectedIconColor → Color?
-
Icon color for unselected segments. Scrollable mode only.
Defaults to the secondary label color.
final
- unselectedTextStyle → TextStyle?
-
Text style for unselected segments.
final
- useOwnLayer → bool
-
Whether to create its own layer or use grouped glass.
final
Methods
-
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree.
inherited
-
createState(
) → State< GlassSegmentedControl> -
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.
inherited
-
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