settings_ui 4.0.0 copy "settings_ui: ^4.0.0" to clipboard
settings_ui: ^4.0.0 copied to clipboard

Settings screens that look native on iOS, Android, macOS, Windows, Linux (GNOME) and the web, from one API, with sub-pages and a split view for tablets and desktop.

Settings UI for Flutter #

Pub Version License Platform

settings_ui on Android and iPhone, and a split view on an iPad

settings_ui on macOS, Windows, Linux and the web

Add it with your coding agent #

Paste this into Claude Code, Codex, Cursor or another coding agent, from your app's root folder. The agent reads the package's recipe in llms.txt, looks at your app, asks before big changes, and builds a settings screen wired to real, saved state.

Add a settings screen to this Flutter app with the settings_ui package.
Read the section "Recipe: build a settings screen for an app" in
https://raw.githubusercontent.com/yako-dev/flutter-settings-ui/master/llms.txt
and follow it step by step. If you can't open the link, tell me.

Always:
- Pick the version by the app's imports: package:material_ui or package:cupertino_ui
  -> settings_ui: ^4.0.0; package:flutter/material.dart -> settings_ui: ^3.0.1.
- Show me your plan and wait for my OK before adding dependencies or screens.
- Never invent URLs or email addresses (privacy policy, terms, support). Ask me.
Full prompt (if your agent can't open links)
Build a store-ready Settings screen for this Flutter app with the settings_ui package.
First read https://raw.githubusercontent.com/yako-dev/flutter-settings-ui/master/llms.txt (API,
platform differences and mistakes to avoid). If you can't fetch it, read the package source after
`flutter pub get`.

1. Inspect the app before changing anything, and tell me what you found:
   - Flutter version and UI imports. package:material_ui / package:cupertino_ui -> settings_ui: ^4.0.0.
     package:flutter/material.dart -> settings_ui: ^3.0.1. Don't migrate the app unless I ask.
   - The platforms it ships (ios/, android/, macos/, windows/, linux/, web/), and tablet support.
   - State management, persistence (shared_preferences, Hive, secure storage...), localization,
     routing, and whether the app supports light/dark/system theme modes.
   - Existing preferences and feature flags, sign-up/sign-in, in-app purchases, permissions in
     ios/Runner/Info.plist and android/app/src/main/AndroidManifest.xml, and any existing settings UI.
2. Propose grouped sections that follow Apple HIG and Material conventions (for example: account,
   appearance, notifications, privacy, support, about; destructive actions last). For each row give
   the tile type, the state behind it and where it is stored. If the app runs on tablets, desktop or
   the web, propose SettingsSplitView (list and page side by side). Wait for my OK before adding
   dependencies, adding screens or moving existing code.
3. Build it with settings_ui, following the app's existing patterns:
   - SettingsTile.switchTile for on/off, SettingsTile.navigation for rows that open a page or
     picker, plain SettingsTile for values and actions (no chevron). Section titles in sentence case.
   - Settings sub-pages: `destination: SettingsDestination(id: ..., builder: ...)` on the navigation
     tile. The builder returns only the body; the package draws the header and back button.
   - Wire every row to real state that survives a restart. No placeholder rows, empty handlers or
     TODOs. Permission rows show the real OS status and open system settings when denied.
   - Use the app's localization for strings and its router for other screens. Leave `platform`
     unset, so iOS, Android, macOS, Windows, Linux and the web each get their own style.
4. Add these rows when they apply. Ask me for URLs and emails; never invent them.
   - Version and build number (package_info_plus). Open-source licenses (showLicensePage).
   - Privacy policy, terms of use and contact support (url_launcher).
   - Restore purchases, if the app sells subscriptions or non-consumable purchases.
   - Sign out and Delete account, if users can create accounts. Deletion starts in the app, asks for
     confirmation and calls the real backend (App Store Review Guideline 5.1.1(v); Google Play has a
     similar rule).
5. Add widget tests: the screen renders in the style of every platform the app ships
   (TargetPlatformVariant), every toggle persists, links and actions fire, and a split view shows
   one pane at 402x874 and two at 1210x834 (tester.view.physicalSize).
6. Run `flutter analyze` and `flutter test`. Then run the app on an iOS simulator and an Android
   emulator, plus iPad, desktop or web if the app ships there, in light and dark mode
   (`xcrun simctl ui booted appearance dark`, `adb shell cmd uimode night yes`), and screenshot
   the settings screen each time (`xcrun simctl io booted screenshot`,
   `adb exec-out screencap -p`). Fix anything clipped, misaligned or hard to read. If you can't
   launch a device, tell me what to run.
