Cupertino Widgets in Flutter

This code snippet demonstrates how to use various Cupertino widgets in Flutter, including activity indicators, alerts, buttons, context menus, navigation bars, pickers, scrollbars, segmented controls, sliders, switches, tab bars, and text fields.

Here's an overview of some of the Cupertino-style widgets available in Flutter:

Cupertino Activity Indicator

An iOS-style activity indicator that spins clockwise.

The CupertinoActivityIndicator widget displays a spinning wheel to indicate that the application is busy.

import 'package:flutter/cupertino.dart';

class CupertinoActivityIndicatorDemo extends StatelessWidget {
  const CupertinoActivityIndicatorDemo({Key? key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: CupertinoActivityIndicator(),
    );
  }
}

..

Cupertino Alerts

iOS-style activity indicators

The showCupertinoDialog function displays an alert dialog with a message and optional buttons.

import 'package:flutter/cupertino.dart';

class CupertinoAlertDialogDemo extends StatelessWidget {
  const CupertinoAlertDialogDemo({Key? key});

  @override
  Widget build(BuildContext context) {
    return CupertinoButton(
      child: const Text('Show Alert'),
      onPressed: () {
        showCupertinoDialog(
          context: context,
          builder: (BuildContext context) => CupertinoAlertDialog(
            title: const Text('Alert'),
            content: const Text('This is an alert dialog.'),
            actions: <CupertinoDialogAction>[
              CupertinoDialogAction(
                child: const Text('OK'),
                onPressed: () => Navigator.pop(context),
              ),
            ],
          ),
        );
      },
    );
  }
}

  • Cupertino Dialogs in Flutter: A Step-by-Step Guide to Professional App Design  Read More

..

Cupertino Button

An iOS-style button. It takes in text and/or an icon that fades out and in on touch. May optionally have a background.

The CupertinoButton widget displays a button in the Cupertino style.

import 'package:flutter/cupertino.dart';

class CupertinoButtonDemo extends StatelessWidget {
  const CupertinoButtonDemo({Key? key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: CupertinoButton(
        child: const Text('Press me'),
        onPressed: () {},
      ),
    );
  }
}

import 'package:flutter/cupertino.dart';

class CupertinoButtonDemo extends StatelessWidget {
  const CupertinoButtonDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        automaticallyImplyLeading: false,
        middle: Text('Buttons'),
      ),
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CupertinoButton(
              onPressed: () {},
              child: const Text(
                'Button',
              ),
            ),
            const SizedBox(height: 16),
            CupertinoButton.filled(
              onPressed: () {},
              child: const Text(
                'Button With Background',
              ),
            ),
            const SizedBox(height: 30),
            // Disabled buttons
            const CupertinoButton(
              onPressed: null,
              child: Text(
                'Button',
              ),
            ),
            const SizedBox(height: 16),
            const CupertinoButton.filled(
              onPressed: null,
              child: Text(
                'Button With Background',
              ),
            ),
          ],
        ),
      ),
    );
  }
}

..

Context Menu

An iOS-style full screen contextual menu that appears when an element is long-pressed.

The CupertinoContextMenu widget displays a context menu when the user long-presses a widget.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class CupertinoContextMenuDemo extends StatelessWidget {
  const CupertinoContextMenuDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        automaticallyImplyLeading: false,
        middle: Text(
          'Context Menu', // set title of the page
        ),
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: SizedBox(
              width: 100,
              height: 100,
              child: CupertinoContextMenu(
                actions: [
                  CupertinoContextMenuAction(
                    onPressed: () {
                      Navigator.pop(context); // close the context menu on tap of 'Action One'
                    },
                    child: const Text(
                      'Action One', // set text for 'Action One'
                    ),
                  ),
                  CupertinoContextMenuAction(
                    onPressed: () {
                      Navigator.pop(context); // close the context menu on tap of 'Action Two'
                    },
                    child: const Text(
                      'Action Two', // set text for 'Action Two'
                    ),
                  ),
                ],
                child: const FlutterLogo(size: 250), // set child widget for the context menu
              ),
            ),
          ),
          const SizedBox(height: 20), // add space between logo and text
          const Padding(
            padding: EdgeInsets.all(30),
            child: Text(
              'Tap and hold the flutter logo to see the context menu.', // set instruction text
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: 12,
                color: Colors.black, // set text color to black
              ),
            ),
          ),
        ],
      ),
    );
  }
}

