adaptive_platform_ui: one widget tree, native iOS 26 and Material

adaptive_platform_ui renders real iOS 26 UIKit toolbars and tab bars with Liquid Glass on new iPhones, Cupertino on older ones and Material 3 on Android - from one widget tree.

CategoryUI/Components
Stars★ 235
Last update2026-07-25
PriorityHigh

adaptive_platform_ui gives you one widget tree that renders native iOS 26 Liquid Glass components on new iPhones, Cupertino on older ones, and Material 3 on Android. 235★, MIT, last pushed 2026-07-25.

What is adaptive_platform_ui?

Flutter has always let you build a Cupertino UI and a Material UI, but never comfortably in the same app. The usual result is Platform.isIOS ? CupertinoButton(...) : ElevatedButton(...) scattered through the widget tree, and a Cupertino layer that lags a year or two behind whatever Apple shipped.

iOS 26 made that worse. Liquid Glass is not a colour scheme you can approximate with a BackdropFilter; the toolbar’s blur, its minimize-on-scroll behaviour and its gesture handling come from UIKit itself.

adaptive_platform_ui takes the position that the only honest way to match it is to embed the real control. It is a Flutter plugin, not a pure-Dart widget library, and on iOS 26 useNativeToolbar: true puts an actual UIToolbar on screen — likewise UITabBar for the bottom bar, with UIButton, UISegmentedControl, UISwitch and UISlider alongside them.

Where that is not possible, it degrades: Cupertino widgets on iOS 18 and below, Material 3 on Android and web. The decision is made at runtime by the package, not by you.

Why it matters in 2026

The value is in the version axis, not just the platform axis. Most adaptive packages branch on Platform.isIOS and stop there, which means the moment Apple ships a new design language your “adaptive” UI is adaptive to the wrong iOS.

The API is shaped around one app-level widget and a handful of adaptive components:

AdaptiveScaffold(
  appBar: AdaptiveAppBar(
    title: 'My App',
    useNativeToolbar: true,
    actions: [
      AdaptiveAppBarAction(
        onPressed: () {},
        iosSymbol: 'gear',
        icon: Icons.settings,
      ),
    ],
  ),
  bottomNavigationBar: AdaptiveBottomNavigationBar(
    items: [
      AdaptiveNavigationDestination(icon: 'house.fill', label: 'Home'),
      AdaptiveNavigationDestination(icon: 'person.fill', label: 'Profile'),
    ],
    selectedIndex: 0,
    onTap: (index) {},
  ),
  body: YourContent(),
)

Note iosSymbol: 'gear' next to icon: Icons.settings — you supply both, and the right one is used. AdaptiveApp takes separate Material and Cupertino themes, supports light/dark/system, and has an AdaptiveApp.router() constructor for go_router.

Getting started

flutter pub add adaptive_platform_ui

The package needs Dart ^3.9.2. Then set up localization delegates — the README flags this as the most common mistake:

import 'package:flutter_localizations/flutter_localizations.dart';

AdaptiveApp(
  localizationsDelegates: const [
    GlobalMaterialLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
  ],
  supportedLocales: const [Locale('en'), Locale('de'), Locale('tr')],
  // ...
)

Miss GlobalCupertinoLocalizations and every date and time picker shows English no matter what the device language is.

When should you use adaptive_platform_ui?

  • your app should feel genuinely native on iOS rather than “Material with rounded corners”
  • you want iOS 26 Liquid Glass chrome without writing platform-channel code yourself
  • you are tired of maintaining parallel Cupertino and Material widget trees
  • you support a wide iOS version range and want the fallback handled for you

Where it falls short

Embedding UIKit views has costs that a pure-Dart package does not. Platform views composite differently, they can be awkward inside scrollables and transitions, and they are effectively invisible to Flutter’s widget tests — you cannot assert on a UITabBar from flutter_test. Budget for real-device verification.

Version 0.1.111 is not a stability signal. The package is young, the API surface is broad, and 85 forks against 235 stars with 44 open issues suggests a lot of people are patching things locally.

And this is an iOS-forward package. The Android side is standard Material 3 — perfectly fine, but nobody is choosing this library for what it does on Android.

Alternatives worth comparing

Frequently asked questions

Does adaptive_platform_ui really use native iOS controls?

For the iOS 26 toolbar and tab bar, yes — it is a Flutter plugin that embeds UIKit’s UIToolbar and UITabBar, which is why you get real Liquid Glass blur, the minimize behaviour and native gesture handling instead of an approximation.

What happens on iOS 18 or older?

It renders traditional Cupertino widgets. The version-aware rendering is automatic — you set useNativeToolbar: true and the package decides at runtime whether the device can honour it.

Do I still need to configure localization?

Yes, and this catches people out. Add GlobalMaterialLocalizations, GlobalCupertinoLocalizations and GlobalWidgetsLocalizations delegates to AdaptiveApp or date and time pickers show English regardless of the system language.

Is it production ready?

Treat it as promising rather than settled. It is MIT-licensed and actively developed, but the version number is 0.1.111 — the API is still moving, and embedding platform views has real performance and testing costs.


Part of FlutterCook — hands-on guides to the best open-source Flutter libraries, UI kits, and apps. Explore the live GitHub trends or browse YouTube guides.