7. Summarize: files changed, dependencies added, each row with its state and storage key, tests
   added, screenshot paths, and anything I still need to provide.

More prompts, to upgrade from 3.x, replace a hand-built settings screen, add one setting end to end, add a split view, or audit a screen: see agent prompts.


One API, every platform #

settings_ui draws iOS 26 and Android 16 settings on phones, macOS System Settings, Windows 11 and GNOME on the desktop, and Chrome's settings page on the web, and picks the style at runtime. Version 4.0.0 adds a split view for iPad, tablets, foldables, desktop and the web, and its own switches for iOS 26 (Liquid Glass), macOS, Windows 11 and GNOME. It is built on material_ui and cupertino_ui and needs Flutter 3.44+. See the changelog.

Install #

dependencies:
  settings_ui: ^4.0.0

Version 4 needs Flutter 3.44+ and an app built on material_ui and cupertino_ui (import 'package:material_ui/material_ui.dart', not package:flutter/material.dart). If your code imports them, add them to your own pubspec.yaml too: flutter pub add material_ui cupertino_ui. Apps still on package:flutter/material.dart stay on settings_ui: ^3.0.1, or see Migrating from 3.x.

Quick start #

import 'package:material_ui/material_ui.dart';
import 'package:settings_ui/settings_ui.dart';

class SettingsScreen extends StatefulWidget {
  const SettingsScreen({super.key});

  @override
  State<SettingsScreen> createState() => _SettingsScreenState();
}

class _SettingsScreenState extends State<SettingsScreen> {
  bool _notifications = true; // load from and save to your store

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Settings')),
      body: SettingsList(
        sections: [
          SettingsSection(
            title: const Text('General'),
            tiles: [
              SettingsTile.navigation(
                leading: const Icon(Icons.language),
                title: const Text('Language'),
                value: const Text('English'),
                onPressed: (context) {/* open a language picker */},
              ),
              SettingsTile.switchTile(
                leading: const Icon(Icons.notifications),
                title: const Text('Notifications'),
                initialValue: _notifications,
                onToggle: (value) => setState(() => _notifications = value),
              ),
            ],
          ),
          SettingsSection(
            title: const Text('About'),
            tiles: [
              SettingsTile(
                title: const Text('Version'),
                value: const Text('1.4.0 (57)'),
              ),
              SettingsTile.navigation(
                title: const Text('Open-source licenses'),
                onPressed: (context) => showLicensePage(context: context),
              ),
            ],
          ),
        ],
      ),
    );
  }
}
  • SettingsTile.switchTile for on/off. It is controlled: initialValue is the current value and onToggle gets the new one. Screen readers announce the switch with the tile's title.
  • SettingsTile.navigation for rows that open a page or a picker. It shows a chevron in the iOS, macOS, Windows and web styles.
  • SettingsTile for a value or an action, with no chevron.
  • CustomSettingsTile and CustomSettingsSection for any other widget. Write section titles in sentence case.
  • enabled: false greys out any tile, and it ignores taps and the keyboard.

Split view #

On iPad, tablets, foldables, desktop and the web, use SettingsSplitView as the whole screen (no app bar above it) and give each navigation tile a SettingsDestination. Wide windows show the list and the page side by side; phones push the page over the list. The package draws each platform's page header and back button, so builder returns only the body.

SettingsSplitView(
  title: const Text('Settings'),
  sections: [
    SettingsSection(
      tiles: [
        SettingsTile.navigation(
          leading: const Icon(Icons.wifi),
          title: const Text('Network & internet'),
          destination: SettingsDestination(
            id: 'network',
            builder: (context) => const NetworkSettings(),
          ),
        ),
        SettingsTile.navigation(
          leading: const Icon(Icons.brightness_medium),
          title: const Text('Display'),
          destination: SettingsDestination(
            id: 'display',
            builder: (context) => const DisplaySettings(),
          ),
        ),
      ],
    ),
  ],
)

Each style follows its platform's Settings app: two panes on iPads in both orientations, on Android tablets and unfolded foldables, and above 980px on the web; on the desktop, the sidebars of System Settings, Windows 11 Settings and GNOME Settings. Pages keep their state when a device folds, unfolds or rotates; system back, Android predictive back and the iOS back swipe work; hinges and right-to-left layouts are handled. A destination works in a plain SettingsList too: the tile pushes its page. For deep links and URL sync, see SettingsSplitController and onDestinationChanged in the API reference.

iOS style on an iPhone Android style on a Pixel phone
iOS 26 Android 16
Split view on an iPad Split view on an unfolded foldable
iPad, split view Foldable, split view
macOS style with the System Settings sidebar Windows 11 style with the Settings navigation pane
macOS System Settings Windows 11
GNOME style with the GNOME Settings sidebar Web style with the Chrome settings menu
Linux (GNOME) Web (Chrome)

