'Is there a cupertino equivelent of SwitchListTile?

I need to create a settings page for my iOS app. On my Android side, I have SwitchListTile to layout the switches nicely.

Is there a Flutter widget that would help me or do I have to write one myself?



Solution 1:[1]

You have to write one yourself, however you can crib from the SwitchListTile source pretty easily:

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

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  bool _isSelected = false;

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new SafeArea(
          child: new Material(
              child: new ListView(
                children: <Widget>[
                  new CupertinoSwitchListTile(
                    value: _isSelected,
                    onChanged: (value) {
                      print("Value changed to $value");
                      setState(() => _isSelected = value);
                    },
                    activeColor: CupertinoColors.activeGreen
                  )
                ],
              ))),
    );
  }

}

class CupertinoSwitchListTile extends StatelessWidget {
  /// This has been shamelessly copied from Material/SwitchListTile.
  /// The applicable license applies.
  const CupertinoSwitchListTile({
    Key key,
    @required this.value,
    @required this.onChanged,
    this.activeColor,
    this.title,
    this.subtitle,
    this.isThreeLine: false,
    this.dense,
    this.secondary,
    this.selected: false,
  })  : assert(value != null),
        assert(isThreeLine != null),
        assert(!isThreeLine || subtitle != null),
        assert(selected != null),
        super(key: key);

  /// Whether this switch is checked.
  ///
  /// This property must not be null.
  final bool value;

  /// Called when the user toggles the switch on or off.
  ///
  /// The switch passes the new value to the callback but does not actually
  /// change state until the parent widget rebuilds the switch tile with the
  /// new value.
  ///
  /// If null, the switch will be displayed as disabled.
  ///
  /// The callback provided to [onChanged] should update the state of the parent
  /// [StatefulWidget] using the [State.setState] method, so that the parent
  /// gets rebuilt; for example:
  ///
  /// ```dart
  /// new SwitchListTile(
  ///   value: _lights,
  ///   onChanged: (bool newValue) {
  ///     setState(() {
  ///       _lights = newValue;
  ///     });
  ///   },
  ///   title: new Text('Lights'),
  /// )
  /// ```
  final ValueChanged<bool> onChanged;

  /// The color to use when this switch is on.
  ///
  /// Defaults to accent color of the current [Theme].
  final Color activeColor;

  /// The primary content of the list tile.
  ///
  /// Typically a [Text] widget.
  final Widget title;

  /// Additional content displayed below the title.
  ///
  /// Typically a [Text] widget.
  final Widget subtitle;

  /// A widget to display on the opposite side of the tile from the switch.
  ///
  /// Typically an [Icon] widget.
  final Widget secondary;

  /// Whether this list tile is intended to display three lines of text.
  ///
  /// If false, the list tile is treated as having one line if the subtitle is
  /// null and treated as having two lines if the subtitle is non-null.
  final bool isThreeLine;

  /// Whether this list tile is part of a vertically dense list.
  ///
  /// If this property is null then its value is based on [ListTileTheme.dense].
  final bool dense;

  /// Whether to render icons and text in the [activeColor].
  ///
  /// No effort is made to automatically coordinate the [selected] state and the
  /// [value] state. To have the list tile appear selected when the switch is
  /// on, pass the same value to both.
  ///
  /// Normally, this property is left to its default value, false.
  final bool selected;

  @override
  Widget build(BuildContext context) {
    var color =  activeColor ?? Theme.of(context).accentColor;
    print("Active color: ${color.red} ${color.green} ${color.blue}");
    final Widget control = new CupertinoSwitch(
      value: value,
      onChanged: onChanged,
      activeColor: activeColor ?? CupertinoColors.activeGreen,
    );
    return new MergeSemantics(
      child: ListTileTheme.merge(
        selectedColor: activeColor ?? CupertinoColors.activeGreen,
        child: new ListTile(
          leading: secondary,
          title: title,
          subtitle: subtitle,
          trailing: control,
          isThreeLine: isThreeLine,
          dense: dense,
          enabled: onChanged != null,
          onTap: onChanged != null
              ? () {
                  onChanged(!value);
                }
              : null,
          selected: selected,
        ),
      ),
    );
  }
}

As I noted in the source, because it's copied from the flutter source the license at time of copying from the source applies.

Solution 2:[2]

Use SwitchListTile.adaptive widget instead of SwitchListTile widget

Solution 3:[3]

Since Flutter 2, there are now Cupertino equivalents of the SwitchListTile.

You can use a combination of CupertinoFormSection, CupertinoFormRow, CupertinoSwitch widgets to produce validated form fields with iOS’s sectioned visual aesthetics.

CupertinoFormSection(
  header: Text('Section 1'),
  children: <Widget>[
    CupertinoFormRow(
      child: CupertinoSwitch(
        value: toggleValue,
        onChanged: (value) {
          setState(() {
            toggleValue = value;
          });
        },
      ),
      prefix: Text('Toggle 1'),
      helper: Text('Slide me'),
      error: toggleValue ? null : Text('Not slided'),
    ),
    CupertinoFormRow(
      child: CupertinoSwitch(
        value: !toggleValue,
        onChanged: (value) {
          setState(() {
            toggleValue = value;
          });
        },
      ),
      prefix: Text('Toggle 2'),
    ),
  ],
)

Cupertino form with Switch

Solution 4:[4]

Just Change the SwitchListTile to ListTile remove the fields "value" and "onchanged" and set a CupertinoSwitch as a trailing parameter. like this

From:

return SwitchListTile(
    title: Text(title),
    subtitle: Text(subTitle),
    value: value,
    onChanged: onChanged);

To:

return ListTile(
  title: Text(title),
  subtitle: Text(subTitle),
  trailing: CupertinoSwitch(value: value, onChanged: onChanged),
);

hope that it helped.

Solution 5:[5]

Make a custom component like this:

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

class CupertinoSwitchListTile extends StatelessWidget {
  const CupertinoSwitchListTile({
    Key key,
    @required this.onChanged,
    @required this.value,
    @required this.text,
  }) : super(key: key);

  final Function onChanged;
  final bool value;
  final String text;

  @override
  Widget build(BuildContext context) {
    return ListTile(
      onTap: onChanged,
      title: Text(text),
      leading: CupertinoSwitch(
        value: value,
        onChanged: (bool isChecked) => onChanged(),
      ),
    );
  }
}

Use it like this after declare a bool variable called a boolValue in a statefullWidget:

CupertinoSwitchListTile(
                    onChanged: () {
                      setState(() {
                          boolValue = !boolValue;
                      });
                    },
                    text: 'toggle switch',
                    value: boolValue,
                  )

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rmtmckenzie
Solution 2 Badi3
Solution 3 Etienne
Solution 4 Vitor Medeiros
Solution 5