هيكل التطبيق
الهيكل، والأشرطة التي تطفو فوق الصفحة، ومنافذ الأيقونات التي تقبلها.
LiquidGlassScaffold
صنفLiquidGlassScaffoldAdaptivity
صنفLiquidGlassAppBar
صنفLiquidGlassTabBar
صنفLiquidGlassTabBarItem
صنفLiquidGlassTabBarAction
صنفLiquidGlassTabItemStyle
صنفLiquidGlassTabPillStyle
صنفLiquidGlassTabMagnifierPillStyle
تعدادLiquidGlassPillMode
صنفLiquidGlassGlyph
نوع مُسمّىLiquidGlassGlyphBuilder
صنفLiquidGlassLabel
نوع مُسمّىLiquidGlassLabelBuilder
A Scaffold-style layout for liquid-glass UIs.
LiquidGlassScaffold owns a single LiquidGlassView internally so you don't have to wire one up by hand. Your page content goes in body and becomes the background that every glass slot refracts; the appBar, bottomNavigationBar, and bottomNavigationBarAction are placed on top of it as ordinary widgets (typically the package's LiquidGlassLens-based components).
The renderer is chosen automatically — Impeller devices sample the live backdrop, Skia / Web fall back to a captured snapshot — so the same scaffold runs on both.
Z-order
Slots are composited bottom-to-top: lenses → appBar → bottomNavigationBar → bottomNavigationBarAction → floatingActionButton → dialog.
With a glass-pill LiquidGlassTabBar the bar runs two views and places the slots by renderer. On Impeller they sit in its outer view, over the bar's cells and the moving pill, so the order above holds. On Skia they ride its inner view — over the captured body, above the bar's capsule but below its cells and the pill — and the outer view holds the pill and nothing else: that view captures the whole screen a second time, and keeping the chrome out of it is what lets the capture sleep whenever the pill is at rest. So on Skia the bar's cells and pill paint over a lenses entry that overlaps them, and the dialog barrier dims the body and the capsule but not the cells or the pill.
LiquidGlassScaffold(
appBar: LiquidGlassAppBar(
title: const Text('Gallery'),
actions: const [Icon(Icons.search)],
),
body: MyPageContent(),
bottomNavigationBar: LiquidGlassTabBar(
items: const [
LiquidGlassTabBarItem(icon: Icons.home_rounded, label: 'Home'),
LiquidGlassTabBarItem(icon: Icons.search_rounded, label: 'Search'),
LiquidGlassTabBarItem(icon: Icons.person_rounded, label: 'You'),
],
selectedIndex: _index,
onChanged: (i) => setState(() => _index = i),
),
bottomNavigationBarAction: LiquidGlassTabBarAction(
icon: Icons.add_rounded,
onTap: _compose,
),
)المُنشئات
const LiquidGlassScaffold({ super.key, required this.body, this.appBar, this.bottomNavigationBar, this.bottomNavigationBarAction, this.floatingActionButton, this.floatingActionButtonAlignment = AlignmentDirectional.bottomEnd, this.floatingActionButtonClearance, this.dialog, this.onDialogDismissed, this.dialogBarrierColor = const Color(0x80000000), this.dialogBarrierDismissible = true, this.dialogTransitionDuration = const Duration(milliseconds: 350), this.lenses = const [], this.backgroundColor, this.safeArea = true, this.appBarTopMargin = 0, this.actionMargin = 16, this.controller, this.pixelRatio = 1.0, this.realTimeCapture = true, this.useSync = true, this.refreshRate = LiquidGlassRefreshRate.deviceRefreshRate, this.useImpellerBackdrop, this.batch = true, this.adaptivity, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
key | Key? | — | |
bodyمطلوب | Widget | — | The primary content of the screen. Rendered behind every glass slot and used as the background the lenses refract. |
appBar | Widget? | — | A glass app bar pinned to the top. Typically a LiquidGlassAppBar. |
bottomNavigationBar | Widget? | — | A glass bottom navigation bar pinned to the bottom. Typically a LiquidGlassTabBar. |
bottomNavigationBarAction | Widget? | — | A standalone glass action that floats at the bottom-right, the common "tab bar + side action" pairing. Typically a LiquidGlassTabBarAction. |
floatingActionButton | Widget? | — | A floating action button, typically a LiquidGlassFab. With the default alignment this shares the bottom-end corner with bottomNavigationBarAction; the button is lifted clear of the bar, so use both only when there is a bottomNavigationBar between them. |
floatingActionButtonAlignment | AlignmentGeometry | AlignmentDirectional.bottomEnd | Position of floatingActionButton. Defaults to the bottom-end corner — bottom-right in LTR, bottom-left in RTL. Pass a plain Alignment to pin a physical side, or any offset to nudge it. |
floatingActionButtonClearance | double? | — | Room kept clear below a bottom-aligned floatingActionButton so it floats above the bottomNavigationBar. Left null the scaffold measures a LiquidGlassTabBar itself. Any other bar can't be measured from here, so it falls back to kFallbackNavClearance — set this when yours is a different height. Ignored unless the button is aligned toward the bottom. |
dialog | Widget? | — | A glass panel laid over the page, inside this scaffold's own view. Unlike showLiquidGlassDialog, which pushes a route, this one is an ordinary widget in the lens layer: it refracts the live body on every backend, and can be merged with the other slots' glass by a LiquidGlassBlender. What it gives up is the navigator — there is no Future to await and no route on the stack, so you hold the open/ closed state yourself and set this back to null to close it. Typically a LiquidGlassDialog or LiquidGlassAlertDialog. |
onDialogDismissed | VoidCallback? | — | Called when the dialog asks to close — a tap on the barrier or a system back gesture. Clear dialog from here; the panel plays its exit animation on the way out. |
dialogBarrierColor | Color | const Color(0x80000000) | Scrim painted under dialog and over everything else. It fades with the panel and swallows taps meant for the page beneath. |
dialogBarrierDismissible | bool | true | Whether tapping the barrier fires onDialogDismissed. |
dialogTransitionDuration | Duration | const Duration(milliseconds: 350) | How long dialog takes to appear and to leave. |
lenses | List<Widget> | const | Extra free-floating glass widgets composited between the body and the bars. An escape hatch — position each with your own Align/Positioned. |
backgroundColor | Color? | — | Optional solid color painted behind body. Leave null to let body supply its own background. |
safeArea | bool | true | Whether the bars automatically clear the device safe areas. When true (the default), the appBar is pushed below the top inset and the bottom slots above the bottom inset. The body still fills the whole window behind the glass. |
appBarTopMargin | double | 0 | Extra space above the appBar, in addition to the safe-area inset. |
actionMargin | double | 16 | Bottom-right padding applied to bottomNavigationBarAction. |
controller | LiquidGlassViewController? | — | Controls the internal view's capture pipeline. Optional. |
pixelRatio | double | 1.0 | See LiquidGlassView.pixelRatio. |
realTimeCapture | bool | true | See LiquidGlassView.realTimeCapture. |
useSync | bool | true | See LiquidGlassView.useSync. |
refreshRate | LiquidGlassRefreshRate | LiquidGlassRefreshRate.deviceRefreshRate | See LiquidGlassView.refreshRate. |
useImpellerBackdrop | bool? | — | See LiquidGlassView.useImpellerBackdrop. Leave null for automatic Skia / Impeller detection. |
batch | bool | true | See LiquidGlassView.batch. true (the default) puts the glass in body on one shared read of the backdrop and the chrome — app bar, tab bar, action, FAB, dialog, lenses — on another. It is the one chrome batch on both tab bar paths: with a glass pill the bar's capsule sits in its inner view and the slots in the outer one on Impeller, and the scaffold hands both views the same key. A showLiquidGlassSheet or a showLiquidGlassDialog opened from a context inside this scaffold can join that batch too, with batch: true on the call, so the sheet or the dialog costs no read of its own — the same read the tab bar takes. Off by default: each takes a read of its own. With a glass pill tab bar the moving pill and its magnifier keep reads of their own: the pill exists to refract the capsule under it, which no batch member can see. |
adaptivity | LiquidGlassScaffoldAdaptivity? | — | The palettes this scaffold's glass chrome wears, the OS bars it drives, and the strips that judge them — see LiquidGlassScaffoldAdaptivity. null (the default) means nothing adapts unless a widget opts in itself, and the system bars are left untouched. |
الأعضاء الساكنة
| التوقيع | الوصف |
|---|---|
double kFallbackNavClearance | Clearance assumed under the FAB for a bottom bar the scaffold cannot measure. Override it with floatingActionButtonClearance. |
int? chromeBatchIdOf(BuildContext context) | The key of the chrome batch of the nearest enclosing scaffold, or null outside one or with its batch off. What showLiquidGlassSheet and showLiquidGlassDialog read from the context they are called with when asked to batch, to put what they present on the scaffold's chrome read — see batch. Library-internal. |
معرَّف في lib/src/widgets/components/liquid_glass_scaffold.dart
The scaffold's adaptivity: the palettes its glass chrome wears, and the edge strips that drive the system bars.
Two jobs, deliberately kept apart:
- System chrome. For every side
systemChromeasks for — the status bar by default — the scaffold pins an invisible strip along that screen edge, the status bar's at the top and the navigation bar's at the bottom, samples it, and drives that bar's icon brightness from the result. A strip judges nothing but its own system bar. - Chrome palettes.
adaptivityis handed down to the app bar, the bottom bar, the action button and anylenses, each of which resolves its own verdict from the background directly behind itself. One config, one verdict per surface.
A strip never captures the chrome: the app bar is judged by the pixels behind the app bar, not by the status bar's strip. Coupling goes the other way round — point a strip at an area's link with topFollowLink / bottomFollowLink and the system bar mirrors that area's verdict. A following strip stops sampling entirely, so it has no region of its own and topHeight / bottomHeight no longer apply to it.
The config's own link is deliberately never inherited by the chrome — otherwise every surface would follow it by accident.
A surface escapes the inherited palettes with LiquidGlassAdaptivity.none; its own style.adaptivity overrides them. LiquidGlassScaffold.adaptivity left null (the default) → nothing adapts unless a widget opts in itself, and no strip is pinned: with nothing to sample there is nothing to tell the OS bars.
المُنشئات
const LiquidGlassScaffoldAdaptivity(this.adaptivity, { this.systemChrome = LiquidGlassSystemChrome.statusBar, this.topFollowLink, this.bottomFollowLink, this.sampling = const LiquidGlassAdaptiveSampling(), this.topHeight, this.bottomHeight, this.debugBounds = false, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
adaptivity | LiquidGlassAdaptivity | — | Palettes, thresholds and controller for the scaffold's glass chrome and for the system-bar strips. Inherited by every chrome surface — minus its link, which is never inherited (see topLink). |
systemChrome | LiquidGlassSystemChrome | LiquidGlassSystemChrome.statusBar | Which OS bars this scaffold's verdict also drives — icon brightness only, never bar colours. Each requested side pins an invisible strip along that screen edge, samples it, and annotates that bar from the result. The strips judge only the system bars; the glass chrome judges its own backdrop. Defaults to LiquidGlassSystemChrome.statusBar — the bar the glass chrome sits under on every screen. Pass LiquidGlassSystemChrome.none to leave the OS bars alone: nothing goes in the tree at all. It lives here, and not on the scaffold, because a strip is only worth pinning where there is something to judge from: a scaffold with no adaptivity never touches the bars. |
topFollowLink | LiquidGlassAdaptivityLink? | — | Makes the TOP strip follow this link instead of judging the status bar's own band — hand it the link a LiquidGlassAdaptiveArea publishes on and the status bar mirrors that area. A following strip samples nothing, so it has no region and topHeight is ignored: there is no pixel height to get wrong. It inherits the area's verdict wholesale, including a permanentBrightness the area may be pinned to. |
bottomFollowLink | LiquidGlassAdaptivityLink? | — | Makes the BOTTOM strip follow this link instead of judging the navigation bar's own band. See topFollowLink; bottomHeight is likewise ignored while following. |
sampling | LiquidGlassAdaptiveSampling | const LiquidGlassAdaptiveSampling() | Tuning of the background-luminance sampler serving the strips and the chrome — see LiquidGlassAdaptiveSampling. The default is the standard tiny capture (pixelRatio 0.05, 8 samples/s), so it never needs to be written unless you want different numbers. |
topHeight | double? | — | How tall a band the TOP system bar is judged from, measured from the top screen edge (the status bar is inside it, not added to it). null — the default — derives it from the safe-area inset, floored so a zero inset (safeArea: false) still samples something instead of freezing the chrome. Ignored while topFollowLink is set: a following strip judges nothing. Prefer following an area over guessing a height. |
bottomHeight | double? | — | How tall a band the BOTTOM system bar is judged from, measured from the bottom screen edge. null = the safe-area inset, floored — gesture navigation leaves only a few pixels. Ignored while bottomFollowLink is set. |
debugBounds | bool | false | Debug: outline each strip the scaffold pins (cyan), so the invisible strips' size and position can be verified on screen. Same idea as the blender's debugClipBounds. Off by default. |
معرَّف في lib/src/widgets/components/liquid_glass_scaffold.dart
A floating, drop-in liquid-glass app bar — a translucent bar with an optional leading widget, a title, and trailing actions, all refracting the content behind it.
Place it wherever you want the bar to sit (a top-aligned Stack child, the appBar: slot of a LiquidGlassScaffold, …). It is a single LiquidGlassLens around its content, so on Impeller it works standalone and on Skia / Web it needs an ancestor LiquidGlassView with a background.
Styling uses the LiquidGlassLens vocabulary — shape, appearance, refraction — each defaulted to a tuned glass. Foreground color is applied to icons and text through an IconTheme / DefaultTextStyle, so a plain Icon(...) or Text(...) automatically picks up foregroundColor.
LiquidGlassScaffold(
appBar: LiquidGlassAppBar(
leading: const Icon(Icons.menu),
title: const Text('Gallery'),
actions: const [Icon(Icons.search), Icon(Icons.more_vert)],
),
body: myPageContent,
)المُنشئات
const LiquidGlassAppBar({ super.key, this.leading, this.title, this.actions = const [], this.centerTitle = true, this.height = 56, this.width = 360, this.horizontalPadding = 14, this.actionSpacing = 8, this.style, this.visibility = true, this.foregroundColor, this.fontSize = 18, this.touch, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
key | Key? | — | |
leading | Widget? | — | Leading widget (typically a menu or back button), shown at the start of the bar. |
title | Widget? | — | The bar's title. Usually a Text; inherits foregroundColor and a semi-bold style unless the widget overrides it. |
actions | List<Widget> | const | Trailing widgets (search, overflow menu, avatar, …), laid out at the end of the bar in order. |
centerTitle | bool | true | Whether the title is centered. When false the title is left-aligned next to the leading widget (Material style). |
height | double | 56 | Bar height; also drives the default pill radius (height / 2). |
width | double? | 360 | Explicit width. When null the bar hugs its content. Defaults to a wide floating capsule. |
horizontalPadding | double | 14 | Horizontal padding between the bar rim and its content. |
actionSpacing | double | 8 | Spacing between the action widgets. |
style | LiquidGlassStyle? | — | The bar's glass look as one LiquidGlassStyle (shape + appearance + refraction), taken as the complete look. When null the tuned defaultStyle is used. Its shape may be null, in which case a full pill with a tuned optical border is used. To tweak one facet while keeping the rest of the tuned look, compose with copyWith, e.g. style: LiquidGlassAppBar.defaultStyle.copyWith(...). |
visibility | bool | true | Whether the bar is shown; toggling animates the glass in/out. |
foregroundColor | Color? | — | Color applied to icons and text inside the bar. null (the default) means white — or, while the bar's adaptivity is active, the animated adaptive content color. An explicit color always wins and never adapts. Adaptivity outranks this. On an adaptive surface the color comes from the verdict, whatever is named here — a pinned foreground would otherwise defeat the one thing adaptivity exists to guarantee. Opt the surface out with adaptivity: LiquidGlassAdaptivity.none to pin a color on it. |
fontSize | double | 18 | Font size of the title when it is a plain Text. |
touch | LiquidGlassTouch? | — | How the bar answers a finger — see LiquidGlassTouch. With a LiquidGlassTouch.flex the whole bar deforms as one body under a press or a drag, then springs back. The bar does not move. null (the default) leaves the glass rigid — no gesture listener, no ticker, nothing added to the tree. A bar is a large surface, so prefer a restrained spec such as LiquidGlassFlex.subtle if you enable it. |
الأعضاء الساكنة
| التوقيع | الوصف |
|---|---|
LiquidGlassStyle defaultStyle | The tuned default look — a faint white frost over a soft optical refraction. Its shape is null: the bar derives a height-tracking full pill with an optical border when style supplies no shape. Compose with copyWith to tweak one facet, e.g. style: LiquidGlassAppBar.defaultStyle.copyWith(...). |
معرَّف في lib/src/widgets/components/liquid_glass_app_bar.dart
A floating, drop-in liquid-glass bottom navigation bar.
It is a single LiquidGlassLens capsule with the icons, labels, and the selection highlight baked into the lens child — so drop it wherever you want the bar to sit (most commonly the bottomNavigationBar: slot of a LiquidGlassScaffold).
The bar capsule's look is one LiquidGlassStyle (style — shape + appearance + refraction), plus grouped itemStyle / pillStyle descriptors for the icons and selection pill.
By default the selection moves instantly between tabs. Set the pill style's animated: true to make the selection pill slide. When pillStyle's mode enables the glass-refracting morph pill, a LiquidGlassScaffold swaps in the self-contained dual-pipeline variant via buildGlassPillBar.
المُنشئات
const LiquidGlassTabBar({ super.key, required this.items, required this.selectedIndex, required this.onChanged, this.itemStyle = const LiquidGlassTabItemStyle(), this.pillStyle = const LiquidGlassTabPillStyle(), this.style, this.visibility = true, this.width = 300, this.height = 64, this.margin = const EdgeInsets.only(bottom: 24), this.itemPadding = 6, this.alignment = Alignment.bottomCenter, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
key | Key? | — | |
itemsمطلوب | List<LiquidGlassTabBarItem> | — | The tab items. |
selectedIndexمطلوب | int | — | The selected tab index. |
onChangedمطلوب | ValueChanged<int> | — | Selection callback. |
itemStyle | LiquidGlassTabItemStyle | const LiquidGlassTabItemStyle() | Icon + label styling of the tabs (colors, icon size, label font). |
pillStyle | LiquidGlassTabPillStyle | const LiquidGlassTabPillStyle() | Everything about the selection pill — highlight look, slide animation, and the glass-refracting morph mode. |
style | LiquidGlassStyle? | — | The bar capsule's look as one LiquidGlassStyle (shape + appearance + refraction), taken as the complete look. When null the tuned defaultStyle (full-pill optical-border shape, faint white tint, default refraction) is used. To keep the tuned default but change a single facet, compose with copyWith, e.g. LiquidGlassTabBar.defaultStyle.copyWith(shape: …). Honored by both the plain and glass-pill bars. |
visibility | bool | true | Whether the bar is shown; toggling animates the glass in/out. |
width | double | 300 | Capsule width. |
height | double | 64 | Capsule height; also drives the default pill radius (height / 2). |
margin | EdgeInsets | const EdgeInsets.only(bottom: 24) | Outer margin honored by a host (e.g. LiquidGlassScaffold) when placing the bar. margin.bottom is the gap above the bottom edge (the safe-area inset is added on top of it); margin.left/ margin.right inset the bar from the matching edge. The bar has a fixed width, so on a centered bar symmetric left/right values are a no-op while an asymmetric pair shifts it off-center; the side insets matter most when alignment is biased to an edge. |
itemPadding | double | 6 | Inner padding between the capsule rim and the icon row. |
alignment | Alignment | Alignment.bottomCenter | Where the bar floats within its host. Defaults to Alignment.bottomCenter. The edge spacing comes from margin: the bottom gap from margin.bottom (plus any safe-area inset) and, when the alignment is biased to a side (e.g. Alignment.bottomLeft), the horizontal inset from margin.left/margin.right. Honored by LiquidGlassScaffold on both the plain and glass-pill paths. |
const LiquidGlassTabBar.withImpeller({ super.key, required this.items, required this.selectedIndex, required this.onChanged, this.itemStyle = const LiquidGlassTabItemStyle(), this.pillStyle = const LiquidGlassTabPillStyle(), this.style, this.visibility = true, this.width = 300, this.height = 64, this.margin = const EdgeInsets.only(bottom: 24), this.itemPadding = 6, this.alignment = Alignment.bottomCenter, })Impeller-only, bodyless morph-pill bar: the animated glass-refracting morph selection pill WITHOUT a captured body.
| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
key | Key? | — | |
itemsمطلوب | List<LiquidGlassTabBarItem> | — | The tab items. |
selectedIndexمطلوب | int | — | The selected tab index. |
onChangedمطلوب | ValueChanged<int> | — | Selection callback. |
itemStyle | LiquidGlassTabItemStyle | const LiquidGlassTabItemStyle() | Icon + label styling of the tabs (colors, icon size, label font). |
pillStyle | LiquidGlassTabPillStyle | const LiquidGlassTabPillStyle() | Everything about the selection pill — highlight look, slide animation, and the glass-refracting morph mode. |
style | LiquidGlassStyle? | — | The bar capsule's look as one LiquidGlassStyle (shape + appearance + refraction), taken as the complete look. When null the tuned defaultStyle (full-pill optical-border shape, faint white tint, default refraction) is used. To keep the tuned default but change a single facet, compose with copyWith, e.g. LiquidGlassTabBar.defaultStyle.copyWith(shape: …). Honored by both the plain and glass-pill bars. |
visibility | bool | true | Whether the bar is shown; toggling animates the glass in/out. |
width | double | 300 | Capsule width. |
height | double | 64 | Capsule height; also drives the default pill radius (height / 2). |
margin | EdgeInsets | const EdgeInsets.only(bottom: 24) | Outer margin honored by a host (e.g. LiquidGlassScaffold) when placing the bar. margin.bottom is the gap above the bottom edge (the safe-area inset is added on top of it); margin.left/ margin.right inset the bar from the matching edge. The bar has a fixed width, so on a centered bar symmetric left/right values are a no-op while an asymmetric pair shifts it off-center; the side insets matter most when alignment is biased to an edge. |
itemPadding | double | 6 | Inner padding between the capsule rim and the icon row. |
alignment | Alignment | Alignment.bottomCenter | Where the bar floats within its host. Defaults to Alignment.bottomCenter. The edge spacing comes from margin: the bottom gap from margin.bottom (plus any safe-area inset) and, when the alignment is biased to a side (e.g. Alignment.bottomLeft), the horizontal inset from margin.left/margin.right. Honored by LiquidGlassScaffold on both the plain and glass-pill paths. |
الخصائص
| الاسم | النوع | الوصف |
|---|---|---|
glassPill | LiquidGlassPillMode | Which renderer(s) use the glass-refracting morphing pill. |
effectiveBarStyle | LiquidGlassStyle | The bar capsule's resolved look: the tuned defaultStyle when no style is given, otherwise style taken as the whole look — its appearance + refraction replace the defaults wholesale (matching how every other component merges a style). Its shape falls back to defaultStyle's when null; shape may still be null here, in which case build / buildGlassPillBar supply the height-derived capsule. To tweak a single facet while keeping the rest of the tuned look, compose from the default rather than passing a bare style, e.g. style: LiquidGlassTabBar.defaultStyle.copyWith(shape: …). |
الدوال
| التوقيع | الوصف |
|---|---|
bool resolveGlassPill({bool? useImpellerBackdrop}) | Whether glassPill resolves to the glass-refracting morphing pill on the active renderer. |
Widget buildGlassPillBar({ required Widget body, Widget? chromeChild, Widge… | Builds the self-contained dual-pipeline variant of this bar — the glass-refracting morphing pill. Hosts like LiquidGlassScaffold check resolveGlassPill and call this, passing their slots through. body is the page content captured behind the glass. chromeChild is the host's chrome (app bar, side action, extra lenses, dialog) — a full-screen Stack of lens-anywhere widgets — which the bar places by renderer: in the outer view over the bar and the pill on Impeller, in the inner view under the bar's cells on Skia, where the outer capture then sleeps whenever the pill is at rest. outerChild is the explicit outer slot on both renderers; pass outerNeedsRealtime while it is showing. bottomInset is the safe-area bottom inset. |
LiquidGlassPosition? resolveBarPosition({double bottomInset = 0}) | The bar's placement derived from alignment and margin, or null for the default bottom-center anchor with no horizontal margin (so the centered fast-path is kept untouched). bottomInset is the host's safe-area bottom inset, folded into margin.bottom. |
الأعضاء الساكنة
| التوقيع | الوصف |
|---|---|
LiquidGlassStyle defaultStyle | The tuned default capsule look — a faint white frost over the default refraction. Its shape is null: the bar derives a height-tracking full-pill optical-border shape when style supplies no shape. Compose with copyWith to tweak one facet while keeping the rest of the tuned look, e.g. style: LiquidGlassTabBar.defaultStyle.copyWith(shape: …). |
معرَّف في lib/src/widgets/components/bottom_nav_bar/liquid_glass_tab_bar.dart
Description of a single tab in LiquidGlassTabBar.
المُنشئات
const LiquidGlassTabBarItem({ this.icon, this.selectedIcon, this.label, this.iconBuilder, this.labelBuilder, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
icon | IconData? | — | Icon shown when the tab is unselected. Ignored when iconBuilder is set — and may be left null when the builder draws the tab entirely. |
selectedIcon | IconData? | — | Icon shown when the tab is selected (defaults to icon). Ignored when iconBuilder is set — the builder gets the selected state instead and picks its own art. |
label | String? | — | Optional label below the icon. When null the tab renders icon only, matching the modern liquid-glass minimal style. |
iconBuilder | LiquidGlassGlyphBuilder? | — | Draws the glyph instead of icon — for artwork Flutter's Icon can't render (SVG, PNG, a CustomPaint, a badge). Honored by every tier: the plain bar, the sliding bar, the glass-pill bar and the tab bar. The builder receives the resolved color for the layer being drawn and whether that layer is the selected one, so tinting with LiquidGlassGlyph.color and switching art on LiquidGlassGlyph.selected reproduces exactly what icon + selectedIcon do — including the moving pill's reveal. |
labelBuilder | LiquidGlassLabelBuilder? | — | Draws the label instead of the plain Text built from label — for a custom font, rich text, a badge row. Honored by every tier, like iconBuilder. The builder receives the resolved color, font size and weight for the layer being drawn (see LiquidGlassLabel.textStyle), so a custom label follows every state change the built-in labels follow — including the moving pill's reveal. label may still be set as the text to render, or left null for builder-only content. |
الخصائص
| الاسم | النوع | الوصف |
|---|---|---|
hasLabel | bool | Whether this tab renders a label line at all — a label string, a labelBuilder, or both. |
معرَّف في lib/src/widgets/components/liquid_glass_tab_item.dart
Companion floating action button rendered as its own liquid-glass pill, mirroring the pattern of pairing a tab bar with a separate, side-floating action (often Search).
المُنشئات
const LiquidGlassTabBarAction({ super.key, this.icon, this.onTap, this.foregroundColor, this.size = 56, this.style, this.visibility = true, this.child, this.touch, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
key | Key? | — | |
icon | IconData? | — | The action glyph. Ignored when child is set. |
onTap | VoidCallback? | — | Tap callback. |
foregroundColor | Color? | — | Color of the glyph. null (the default) means white — or, while the action's adaptivity is active, the animated adaptive content color. An explicit color always wins and never adapts. Adaptivity outranks this. On an adaptive surface the color comes from the verdict, whatever is named here — a pinned foreground would otherwise defeat the one thing adaptivity exists to guarantee. Opt the surface out with adaptivity: LiquidGlassAdaptivity.none to pin a color on it. |
size | double | 56 | Diameter of the circular button. |
style | LiquidGlassStyle? | — | The action's glass look as one LiquidGlassStyle (shape + appearance + refraction), taken as the complete look. When null the tuned defaultStyle is used; its shape may be null, in which case a circular pill mirroring the bottom-nav capsule rim is used. To tweak one facet while keeping the rest, compose with copyWith, e.g. style: LiquidGlassTabBarAction.defaultStyle.copyWith(...). |
visibility | bool | true | Whether the button is shown; toggling animates the glass in/out. |
child | Widget? | — | Custom content replacing icon. Centered in the button and scaled down when it exceeds it, so it never sizes the button — that stays a size-diameter circle and the lens geometry holds. A bare Icon/Text inside it inherits foregroundColor; give the widget its own color (or an SvgPicture its own colorFilter) to paint it yourself. |
touch | LiquidGlassTouch? | — | Makes the button deform under touch without moving it — press and it swells, drag and it elongates along the pull, then springs back. See LiquidGlassTouch; null (the default) disables it entirely. |
الأعضاء الساكنة
| التوقيع | الوصف |
|---|---|
LiquidGlassStyle defaultStyle | The tuned default look — a transparent body over a soft optical refraction. Its shape is null: the action derives a circular pill when style supplies no shape. Compose with copyWith to tweak one facet, e.g. style: LiquidGlassTabBarAction.defaultStyle.copyWith(...). |
معرَّف في lib/src/widgets/components/liquid_glass_tab_item.dart
Item group for LiquidGlassTabBar: how each tab's icon and label render. Defaults mirror the bar's flat parameters, so swapping APIs is lossless.
المُنشئات
const LiquidGlassTabItemStyle({ this.selectedColor = Colors.white, this.unselectedColor = Colors.white70, this.iconSize = 24, this.underGlassIconSize, this.labelFontSize = 10.5, this.underGlassLabelFontSize, this.iconLabelGap = 2, this.selectedFontWeight = FontWeight.w600, this.unselectedFontWeight = FontWeight.w500, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
selectedColor | Color | Colors.white | Color of the selected item's icon + label. |
unselectedColor | Color | Colors.white70 | Color of unselected items' icons + labels. |
iconSize | double | 24 | Icon size for every item. |
underGlassIconSize | double? | — | Icon size for the item under the glass — and only there. null (the default) keeps iconSize, so nothing changes unless asked. This is the glass's state, not the selection's: it applies while the moving glass pill is over an item — lifted on it, dragging across it, sweeping past it mid-travel — and it scales with how much of the pill still reads as glass, so as the landed pill sheds into the static rest pill the icon glides back down to iconSize with it instead of popping at the swap. A flat pill is not glass: the static rest highlight, the sliding tier's soft pill and a hidden pill never enlarge anything — a selected tab shows its selection through color and weight alone. While the pill travels, the layer inside it draws at this size while the layer outside stays at iconSize, so mid-slide the clip edge joins two sizes. A modest delta reads as the glass magnifying the icon; a large one reads as a seam. |
labelFontSize | double | 10.5 | Label font size. Labels are only shown for items that provide one. |
underGlassLabelFontSize | double? | — | Label font size for the item under the glass. null (the default) keeps labelFontSize. Same rules as underGlassIconSize: the glass's state, not the selection's. |
iconLabelGap | double | 2 | Vertical gap between the icon and its label, in logical pixels. |
selectedFontWeight | FontWeight | FontWeight.w600 | Font weight of the selected item's label. |
unselectedFontWeight | FontWeight | FontWeight.w500 | Font weight of unselected items' labels. |
الدوال
| التوقيع | الوصف |
|---|---|
Color colorFor({required bool selected}) | Resolves the icon/label color for a cell in selected state. |
double iconSizeFor({required double underGlass}) | Resolves the icon size for a cell by how much glass is over it: a lerp from the shared iconSize (0) to underGlassIconSize (1), so the enlargement fades in and out with the glass itself — through the landing handover it glides back down instead of popping when the static pill takes over. Selection alone never changes size. |
double labelFontSizeFor({required double underGlass}) | Resolves the label font size for a cell by how much glass is over it — same lerp as iconSizeFor. |
FontWeight fontWeightFor({required bool selected}) | Resolves the label weight for a cell in selected state. |
LiquidGlassTabItemStyle copyWith({ Color? selectedColor, Color? unselectedC… |
معرَّف في lib/src/widgets/components/bottom_nav_bar/liquid_glass_nav_bar_style.dart
Selection pill group for LiquidGlassTabBar: everything about the highlight behind the active tab — its look, whether it slides, and whether/where it upgrades to the glass-refracting morphing pill. Defaults mirror the bar's flat parameters, so swapping APIs is lossless.
The three tiers, all configured here:
- glass-refracting morphing pill — the default (
modeLiquidGlassPillMode.both): the dual-pipeline pill that refracts the bar itself. Thedistortion/growHeight/… knobs below apply to this tier only. A settled bar costs no shader pass, no clip and no capture, on either backend. - sliding highlight —
modenone +animatedtrue: the pill slides between tabs with the iOS-26 icon-reveal, drawn inside the lens (works on every renderer); - static highlight —
modenone,animatedfalse: the flat instant highlight, the cheapest tier of all.
المُنشئات
const LiquidGlassTabPillStyle({ this.mode = LiquidGlassPillMode.both, this.show = true, this.color = const Color(0x2EAEAEB2), this.animated = false, this.animationDuration = const Duration(milliseconds: 320), this.animationCurve = Curves.easeOutCubic, this.blur = const LiquidGlassBlur(), this.growHeight = 9, this.distortion = 0.04, this.distortionWidth = 12, this.magnification = 1, this.enableInnerRadiusTransparent = false, this.shape, this.glassStyle, this.rest, this.travelStiffness = 280, this.travelDamping = 31.4, // Tuned for tab-scale travel: the sampling window and response ease of // the motion pill, with the deformation ceiling brought down to ±12 %. this.motion = const LiquidGlassLensMotionSpec( sampleWindow: 0.3, sensitivity: 0.00007, maxDeformation: 0.12, responseTime: 0.18, ), this.magnifierPill = const LiquidGlassTabMagnifierPillStyle(), })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
mode | LiquidGlassPillMode | LiquidGlassPillMode.both | Which renderer(s) use the glass-refracting morphing pill. |
show | bool | true | Whether to draw the soft pill behind the selected item. |
color | Color | const Color(0x2EAEAEB2) | Color of the selection pill behind the active item. |
animated | bool | false | When true, the selection pill slides between tabs with the iOS-26 "icon highlights through the moving pill" reveal. When false the selection jumps instantly. |
animationDuration | Duration | const Duration(milliseconds: 320) | How long the pill takes to slide between tabs (animated only). |
animationCurve | Curve | Curves.easeOutCubic | Easing curve for the pill slide (animated only). |
blur | LiquidGlassBlur | const LiquidGlassBlur() | Blur behind the moving glass pill (glass modes only). |
growHeight | double | 9 | How much taller than the bar the glass pill stands while it is lifted (glass modes only) — the pill's main size knob. It inflates to this the instant a tab is tapped, holds it for the whole travel, and comes back down once it has landed. |
distortion | double | 0.04 | Refraction strength of the moving glass pill (glass modes only). |
distortionWidth | double | 12 | Width of the glass pill's refraction band in logical pixels (glass modes only). |
magnification | double | 1 | Magnification of the content seen through the glass pill (glass modes only). 1 = none. |
enableInnerRadiusTransparent | bool | false | When true, the glass pill's inner area is transparent (glass modes only). |
shape | LiquidGlassShape? | — | Shape of the moving glass pill (glass modes only). When null (the default) the pill is an Apple capsule-style LiquidGlassShape whose corner radius tracks the pill's height, so it stays a clean capsule while it grows and squashes. Supply a custom LiquidGlassShape — e.g. a continuous variant with a smaller cornerRadius for visible continuous corners, or a plain rounded variant — to change the pill's silhouette and rim. Superseded by glassStyle/rest, which bundle shape + fill + refraction per pill state. When glassStyle/rest omit a shape they fall back to this one. |
glassStyle | LiquidGlassStyle? | — | The moving glass pill's full look as one LiquidGlassStyle (shape + fill/blur + refraction). When non-null it supersedes the individual glass-pill fields (shape, blur, distortion, distortionWidth, magnification, enableInnerRadiusTransparent); a null shape inside it falls back to shape. Glass modes only. |
rest | LiquidGlassStyle? | — | The static rest pill's look as one LiquidGlassStyle — the non-refracting highlight shown when the glass pill is not moving (and the fill of the non-glass tiers). Its appearance.color is the pill's background, its shape the corners (falls back to shape), and a border is drawn only when the shape sets a borderColor (default: no border). Refraction is ignored. |
travelStiffness | double | 280 | Stiffness of the spring that carries the glass pill between tabs (glass modes only). Higher → snappier travel. Default 320. |
travelDamping | double | 31.4 | Damping of the travel spring (glass modes only). The critical (no-overshoot) value is 2·√travelStiffness (≈ 36 at the default stiffness): below it the pill bounces, at/above it just settles. Default 30 — a faint settle. |
magnifierPill | LiquidGlassTabMagnifierPillStyle | const LiquidGlassTabMagnifierPillStyle() | The Impeller-only magnifier pill under the moving glass pill — see LiquidGlassTabMagnifierPillStyle. Defaults to enabled at magnification 0.87. |
الخصائص
| الاسم | النوع | الوصف |
|---|---|---|
motion | LiquidGlassLensMotionSpec | The pill's squash/stretch tuning (glass modes only) — the same acceleration model LiquidGlassMotionPill runs, applied to both finger-drags and tap-travel. The pill's drawn position is sampled every frame, differentiated twice, and the averaged acceleration scales it oppositely on the two axes: it stretches wide and flat as it launches off a tab, squashes narrow and tall as it brakes into the next, and sits undeformed at constant speed. Force, not speed. The default caps the deviation at ±12 %, since this pill travels inside the bar capsule and a taller overhang would climb out of it. |
effectiveGlass | LiquidGlassStyle | The moving glass pill's resolved look: glassStyle when set, otherwise built from the individual glass-pill fields (preserving the shipped defaults — pure refraction: no tint of its own, since over glass a fill only flattens the capsule, with a thin-rimmed continuous capsule shape and the flat refraction knobs). |
effectiveRest | LiquidGlassStyle |
الدوال
| التوقيع | الوصف |
|---|---|
LiquidGlassTabPillStyle copyWith({ LiquidGlassPillMode? mode, bool? show, C… |
الأعضاء الساكنة
| التوقيع | الوصف |
|---|---|
LiquidGlassAdaptivity defaultRestAdaptivity | The static rest pill's resolved look: rest when set, otherwise a borderless highlight filled with color (the shipped ~15% white), with corners from shape. A border appears only when the resolved shape carries a borderColor. The palette the static pill flips on whenever the bar adapts and rest names no palette of its own. The bar's adaptivity may be its own style.adaptivity or one inherited from an enclosing LiquidGlassAdaptiveArea / LiquidGlassScaffold — the source makes no difference to what the pill has to do. The pill sits ON the capsule and has to contrast it, so a capsule that darkens over a dark page while the pill holds a fixed light fill leaves a light pill on a dark bar. Set rest's adaptivity to override this palette, or LiquidGlassAdaptivity.none to hold a caller-chosen fill fixed. Opposite polarity to the bar's glass, and the same as its content: the pill has to contrast the BAR it sits on, and an adaptive bar darkens over a dark page and lightens over a light one. The light side runs a little heavier because black on a bright surface needs more alpha to read as the same step — at 18%/20% both land near a 1.6:1 step against the capsule. |
معرَّف في lib/src/widgets/components/bottom_nav_bar/liquid_glass_nav_bar_style.dart
LiquidGlassTabMagnifierPillStyle#
Magnifier pill group for LiquidGlassTabPillStyle: the invisible second pill mounted under the moving glass pill on the Impeller path. It shares the glass pill's silhouette, lift, travel, squash and shed exactly, but is transparent, unblurred, undistorted, rimless and shadowless — its one job is to magnify the bar seen under the pill (it sits below the icon shell, so the icons keep their size).
Impeller only: stacked lenses chain there, so the glass pill above refracts this pill's output. The Skia capture path never mounts it, whatever these fields say.
المُنشئات
const LiquidGlassTabMagnifierPillStyle({ this.enabled = true, this.magnification = 0.87, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
enabled | bool | true | Whether the magnifier pill is mounted at all. A feature switch, not an animated visibility — when mounted it already appears and retires with the glass pill's own show/hide. |
magnification | double | 0.87 | Magnification of the bar seen under the pill. Below 1 the bar recedes (reads pushed back); 1 is inert. Ramps in with the pill's lift and back out through the landing handover. |
الدوال
| التوقيع | الوصف |
|---|---|
LiquidGlassTabMagnifierPillStyle copyWith({ bool? enabled, double? magnific… |
معرَّف في lib/src/widgets/components/bottom_nav_bar/liquid_glass_nav_bar_style.dart
Which renderer(s) get the full iOS-26 glass-refracting morphing pill (the dual-pipeline animated bar). See LiquidGlassTabBar.glassPill for how to opt in.
القيم
| القيمة | الوصف |
|---|---|
none | No glass pill — the lightweight single-lens bar (instant, or a soft sliding highlight with animated: true). Works everywhere. |
impellerOnly | Glass-refracting morphing pill only on Impeller; falls back to none on Skia / Web. |
both | Glass-refracting morphing pill on both Impeller and Skia. |
معرَّف في lib/src/widgets/components/bottom_nav_bar/liquid_glass_nav_bar_style.dart
Everything a LiquidGlassGlyphBuilder needs to draw one glyph in the state its host is currently rendering it.
color is the already resolved color a plain Icon would have received for this exact layer — the item style's selected/unselected color, the action's foreground, the tile's glyph color. Tint with it and custom art follows every state change the built-in icons follow, including the nav bar's moving-pill reveal.
On the nav/tab bars a glyph is in one of three states:
- unselected —
selectedandunderGlassbothfalse; - selected —
selectedtrue: the committed tab, whether or not a pill is on it (a bar may hide its pill entirely); - under glass —
underGlasstrue: the moving glass pill is over this layer right now — lifted on it, dragged across it, or sweeping past it mid-travel. A flat pill is not glass, so the static rest highlight never sets it.
المُنشئات
const LiquidGlassGlyph({ required this.color, required this.size, this.selected = false, this.underGlass = false, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
colorمطلوب | Color | — | The color this glyph should paint in for this layer/frame. |
sizeمطلوب | double | — | The box the glyph is laid out in. Content larger than this is scaled down; it never grows its cell (hosts derive their layout — and, on the nav bar, the moving pill's rect — from their own numbers, not from the glyph). |
selected | bool | false | Whether this layer draws the host's selected/active state. Always false on hosts that have no such state (an app icon, a dock entry). |
underGlass | bool | false | Whether the host's moving glass pill is over this layer right now. Stays true through the landing until the pill has fully shed into the static rest pill; always false under a flat pill, a hidden one, or on hosts that have no pill at all. |
معرَّف في lib/src/widgets/utils/liquid_glass_glyph.dart
LiquidGlassGlyphBuilder#
Builds custom glyph content — an SVG, a PNG, a CustomPaint, a badge — anywhere the package would otherwise draw an Icon.
Called once per rendered layer, so on the nav bar's glass-pill tier it runs for both the inside-the-pill and outside-the-pill passes of the same tab, each with its own LiquidGlassGlyph.color and LiquidGlassGlyph.selected.
Multi-color art can simply ignore the color and stay as authored.
typedef LiquidGlassGlyphBuilder = Widget Function( BuildContext context, LiquidGlassGlyph glyph, );iconBuilder: (context, i) => SvgPicture.asset(
i.selected ? 'assets/home_fill.svg' : 'assets/home.svg',
width: i.size,
height: i.size,
colorFilter: ColorFilter.mode(i.color, BlendMode.srcIn),
)معرَّف في lib/src/widgets/utils/liquid_glass_glyph.dart
LiquidGlassLabel#
Everything a LiquidGlassLabelBuilder needs to draw one tab label in the state its host is currently rendering it.
Mirrors LiquidGlassGlyph: color, fontSize and fontWeight are the already resolved values the default Text would have received for this exact layer — the item style's selected/unselected color, its per-state font size and weight. Style with them and a custom label follows every state change the built-in labels follow, including the nav bar's moving-pill reveal. The same three states apply: unselected, selected (the committed tab), and underGlass (the moving glass pill is over this layer right now — see LiquidGlassGlyph.underGlass).
المُنشئات
const LiquidGlassLabel({ required this.color, required this.fontSize, required this.fontWeight, this.text, this.selected = false, this.underGlass = false, })| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
colorمطلوب | Color | — | The color this label should paint in for this layer/frame. |
fontSizeمطلوب | double | — | The font size the default label would use for this layer. |
fontWeightمطلوب | FontWeight | — | The font weight the default label would use for this layer. |
text | String? | — | The item's label string, when it has one. A builder-only item may leave it null and draw its own content. |
selected | bool | false | Whether this layer draws the host's selected/active state. |
underGlass | bool | false | Whether the host's moving glass pill is over this layer right now. See LiquidGlassGlyph.underGlass. |
الخصائص
| الاسم | النوع | الوصف |
|---|---|---|
textStyle | TextStyle | The TextStyle the default label renders with — spread it into a custom Text (via copyWith) to keep the stock look and change only what you need. |
معرَّف في lib/src/widgets/utils/liquid_glass_glyph.dart
LiquidGlassLabelBuilder#
Builds custom label content — a different font, rich text, a badge row — anywhere the package would otherwise draw the item's label as a plain Text.
Called once per rendered layer, like LiquidGlassGlyphBuilder: on the nav bar's reveal tiers it runs for both the inside-the-pill and outside-the-pill passes of the same tab, each with its own resolved LiquidGlassLabel.color / LiquidGlassLabel.selected. The two passes share one layout, so return the same-sized widget for both states or the reveal clip will show a seam.
typedef LiquidGlassLabelBuilder = Widget Function( BuildContext context, LiquidGlassLabel label, );labelBuilder: (context, l) => Text(
l.text ?? 'Home',
style: l.textStyle.copyWith(letterSpacing: 0.4),
)معرَّف في lib/src/widgets/utils/liquid_glass_glyph.dart
التعليقات
التعليقات هي مناقشات GitHub — يمكنك الرد من أيٍّ من المكانين.