The style follows the platform the app runs on, and every browser gets the web style. To use one style everywhere, set platform, for example SettingsList(platform: DevicePlatform.iOS, ...).

API overview #

Class What it is
SettingsList The scrolling list of sections. Optional: platform, brightness, applicationType, lightTheme and darkTheme, contentPadding, crossAxisAlignment, scrollController, shrinkWrap, physics
SettingsSection A group of tiles with an optional title. CustomSettingsSection takes any widget
SettingsTile SettingsTile(), .navigation() and .switchTile(), with title, leading, trailing, value, description, titleDescription, onPressed, enabled, compact. CustomSettingsTile takes any widget
SettingsDestination The page a navigation tile opens: id, builder, title, actions
SettingsSplitView The list and the selected page side by side. SettingsSplitController selects pages from code
SettingsThemeData Colors and text styles for light and dark mode, over each style's defaults
CupertinoSettingsSwitch, MacosSettingsSwitch, FluentSettingsSwitch, AdwaitaSettingsSwitch The iOS 26, macOS, Windows 11 and GNOME switches, which you can also use on their own. AdwaitaPanDownIcon is the arrow of GNOME combo rows

The Android and web styles take their colors from your Material 3 ColorScheme; the iOS, macOS, Windows and GNOME styles use their platforms' own colors. Light and dark mode follow your app theme in every style, and brightness forces one; in a CupertinoApp, pass applicationType: ApplicationType.cupertino so they follow the CupertinoTheme.

  • Every parameter: API reference on pub.dev.
  • Each style's look, where value and description show on each platform, how taps work on switch tiles, theme fields and testing: llms.txt.
  • Every style and the split view in a running app: the example app (cd example && flutter run --route '/split-view?platform=android&theme=dark').

Migrating from 3.x #

The settings_ui API didn't change: 4.0.0 only adds to it. What changes is the UI library your app uses, and the look.

  1. Flutter 3.44+ and Dart 3.12+. If your app can't move yet, stay on settings_ui: ^3.0.1.
  2. Move the app to material_ui and cupertino_ui. Run the import migration from the material_ui README (dart fix --apply --code=migrate_design_widgets) on lib/, test/ and integration_test/, and add both packages to your pubspec.yaml (flutter pub add material_ui cupertino_ui). Dependencies that still import package:flutter/material.dart can be wrapped in MaterialUiCompatibilityBridge or CupertinoUiCompatibilityBridge.
  3. Set settings_ui: ^4.0.0. Your settings screens compile as they are.
  4. Update tests that find switches. Switch tiles now show CupertinoSettingsSwitch on iOS, MacosSettingsSwitch on macOS and FluentSettingsSwitch on Windows, where 3.x showed a CupertinoSwitch, and AdwaitaSettingsSwitch on Linux, where it showed a Material Switch.
  5. Write section titles in sentence case, like iOS 26. If you passed ALL-CAPS titles for the old iOS look, change them.
  6. Check the new look. Sizes, paddings and default colors changed (a list in a side panel or a narrow pane now gets less side padding, because the padding follows the list's own width), and macOS, Windows and Linux have their own styles now (3.x used the iOS style on macOS and Windows, the Android style on Linux). Colors you set in SettingsThemeData still win. To keep one style on every platform, set platform.
  7. Remove 3.x workarounds, such as a trailing: Text(...) added because iOS simple tiles didn't show value.

If a debug build prints settings_ui: SettingsList found no Theme, that screen still sits under a package:flutter/material.dart app or theme.

A coding agent can do the upgrade: use the "Upgrade settings_ui 3.x to 4.0" prompt in agent prompts.

Known issues #

  • iOS, VoiceOver: after a SettingsSplitView changes layout (rotation, an iPad window resize), VoiceOver can misplace the rows' frames until the app restarts. It is a Flutter engine bug; touch input is not affected.

License #

Apache License 2.0. See the LICENSE file for details.

1.04k
likes
160
points
336k
downloads
screenshot

Documentation

API reference

Publisher

verified publisheryako.dev

Weekly Downloads

Settings screens that look native on iOS, Android, macOS, Windows, Linux (GNOME) and the web, from one API, with sub-pages and a split view for tablets and desktop.

Repository (GitHub)
View/report issues

Topics

#settings #preferences #ui #widget #adaptive

License

Apache-2.0 (license)

Dependencies

cupertino_ui, flutter, material_ui

More

Packages that depend on settings_ui