..

Navigation bar

An iOS-styled navigation bar. The navigation bar is a toolbar that minimally consists of a page title, in the middle of the toolbar.

The CupertinoNavigationBar widget displays a navigation bar in the Cupertino style.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class CupertinoNavigationBarDemo extends StatelessWidget {
  const CupertinoNavigationBarDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return const CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('My App'),
      ),
      child: Center(
        child: Text('Hello, world!' , style: TextStyle(
          fontSize: 12,
          color: Colors.black, // set text color to black
        ),),
      ),
    );
  }
}

..

Pickers

The Cupertino Picker widgets allow the user to select a value from a range of values using spinning wheels.

import 'package:flutter/cupertino.dart';

class CupertinoPickerDemos extends StatefulWidget {
  const CupertinoPickerDemos({super.key}); // Constructor for CupertinoPickerDemos

  @override
  CupertinoPickerDemosState createState() => CupertinoPickerDemosState(); // Create state for CupertinoPickerDemos
}

class CupertinoPickerDemosState extends State<CupertinoPickerDemos> {

  final List<String> _items = [ // Create a list of items to display in the picker
    'Item 1',
    'Item 2',
    'Item 3',
    'Item 4',
    'Item 5',
  ];

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text('Cupertino Picker'),
      ),
      child: SafeArea(
        child: Center(
          child: CupertinoPicker(
            itemExtent: 32.0, // Set the height of each item in the picker
            onSelectedItemChanged: (index) {
              setState(() {
                // Update the state when an item is selected
              });
            },
            children: _items
                .map((item) => Text(item))
                .toList(), // Create list of Text widgets for each item in the picker
          ),
        ),
      ),
    );
  }
}

..

Segmented Control in Cupertino Style

Used to select between a number of mutually exclusive options. When one option in the segmented control is selected, the other options in the segmented control cease to be selected.

A segmented control is a horizontal set of two or more segments, each of which functions as a button. When a segment is tapped, it remains selected until another segment is tapped.

import 'package:flutter/cupertino.dart';

// Define a StatefulWidget for the CupertinoSegmentedControlDemo widget
class CupertinoSegmentedControlDemo extends StatefulWidget {
  const CupertinoSegmentedControlDemo({super.key});

  @override
  State<CupertinoSegmentedControlDemo> createState() =>
      _CupertinoSegmentedControlDemoState();
}

