mjn_liquid_ui 0.2.7 copy "mjn_liquid_ui: ^0.2.7" to clipboard
mjn_liquid_ui: ^0.2.7 copied to clipboard

PlatformiOS

Native-inspired Liquid Glass UI components for Flutter, focused on iOS SwiftUI and UIKit.

mjn_liquid_ui #

Pub Version License Platform

A Flutter plugin for native-inspired liquid glass UI components, focused on iOS.

mjn_liquid_ui embeds iOS SwiftUI/UIKit controls in Flutter through platform views. It is designed for apps that want a native-feeling Liquid Glass tab bar, search segment, switch, slider, and glass surface while keeping the Flutter app structure.

Features #

  • Liquid glass tab bar.
  • Separate search tab / search segment using native SwiftUI TabRole.search.
  • Liquid switch.
  • Liquid slider with optional stepped values.
  • Liquid glass surfaces.
  • Native iOS sheet presentation with a Liquid Glass NavigationStack + Form sheet, customizable Dart-provided form content, content-sized detents, optional background color, and background zoom.
  • SF Symbols outside the tab bar through native UIImage(systemName:) rendering.
  • Native iOS-focused implementation using Swift, SwiftUI, and UIKit.
  • Flutter fallbacks for unsupported platforms to avoid crashes during development.

Widgets #

Widget Description Controller
AppleLiquidTabBar Native iOS Liquid Glass tab bar with a dedicated search-role item, tint support, and badges -
AppleLiquidSwitch Native Liquid Glass toggle switch with animated state changes -
AppleLiquidSlider Native Liquid Glass slider with min/max range and optional step support -
AppleLiquidSymbol SF Symbols rendered through native UIImage(systemName:) with optional Flutter icon fallback -
AppleLiquidSurface Apply Liquid Glass effects to any Flutter widget -
AppleLiquidStretch Flutter squash and stretch interaction wrapper for glass content -
AppleLiquidSheet Static API for presenting and dismissing native iOS Liquid Glass sheets AppleLiquidSheetController

Icon support #

AppleLiquidSymbol renders standalone SF Symbols by name. Use AppleLiquidSymbolWeight to select SF Symbol stroke weights such as regular, semibold, or bold. For tab icons, pass SF Symbol names through AppleLiquidTabItem.systemImage and optionally AppleLiquidTabItem.activeSystemImage; use symbolWeight and activeSymbolWeight when individual tab icons need different weights.

API Source
AppleLiquidSymbol('name') Standalone SF Symbol rendered by native iOS
AppleLiquidSymbol(weight: AppleLiquidSymbolWeight.bold) Optional SF Symbol stroke weight
AppleLiquidTabItem(systemImage: 'name') SF Symbol for tab bar items
AppleLiquidTabItem(activeSystemImage: 'name') Optional selected-state SF Symbol for tab bar items
AppleLiquidTabItem(symbolWeight: AppleLiquidSymbolWeight.regular) Optional inactive tab icon weight
AppleLiquidTabItem(activeSymbolWeight: AppleLiquidSymbolWeight.bold) Optional selected tab icon weight
fallbackIcon: Icons.example Flutter IconData fallback for unsupported platforms

Screenshots #

Liquid Tab Bar Liquid Switch
Liquid Tab Bar Liquid Switch
Liquid Slider Liquid Surface
Liquid Slider Liquid Surface
Liquid Sheet Liquid Search
Liquid Sheet Liquid Search

Platform support #

Platform Support
iOS Supported
Android Not officially supported yet
Web Not officially supported yet
macOS Not officially supported yet
Windows Not officially supported yet
Linux Not officially supported yet

The Dart widgets include simple Flutter fallbacks on unsupported platforms so apps should not crash during development. These fallbacks are experimental and are not official Android, web, or desktop support.

Installation #

dependencies:
  mjn_liquid_ui: ^0.2.7

Then import the package:

import 'package:mjn_liquid_ui/mjn_liquid_ui.dart';

Usage #

