cupertino_native

repository·main·Indexed 41 days ago

https://github.com/serverpod/cupertino_native

A Flutter package providing native Liquid Glass widgets for iOS and macOS. It uses Platform Views and method channels to host real UIKit/AppKit controls, including CNButton, CNIcon for SF Symbols, CNSlider, CNSwitch, CNSegmentedControl, CNPopupMenuButton, and CNTabBar. Requires Xcode 26 beta and iOS 26 or later for Liquid Glass components; minimum platform versions are iOS 14.0 and macOS 11.0.

Tokens
6K
Snippets
24
Records
30
Agent score
51%

What's inside cupertino_native

  1. Run the Cupertino Native example app

    main

    The example app demonstrates all supported Liquid Glass widgets. Note that these components only appear when running on iOS 26 or later and must be built with Xcode 26 or later.

    To use the Xcode 26 beta (if installed in your Applications directory), switch your active developer directory using xcode-select before running the Flutter app.

    # Switch to Xcode 26 beta
    sudo xcode-select -s /Applications/Xcode-beta.app
    
    # Run the example app
    cd example
    flutter run
  2. Install cupertino_native

    main

    Add cupertino_native to your Flutter project to use native Liquid Glass widgets for iOS and macOS.

    Platform Requirements:

    • iOS: Minimum platform version 14.0.
    • macOS: Minimum version 11.0 or higher.

    Xcode Requirement: You must install the Xcode 26 beta and set it as your default using xcode-select.

    flutter pub add cupertino_native
    flutter pub get
    
    sudo xcode-select -s /Applications/Xcode-beta.app
  3. How CNButton handles platform fallbacks

    main

    CNButton is designed to provide a native experience on Apple platforms while maintaining cross-platform compatibility:

    • iOS/macOS: It uses a UiKitView or AppKitView to embed actual native platform buttons. This ensures authentic visuals, animations, and behaviors.
    • Other Platforms (Android, Web, etc.): It falls back to a standard Flutter CupertinoButton. In this mode, it uses the provided label or a default CupertinoIcons.ellipsis if an icon was intended, ensuring the app doesn't crash on non-Apple platforms.
  4. Define menu items using CNPopupMenuItem and CNPopupMenuDivider

    main

    The items list in a CNPopupMenuButton accepts a list of CNPopupMenuEntry objects. There are two types:

    • CNPopupMenuItem: A selectable item. It can include a label, an optional icon (using CNSymbol), an enabled state, and a checked state (which displays a check mark).
    • CNPopupMenuDivider: A visual separator between items.
    final List<CNPopupMenuEntry> myMenuItems = [
      CNPopupMenuItem(
        label: 'Edit',
        icon: CNSymbol(name: 'pencil'),
        checked: true,
      ),
      CNPopupMenuDivider(),
      CNPopupMenuItem(
        label: 'Delete',
        icon: CNSymbol(name: 'trash'),
      ),
    ];
  5. Use CNSlider for native sliders

    main

    The CNSlider widget provides a native Liquid Glass slider. On non-Apple platforms, it falls back to a standard Flutter implementation.

    double _value = 50;
    
    CNSlider(
      value: _value,
      min: 0,
      max: 100,
      onChanged: (v) => setState(() => _value = v),
    )
  6. Use CNPopupMenuButton for native popup menus

    main

    The CNPopupMenuButton widget creates a native Liquid Glass popup menu. It accepts a list of CNPopupMenuItem objects and a CNPopupMenuDivider for organization.

    final items = [
      const CNPopupMenuItem(label: 'New File', icon: CNSymbol('doc', size: 18)),
      const CNPopupMenuItem(label: 'New Folder', icon: CNSymbol('folder', size: 18)),
      const CNPopupMenuItem(label: 'Rename', icon: CNSymbol('rectangle.and.pencil.and.ellipsis', size: 18)),
      const CNPopupMenuDivider(),
    ];
    
    CNPopupMenuButton(
      buttonLabel: 'Actions',
      items: items,
      onSelected: (index) {
        // Handle selection
      },
    )
  7. Use CNTabBar for native tab bars

    main

    The CNTabBar widget provides a native Liquid Glass tab bar, typically used at the bottom of a page. It uses a list of CNTabBarItem objects.

    int _tabIndex = 0;
    
    CNTabBar(
      items: const [
        CNTabBarItem(label: 'Home', icon: CNSymbol('house.fill')),
        CNTabBarItem(label: 'Profile', icon: CNSymbol('person.crop.circle')),
        CNTabBarItem(label: 'Settings', icon: CNSymbol('gearshape.fill')),
      ],
      currentIndex: _tabIndex,
      onTap: (i) => setState(() => _tabIndex = i),
    )
  8. Use CNSegmentedControl for native segmented controls

    main

    The CNSegmentedControl widget provides a native Liquid Glass segmented control. On non-Apple platforms, it falls back to a standard Flutter implementation.

    int _index = 0;
    
    CNSegmentedControl(
      labels: const ['One', 'Two', 'Three'],
      selectedIndex: _index,
      onValueChanged: (i) => setState(() => _index = i),
    )
  9. Use CNButton for native buttons

    main

    The CNButton widget provides native Liquid Glass buttons. You can use a standard text label or an icon variant using CNButton.icon.

    // Text button
    CNButton(
      label: 'Press me',
      onPressed: () {},
    )
    
    // Icon button variant
    CNButton.icon(
      icon: const CNSymbol('heart.fill'),
      onPressed: () {},
    )
  10. Use CNIcon for SF Symbols

    main

    The CNIcon widget allows you to display native SF Symbols. You can specify the symbol name using CNSymbol and control the rendering mode (e.g., monochrome or multicolor) via CNSymbolRenderingMode.

    // Monochrome symbol
    const CNIcon(symbol: CNSymbol('star'));
    
    // Multicolor / hierarchical options
    const CNIcon(
      symbol: CNSymbol('paintpalette.fill'),
      mode: CNSymbolRenderingMode.multicolor,
    )
  11. Use CNTabBar for native Apple-style tab bars

    main

    The CNTabBar widget provides a native UITabBar (iOS) or NSTabView (macOS) style visual experience. It uses SF Symbols for icons and supports advanced layout features like splitting items between left and right sections.

    Platform Behavior:

    • iOS/macOS: Renders a true native view via platform views.
    • Other Platforms: Falls back to a standard Flutter CupertinoTabBar with generic circle icons.
    CNTabBar(
      items: [
        CNTabBarItem(label: 'Home', icon: CNSymbol(name: 'house')),
        CNTabBarItem(label: 'Settings', icon: CNSymbol(name: 'gear')),
      ],
      currentIndex: _currentIndex,
      onTap: (index) => setState(() => _currentIndex = index),
    )