adapt method

T adapt(
  1. ThemeData theme,
  2. T defaultValue
)

Typically, this is overridden to return an instance of a custom component ThemeData class, like SwitchThemeData, instead of the defaultValue.

Factory constructors that support adaptations - currently only Switch.adaptive - look for a type-specific adaptation in ThemeData.adaptationMap when computing their effective default component theme. If a matching adaptation is not found, the component may choose to use a default adaptation. For example, the Switch.adaptive component uses an empty SwitchThemeData if a matching adaptation is not found, for the sake of backwards compatibility.

This sample shows how to create and use subclasses of Adaptation that define adaptive SwitchThemeDatas. The adapt method in this example is overridden to only customize cupertino-style switches, but it can also be used to customize any other platforms.

To see it in action, copy and run this code snippet on DartPad.

import 'package:material_ui/material_ui.dart';

/// Flutter code sample for [Switch.adaptive].

void main() => runApp(const SwitchApp());

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

  @override
  State<SwitchApp> createState() => _SwitchAppState();
}

class _SwitchAppState extends State<SwitchApp> {
  bool isMaterial = true;
  bool isCustomized = false;

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = ThemeData(
      platform: isMaterial ? .android : .iOS,
      adaptations: <Adaptation<Object>>[
        if (isCustomized) const _SwitchThemeAdaptation(),
      ],
    );
    final ButtonStyle style = OutlinedButton.styleFrom(
      fixedSize: const Size(220, 40),
    );

    return MaterialApp(
      theme: theme,
      home: Scaffold(
        appBar: AppBar(title: const Text('Adaptive Switches')),
        body: Column(
          mainAxisAlignment: .center,
          children: <Widget>[
            OutlinedButton(
              style: style,
              onPressed: () {
                setState(() {
                  isMaterial = !isMaterial;
                });
              },
              child: isMaterial
                  ? const Text('Show cupertino style')
                  : const Text('Show material style'),
            ),
            OutlinedButton(
              style: style,
              onPressed: () {
                setState(() {
                  isCustomized = !isCustomized;
                });
              },
              child: isCustomized
                  ? const Text('Remove customization')
                  : const Text('Add customization'),
            ),
            const SizedBox(height: 20),
            const SwitchWithLabel(label: 'enabled', enabled: true),
            const SwitchWithLabel(label: 'disabled', enabled: false),
          ],
        ),
      ),
    );
  }
}

class SwitchWithLabel extends StatefulWidget {
  const SwitchWithLabel({
    super.key,
    required this.enabled,
    required this.label,
  });

  final bool enabled;
  final String label;

  @override
  State<SwitchWithLabel> createState() => _SwitchWithLabelState();
}

class _SwitchWithLabelState extends State<SwitchWithLabel> {
  bool active = true;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: .center,
      children: <Widget>[
        Container(
          width: 150,
          padding: const .only(right: 20),
          child: Text(widget.label),
        ),
        Switch.adaptive(
          value: active,
          onChanged: !widget.enabled
              ? null
              : (bool value) {
                  setState(() {
                    active = value;
                  });
                },
        ),
      ],
    );
  }
}

class _SwitchThemeAdaptation extends Adaptation<SwitchThemeData> {
  const _SwitchThemeAdaptation();

  @override
  SwitchThemeData adapt(ThemeData theme, SwitchThemeData defaultValue) {
    switch (theme.platform) {
      case .android:
      case .fuchsia:
      case .linux:
      case .windows:
        return defaultValue;
      case .iOS:
      case .macOS:
        return const SwitchThemeData(
          thumbColor: WidgetStateProperty<Color?>.fromMap(<WidgetState, Color>{
            WidgetState.selected: Colors.yellow,
            // Resolves to null if not selected, deferring to default values.
          }),
          trackColor: WidgetStatePropertyAll<Color>(Colors.brown),
        );
    }
  }
}

Implementation

// TODO(framework): Replace the following block with a @dartpad directive
// when it's supported. https://github.com/dart-lang/dartdoc/issues/4123
/// {@macro material_ui.dartpad_guide}
///
/// {@example /example/lib/switch/switch.4.dart#body}
///
/// </callout-box>
T adapt(ThemeData theme, T defaultValue) => defaultValue;