bloom_native_ui
Build native iOS views directly from Dart. BloomNativeView hosts a composable
SwiftUI hierarchy with native layout, controls, navigation, menus, presentations
and iOS 26 Liquid Glass. Application state and callbacks stay in Dart.
BloomNativeView(
child: BloomNativeNavigation(
title: 'Settings',
child: BloomNativeForm(children: [
BloomNativeToggle(
key: 'notifications',
label: 'Notifications',
value: notifications,
onChanged: (value) => setState(() => notifications = value),
),
]),
),
)
See the native iOS guide for all controls, shared glass/morphing,
native sheets and dialogs, state/identity, and registering custom SwiftUI or UIKit
views. Run example/lib/native_catalog.dart for a complete native demo.
System framework guides cover maps and Look Around, PDFs, drawing and scanning, Safari, contacts and composers, Apple sign-in and StoreKit, Apple Pay with shipping updates, and interactive widgets and Live Activities. See iOS coverage and verification for platform requirements and remaining device/service checks.
The existing BloomGlass* widgets also provide individual SwiftUI and Jetpack
Compose controls, with Flutter fallbacks on other platforms. The composable
native tree currently targets iOS; provide its fallback for other platforms.
Install
dependencies:
bloom_native_ui:
path: ../bloom/packages/bloom_native_ui
Usage
Import package:bloom_native_ui/bloom_native_ui.dart. When using the Flutter glass
fallback, initialize and wrap the app once:
Future<void> main() async {
await BloomNativeUi.initialize();
runApp(BloomNativeUi.wrap(const MyApp()));
}
import 'package:bloom_native_ui/bloom_native_ui.dart';
BloomGlassPanel(
title: 'Now playing',
subtitle: 'Quiet moments',
icon: 'music.note',
)
On iOS, every control uses native rendering by default. The tab bar embeds
Apple's UITabBarController through SwiftUI, so iOS handles its Liquid Glass
lens, quick taps, drag tracking, and accessibility. On Android, panels and tab
bars use Flutter-rendered live glass by default; the other controls use Compose.
For example:
BloomGlassTabBar(
items: const [
BloomGlassTabItem(id: 'home', label: 'Home', icon: 'house'),
BloomGlassTabItem(id: 'search', label: 'Search', icon: 'magnifyingglass'),
],
selectedId: selectedId,
onSelected: (id) => setState(() => selectedId = id),
)
Pass renderer: BloomGlassRenderer.native to request a native control, or
renderer: BloomGlassRenderer.flutter to use Flutter glass. The default is
BloomGlassRenderer.auto, which follows the platform choices above.
BloomGlassButton(
label: 'Continue',
style: BloomGlassButtonStyle.prominent,
onPressed: continueFlow,
)
BloomGlassToggle(
label: 'Airplane mode',
value: airplaneMode,
onChanged: (value) => setState(() => airplaneMode = value),
)
BloomGlassSegmentedControl(
segments: const ['Day', 'Week', 'Month'],
selectedIndex: selectedIndex,
onSelected: (index) => setState(() => selectedIndex = index),
)
BloomGlassTabBar(
items: const [
BloomGlassTabItem(id: 'home', label: 'Home', icon: 'house'),
BloomGlassTabItem(id: 'search', label: 'Search', icon: 'magnifyingglass'),
],
selectedId: selectedId,
onSelected: (id) => setState(() => selectedId = id),
)
Platform support
| Platform | Rendering |
|---|---|
| iOS 15+ | SwiftUI material |
| iOS 26+ | SwiftUI Liquid Glass |
| Android | Jetpack Compose + Material 3 translucent surface |
| Web and desktop | Flutter frosted fallback |
Query the installed native implementation with
final caps = await BloomNativeUi.capabilities();. The result reports the
platform, native view support, native glass support, and OS version.
Compositing limits
The flutter renderer uses a fragment shader to blur, refract, and add a
specular rim over live Flutter content when Impeller is available (Flutter
3.27+). On unsupported renderers or when the shader asset cannot load, it uses
a frosted blur with a painted rim.
The native renderer uses real Apple system controls or Jetpack Compose UI.
On iOS 26, native Liquid Glass can blur and refract the Flutter content behind
the platform view. Android's native Material surfaces do not provide Apple's
Liquid Glass effect.
BloomGlassTabBar reserves 80 logical pixels by default, allowing room for the
system selection lens. Its native bar uses the system's layout. Place it inside
Flutter's SafeArea when positioning it near screen edges.
Wire protocol
The plugin uses the dev.bloom.native_ui method channel. Its capabilities
method returns platform, native view and glass support, and OS version fields.
Platform view types use dev.bloom.native_ui/<view-name> and receive their
initial props through StandardMessageCodec. Each view gets a
dev.bloom.views/<viewType>_<platformViewId> method channel; Dart sends a full
replacement props map with updateProps, and native code invokes event names
with event payloads on that channel. Null props are omitted.
The view types are glass_panel, glass_button, glass_toggle,
glass_segmented, and glass_tab_bar. Events are press, change (new bool),
and select (index for segmented controls, item id for tab bars).
Open source
This package is MIT licensed. All native source code is in this repository; there are no prebuilt binaries or closed-source SDKs.
Flutter glass uses liquid_glass_widgets under the MIT license. Requires Flutter 3.41+ and iOS 15+; compile with Xcode 26+ for iOS 26 Liquid Glass. Android uses the host's AGP/Kotlin versions and matches its Compose compiler automatically.
Testing
Set BloomNativeUi.useNativeViews = false to force Flutter fallbacks in widget
tests.
iOS coverage review
The expanded native API and system-extension integration are in active review. See Native iOS guide, coverage ledger, and the extended example checklist. Android's composable native tree is deferred until the iOS work is verified.
Libraries
- bloom_native_ui
- Open-source native glass UI for Flutter and Bloom apps.