AppleLiquidTabBar(
  currentIndex: currentIndex,
  selectedTintColor: const Color(0xFF007AFF),
  onChanged: (int index) {
    setState(() => currentIndex = index);
  },
  items: const <AppleLiquidTabItem>[
    AppleLiquidTabItem(
      title: 'Home',
      systemImage: 'house.fill',
      symbolWeight: AppleLiquidSymbolWeight.regular,
      activeSymbolWeight: AppleLiquidSymbolWeight.bold,
    ),
    AppleLiquidTabItem(
      title: 'Jobs',
      systemImage: 'briefcase.fill',
    ),
    AppleLiquidTabItem(
      title: 'Chat',
      systemImage: 'message.fill',
      notificationDotColor: Color(0xFF007AFF),
      notificationBadgeValue: '3',
    ),
  ],
  searchItem: const AppleLiquidTabItem(
    title: 'Search',
    systemImage: 'magnifyingglass',
    isSearch: true,
  ),
)

Use the tab bar as an overlay when page content should continue behind the native bar:

Scaffold(
  extendBody: true,
  body: Stack(
    children: <Widget>[
      const Positioned.fill(child: YourPageContent()),
      Positioned(
        left: 0,
        right: 0,
        bottom: 0,
        child: AppleLiquidTabBar(
          currentIndex: currentIndex,
          onChanged: (int index) {
            setState(() => currentIndex = index);
          },
          items: const <AppleLiquidTabItem>[
            AppleLiquidTabItem(title: 'Home', systemImage: 'house.fill'),
            AppleLiquidTabItem(title: 'Jobs', systemImage: 'briefcase.fill'),
            AppleLiquidTabItem(title: 'Chat', systemImage: 'message.fill'),
          ],
          searchItem: const AppleLiquidTabItem(
            title: 'Search',
            systemImage: 'magnifyingglass',
            isSearch: true,
          ),
        ),
      ),
    ],
  ),
)

Components #

Liquid tab bar #

AppleLiquidTabBar renders a native iOS SwiftUI TabView on iOS. The trailing searchItem is created as a separate native search-role tab. Use selectedTintColor to customize the selected icon and label tint while keeping the native Liquid Glass tab bar rendering intact. Use symbolWeight and activeSymbolWeight on AppleLiquidTabItem to tune the normal and selected SF Symbol stroke weights for individual icons. Set notificationDotColor on any AppleLiquidTabItem to show a notification dot on the icon. Add notificationBadgeValue to show text inside the badge.

Liquid switch #

AppleLiquidSwitch(
  value: enabled,
  tintColor: const Color(0xFF14B8A6),
  onChanged: (bool value) {
    setState(() => enabled = value);
  },
)

Liquid slider #

AppleLiquidSlider(
  value: amount,
  min: 0,
  max: 1,
  step: 0.1,
  tintColor: const Color(0xFF8B5CF6),
  onChanged: (double value) {
    setState(() => amount = value);
  },
)

Omit step for a continuous slider.

SF Symbols #

const AppleLiquidSymbol(
  'sparkles',
  size: 32,
  color: Color(0xFF0EA5E9),
  weight: AppleLiquidSymbolWeight.semibold,
  fallbackIcon: Icons.auto_awesome_rounded,
  semanticLabel: 'Highlights',
)

AppleLiquidSymbol renders the provided SF Symbol name natively on iOS and paints the result as a normal Flutter image. On unsupported platforms it uses fallbackIcon when provided. The optional weight parameter supports ultraLight, thin, light, regular, medium, semibold, bold, heavy, and black.

Liquid glass surface #

AppleLiquidSurface(
  height: 160,
  borderRadius: 28,
  clear: true,
  interactive: true,
  deformable: true,
  stretchGestureMode: AppleLiquidStretchGestureMode.gestureDetector,
  child: const Text('Flutter content over native Liquid Glass'),
)

Use deformable: true for interactive squash and stretch feedback. Use AppleLiquidStretchGestureMode.gestureDetector when the surface contains buttons or other tappable Flutter children.

Native sheet #

AppleLiquidSheet presents a native iOS sheet from Flutter. The sheet renders a Liquid Glass SwiftUI NavigationStack with Form content, a content-sized detent, optional background zoom on the presenting page, and a checkmark toolbar action to dismiss.

Pass AppleLiquidSheetContent to customize the native form. The content model supports sections plus text, value, toggle, picker, text-field, and nested navigation rows. Toggle, picker, and text-field state stays local to the native sheet while it is presented.