// Define the State class for CupertinoSegmentedControlDemo with RestorationMixin
class _CupertinoSegmentedControlDemoState
    extends State<CupertinoSegmentedControlDemo> with RestorationMixin {

  // Define a RestorableInt variable to hold the current segment value
  RestorableInt currentSegment = RestorableInt(0);

  // Define the restoration ID for the widget
  @override
  String get restorationId => 'cupertino_segmented_control';

  // Register the RestorableInt variable for state restoration
  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    registerForRestoration(currentSegment, 'current_segment');
  }

  // Define the onValueChanged function to handle changes to the selected segment
  void onValueChanged(int? newValue) {
    setState(() {
      currentSegment.value = newValue!;
    });
  }

  // Build the CupertinoSegmentedControlDemo widget
  @override
  Widget build(BuildContext context) {
    // Define the maximum width of the segmented controls
    const segmentedControlMaxWidth = 500.0;

    // Define the children for the segmented controls
    final children = <int, Widget>{
      0: const Text('Indigo'),
      1: const Text('Teal'),
      2: const Text('Cyan'),
    };

    // Return the CupertinoPageScaffold widget with a navigation bar and a child ListView
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        automaticallyImplyLeading: false,
        middle: Text(
          'Segmented Control',
        ),
      ),
      child: DefaultTextStyle(
        // Set the text style of the child widgets
        style: CupertinoTheme.of(context)
            .textTheme
            .textStyle
            .copyWith(fontSize: 13),
        child: SafeArea(
          // Wrap the child ListView in a SafeArea widget
          child: ListView(
            children: [
              const SizedBox(height: 16),
              SizedBox(
                // Set the width of the first segmented control
                width: segmentedControlMaxWidth,
                child: CupertinoSegmentedControl<int>(
                  children: children,
                  onValueChanged: onValueChanged,
                  groupValue: currentSegment.value,
                ),
              ),
              SizedBox(
                // Set the width of the second segmented control and wrap it in a Padding widget
                width: segmentedControlMaxWidth,
                child: Padding(
                  padding: const EdgeInsets.all(16),
                  child: CupertinoSlidingSegmentedControl<int>(
                    children: children,
                    onValueChanged: onValueChanged,
                    groupValue: currentSegment.value,
                  ),
                ),
              ),
              // Display the selected segment content in a container
              Container(
                padding: const EdgeInsets.all(16),
                height: 300,
                alignment: Alignment.center,
                child: children[currentSegment.value],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

..

Flutter Cupertino Slider

A slider can be used to select from either a continuous or a discrete set of values.

The Cupertino slider is a slider that is designed in the same style as the iOS native slider. It can be used to allow the user to select a value from a continuous range of values by dragging the slider knob.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class CupertinoSliderEx extends StatefulWidget {
  const CupertinoSliderEx ({Key? key}) : super(key: key);

  @override
  CupertinoSliderExState createState() => CupertinoSliderExState();
}

class CupertinoSliderExState extends State<CupertinoSliderEx > {
  double _sliderValue = 50; // initial value of the slider

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text('Cupertino Slider'), // title of the navigation bar
      ),
      child: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              // Cupertino slider widget
              CupertinoSlider(
                value: _sliderValue, // current value of the slider
                min: 0, // minimum value of the slider
                max: 100, // maximum value of the slider
                onChanged: (newValue) {
                  setState(() {
                    _sliderValue = newValue; // update the value of the slider
                  });
                },
              ),
              // display the current value of the slider
              Text('Slider Value: ${_sliderValue.toInt()}',
                style: const TextStyle(
                  fontSize: 12,
                  color: Colors.black, // set text color to black
                ),),
            ],
          ),
        ),
      ),
    );
  }
}

..

Flutter Cupertino Switch

A switch is used to toggle the on/off state of a single setting.

The Cupertino switch is a switch that is designed in the same style as the iOS native switch. It can be used to allow the user to toggle between two states.

import 'package:flutter/cupertino.dart';

class CupertinoSwitchEx extends StatefulWidget {
  const CupertinoSwitchEx({Key? key}) : super(key: key);

  @override
  CupertinoSwitchExState createState() => CupertinoSwitchExState();
}

class CupertinoSwitchExState extends State<CupertinoSwitchEx> {
  bool _switchValue = false; // initial value of the switch

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text('Cupertino Switch'), // title of the navigation bar
      ),
      child: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              // Cupertino switch widget
              CupertinoSwitch(
                value: _switchValue, // current value of the switch
                onChanged: (newValue) {
                  setState(() {
                    _switchValue = newValue; // update the value of the switch
                  });
                },
              ),
              // display the current state of the switch
              Text('Switch Value: ${_switchValue.toString()}'),
            ],
          ),
        ),
      ),
    );
  }
}

..

Cupertino Tab Bar

An iOS-style bottom navigation tab bar. Displays multiple tabs with one tab being active, the first tab by default.

A tab bar is a horizontal navigation bar that allows users to switch between different views, typically by tapping on tabs at the bottom of the screen. In Cupertino style, the tab bar has a white background with a subtle gray border at the top and bottom.

import 'package:flutter/cupertino.dart';

// A class to hold information about each tab
class _TabInfo {
  const _TabInfo(this.title, this.icon);

  final String title;
  final IconData icon;
}

// A demo widget that shows how to use the CupertinoTabBar and CupertinoTabView
class CupertinoTabBarDemo extends StatelessWidget {
  const CupertinoTabBarDemo({super.key});

