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.