final AppleLiquidSheetContent content = AppleLiquidSheetContent(
  title: 'Project',
  doneSemanticLabel: 'Close sheet',
  sections: <AppleLiquidSheetSection>[
    AppleLiquidSheetSection(
      title: 'Overview',
      rows: <AppleLiquidSheetRow>[
        AppleLiquidSheetRow.value(
          title: 'Package',
          value: 'mjn_liquid_ui',
          systemImage: 'shippingbox.fill',
        ),
        AppleLiquidSheetRow.toggle(
          title: 'Background zoom',
          value: true,
        ),
        AppleLiquidSheetRow.picker(
          title: 'Theme',
          options: <String>['Auto', 'Light', 'Dark'],
          selectedOption: 'Auto',
        ),
        AppleLiquidSheetRow.navigation(
          title: 'Details',
          content: AppleLiquidSheetContent(
            title: 'Details',
            sections: <AppleLiquidSheetSection>[
              AppleLiquidSheetSection(
                rows: <AppleLiquidSheetRow>[
                  AppleLiquidSheetRow.text(
                    title: 'Rendered natively',
                    subtitle: 'This page is a SwiftUI Form pushed from Dart.',
                  ),
                ],
              ),
            ],
          ),
        ),
      ],
    ),
  ],
);

final bool didShow = await AppleLiquidSheet.showSheet(
  backgroundZoomScale: 0.94,
  sheetColor: const Color(0xFFEAF3FF),
  content: content,
);

Use AppleLiquidSheetController when the calling code needs imperative control or presentation state:

final AppleLiquidSheetController sheetController =
    AppleLiquidSheetController(
  backgroundZoomScale: 0.94,
  sheetColor: null,
  content: content,
);

final bool didShow = await sheetController.showSheet();
await sheetController.dismiss();

backgroundZoomScale controls how far the presenting view scales back while the sheet is open. Set sheetColor to force a specific sheet background color; leave it null to use the native Liquid Glass/system presentation background. The method returns true after a native iOS sheet was shown and dismissed. It returns false on unsupported platforms so apps can present their own Flutter fallback. While a native sheet is active, touches are blocked from reaching the Flutter content behind it. Repeated show calls return true without opening another sheet so fallback code does not stack a second presentation. The controller exposes isShowing and isShown for UI state while its presentation is active.

The iOS implementation uses a single SwiftUI content-sized sheet detent instead of a .large expansion target. The estimated height is derived from the active form content and updates for nested navigation screens. The form scroll background stays hidden so the Liquid Glass sheet remains visible behind the form content. showTemplateSheet() and AppleLiquidSheetController.showTemplateSheet() are kept as compatibility aliases for older code. The earlier bottom search bar option has been removed from the sheet API.

iOS notes #

  • The iOS implementation uses Swift, SwiftUI, UIKit, and Flutter platform views.
  • The tab bar's search segment is implemented with native SwiftUI Tab(..., role: .search).
  • SF Symbols names are passed through systemImage for tab items and through AppleLiquidSymbol.name for standalone symbols.
  • SF Symbol weights are optional and use native UIImage.SymbolConfiguration for standalone symbols. Tabbar weights are passed to native tab labels and may still be influenced by iOS tab bar styling.
  • Liquid Glass appearance depends on the iOS and Xcode versions used to build and run the app. Unsupported iOS versions may display a simpler fallback surface.
  • Changes inside ios/Classes are native Swift/SwiftUI changes. Flutter hot restart does not recompile those files; stop and rerun the example app so Xcode performs an incremental iOS build.

Limitations #

  • iOS is the only officially supported platform for this release.
  • Android, web, and desktop are not officially supported yet.
  • Unsupported-platform fallbacks are intentionally simple and experimental.
  • The plugin does not provide an Android native implementation yet.
  • The search tab is a native search-role segment; app-specific search UI should be implemented by your Flutter page content.

Example #

Run the bundled example app on an iOS simulator:

cd example
flutter run -d <ios-simulator-id>

The example demonstrates the liquid tab bar, standalone SF Symbols, search segment, switch, slider, liquid glass surface, and native settings sheet.

License #

This package is licensed under the BSD 3-Clause License. See LICENSE.

3
likes
150
points
372
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Native-inspired Liquid Glass UI components for Flutter, focused on iOS SwiftUI and UIKit.

Repository (GitHub)
View/report issues
Contributing

Topics

#flutter #ios #cupertino #liquid-glass #ui

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on mjn_liquid_ui

Packages that implement mjn_liquid_ui