  @override
  Widget build(BuildContext context) {
    // Create a list of tab information using the _TabInfo class
    final tabInfo = [
      const _TabInfo(
        'Home',
        CupertinoIcons.home,
      ),
      const _TabInfo(
        'Chat',
        CupertinoIcons.conversation_bubble,
      ),
      const _TabInfo(
        'Profile',
        CupertinoIcons.profile_circled,
      ),
    ];

    // Wrap the entire widget tree with a DefaultTextStyle widget to use the default text style of the CupertinoTheme
    return DefaultTextStyle(
      style: CupertinoTheme.of(context).textTheme.textStyle,
      child: CupertinoTabScaffold(
        // Set a restoration ID for the entire scaffold to enable state restoration
        restorationId: 'cupertino_tab_scaffold',
        tabBar: CupertinoTabBar(
          // Create a list of BottomNavigationBarItems using the tab information
          items: [
            for (final tabInfo in tabInfo)
              BottomNavigationBarItem(
                label: tabInfo.title,
                icon: Icon(tabInfo.icon),
              ),
          ],
        ),
        tabBuilder: (context, index) {
          // Create a CupertinoTabView for each tab using the _CupertinoDemoTab widget
          return CupertinoTabView(
            // Set a restoration scope ID for each tab view to enable state restoration
            restorationScopeId: 'cupertino_tab_view_$index',
            builder: (context) => _CupertinoDemoTab(
              title: tabInfo[index].title,
              icon: tabInfo[index].icon,
            ),
            defaultTitle: tabInfo[index].title,
          );
        },
      ),
    );
  }
}

// A demo tab that shows an icon with the tab's title as the semantic label
class _CupertinoDemoTab extends StatelessWidget {
  const _CupertinoDemoTab({
    required this.title,
    required this.icon,
  });

  final String title;
  final IconData icon;

  @override
  Widget build(BuildContext context) {
    // Create a centered icon with the tab's title as the semantic label
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(),
      backgroundColor: CupertinoColors.systemBackground,
      child: Center(
        child: Icon(
          icon,
          semanticLabel: title,
          size: 100,
        ),
      ),
    );
  }
}

..

Flutter Text Fields

A text field lets the user enter text, either with a hardware keyboard or with an onscreen keyboard.

How to use text fields in Flutter.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class TextFieldDemoEx extends StatefulWidget {
  const TextFieldDemoEx({Key? key}) : super(key: key);

  @override
  TextFieldDemoExState createState() => TextFieldDemoExState();
}

class TextFieldDemoExState extends State<TextFieldDemoEx> {
  final TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Text Fields'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // Basic Text Field
            const Text(
              'Basic Text Field',
              style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8.0),
            TextField(
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                hintText: 'Enter some text',
              ),
              controller: _controller,
            ),
            const SizedBox(height: 16.0),

            // Password Text Field
            const Text(
              'Password Text Field',
              style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8.0),
            TextField(
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                hintText: 'Enter your password',
              ),
              controller: _controller,
              obscureText: true, // hides text as bullets
            ),
            const SizedBox(height: 16.0),

            // Multiline Text Field
            const Text(
              'Multiline Text Field',
              style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8.0),
            TextField(
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                hintText: 'Enter some text',
              ),
              controller: _controller,
              maxLines: null, // allows for multiple lines
            ),
            const SizedBox(height: 16.0),

            // Number Text Field
            const Text(
              'Number Text Field',
              style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8.0),
            TextField(
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                hintText: 'Enter a number',
              ),
              controller: _controller,
              keyboardType: TextInputType.number,
            ),
            const SizedBox(height: 16.0),

            // Input Formatters
            const Text(
              'Input Formatters',
              style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8.0),
            TextField(
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                hintText: 'Enter only digits',
              ),
              controller: _controller,
              keyboardType: TextInputType.number,
              inputFormatters: <TextInputFormatter>[
                FilteringTextInputFormatter.digitsOnly,
              ],
            ),
          ],
        ),
      ),
    );
  }
}

..

Comments