ios_liquid_glass
Apple's native iOS 26 Liquid Glass for Flutter — real UIGlassEffect
surfaces and the real UITabBarController tab bar — plus an Impeller
liquid lens tier for the iridescent droplet bottom nav that refracts
Flutter content (rainbow rim, jelly morph).
![]() |
![]() |
|---|
Left — liquid tier: the Impeller droplet caught mid-morph on the
example's Droplet lens page. This is real refraction of Flutter pixels:
"Night Swim" bends through the lens and the rim splits the backdrop into a
rainbow. Right — native tier: Apple's real UITabBarController and
UIGlassEffect buttons/cards on iOS 26.

The jelly morph between tabs (LiquidGlassBottomNav.liquid), recorded
on the iOS 26.2 Simulator. The droplet squash-stretches with spring physics
and keeps refracting the page content the whole way.

Lens close-up: chromatic aberration splits the backdrop like a prism.
Tune the rim strength with chromaticAberration (default 0.02; the shots
here use 0.06).
![]() |
![]() |
|---|
The native tier in motion: pushing any route hides the system tab bar
with zero manual wiring — see
LiquidGlassNavigatorObserver — and
declarative badges render on the real UITabBar. The Simulator exaggerates
native glass artifacts more than a device does — see
Known limitations.
| Tier | When | Rendering |
|---|---|---|
| liquid | LiquidGlassBottomNav.liquid / preferLiquid: true |
Impeller live-backdrop droplet (needs Impeller) |
| native | iOS 26+ default | Native UIGlassEffect platform view / system UITabBar |
| plain | everything else | Solid surface, identical layout |
Important: Native
UIGlassEffectis decorative — it samples layers beneath the Flutter view and does not refract Flutter pixels. For the floating rainbow droplet over your icons/page, use the liquid tier and stack the bar over content.
Install
dependencies:
ios_liquid_glass:
path: /path/to/flutter_liquid_glass # or ^0.9.0 from pub
Host app requirements
- iOS
Info.plist— enable platform views (native tier) and Impeller (liquid tier):<key>io.flutter.embedded_views_preview</key> <true/> <key>FLTEnableImpeller</key> <true/> - iOS 26+ SDK on the build machine for native glass (deployment target can stay lower).
- Full restart after enabling Impeller (hot reload is not enough).
Usage
Drop-in tab host (recommended)
Register the package observer once — this alone makes the native bar hide on any pushed route (PIN, Order New Card, a details page, ...) and reappear on pop, with no per-route bookkeeping:
MaterialApp(
navigatorObservers: [LiquidGlassNavigatorObserver.instance],
// or with a router:
// routerDelegate: appRouter.delegate(
// navigatorObservers: () => [LiquidGlassNavigatorObserver.instance],
// ),
home: const RootTabs(),
)
Then build the tab host:
import 'package:ios_liquid_glass/ios_liquid_glass.dart';
LiquidGlassTabScaffold(
currentIndex: index,
onIndexChanged: (i) => setState(() => index = i),
destinations: [
LiquidGlassTabDestination(
title: 'Home',
systemImage: 'house',
selectedSystemImage: 'house.fill',
icon: const Icon(Icons.home_outlined),
selectedIcon: const Icon(Icons.home),
page: const HomePage(),
),
LiquidGlassTabDestination(
title: 'Search',
systemImage: 'magnifyingglass',
icon: const Icon(Icons.search),
page: const SearchPage(),
),
],
)
For hiding driven by app state instead of (or in addition to) route
pushes — a PIN screen or blur overlay modeled as a flag rather than a
route — add barVisible and/or shouldHideOverlay:
LiquidGlassTabScaffold(
currentIndex: index,
onIndexChanged: (i) => setState(() => index = i),
barVisible: !isPinOpen, // app-driven flag
shouldHideOverlay: () => isPinOpen || isBlurOpen, // same-frame check
overlayListenable: router, // extra listenable to resync on
destinations: [ /* ... */ ],
)
Use .shell when you already own the page stack:
LiquidGlassTabScaffold.shell(
currentIndex: index,
onIndexChanged: onIndexChanged,
themeBuilder: (context) => LiquidGlassTheme.adaptive(context),
overlayListenable: router,
nativeTabs: [...],
fallbackItems: [...],
child: yourBody,
)
Scroll views should use MediaQuery.paddingOf(context).bottom (applied
automatically when applyContentInset: true).
Liquid droplet bottom nav (matches the morphing lens look)
import 'package:ios_liquid_glass/ios_liquid_glass.dart';
Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
Padding(
padding: EdgeInsets.only(
bottom: LiquidGlassBottomNav.contentBottomClearance(context),
),
child: yourPage,
),
LiquidGlassBottomNav.liquid(
currentIndex: index,
onIndexChanged: (i) => setState(() => index = i),
items: [
LiquidGlassNavItem.custom(
iconBuilder: (context, g) => SvgPicture.asset(
g.selected ? 'assets/home_fill.svg' : 'assets/home.svg',
width: g.size,
height: g.size,
colorFilter: ColorFilter.mode(g.color, BlendMode.srcIn),
),
),
// ...
],
),
],
),
);
Tune the rainbow rim with chromaticAberration (default 0.02; the README
shots use 0.06). See the Droplet lens page in example/lib/main.dart
(DropletNavDemoPage) for the exact setup behind the screenshots.
Native glass card / buttons (iOS 26+)
LiquidGlassContainer(
borderRadius: 24,
style: const LiquidGlassStyle(
nativeVariant: NativeGlassVariant.clear,
),
child: const Text('Hello, glass'),
)
Capability detection
if (LiquidGlassPlatform.supportsLiquidLens) { ... }
if (LiquidGlassPlatform.supportsNativeGlass) { ... } // iOS 26+
The real system tab bar (advanced)
LiquidGlassNativeTabShell overlays Apple's actual UITabBarController
(iOS 26+) — see previous docs / example for install, badges, route sync,
and modals.
Known limitations
- Native
UIGlassEffectdoes not refract Flutter-drawn pixels. - Liquid tier needs Impeller; on Skia/Web it falls back to a frosted bar.
- Custom native-tab icons must be pre-rasterized PNG bytes.
- The iOS Simulator exaggerates native Liquid Glass artifacts; judge native visuals on a device. Liquid Impeller refraction is fine on sim.
Example
example/lib/main.dart — a four-tab LiquidGlassTabScaffold (Home,
Search, Favorites, Profile) wired the way a host app is meant to:
LiquidGlassNavigatorObserver registered once on the MaterialApp, a
Navigator.push from Home that hides the bar with no extra code, a
barVisible toggle for app-driven hiding (PIN screens, blur overlays),
declarative tab badges, and the button/icon-button gallery from the
screenshots above. Native tab shell on iOS 26+, Flutter fallback bars
everywhere else.
The Liquid droplet nav button on Home pushes DropletNavDemoPage —
the page behind the hero shots: LiquidGlassBottomNav.liquid stacked over
a colorful library grid so the droplet has real content to refract (the
system bar hides itself for the pushed route, so the two bars never
fight).
cd example
flutter run
Libraries
- ios_liquid_glass
- Apple's native iOS 26 Liquid Glass (
UIGlassEffectandUITabBarController) for Flutter, plus an Impeller liquid-lens tier for iridescent droplet nav that refracts Flutter content. - ios_liquid_glass_method_channel
- ios_liquid_glass_platform_interface



