switch_theme.dart 8.76 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui' show lerpDouble;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

import 'material_state.dart';
import 'theme.dart';
import 'theme_data.dart';

15 16 17
// Examples can assume:
// late BuildContext context;

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
/// Defines default property values for descendant [Switch] widgets.
///
/// Descendant widgets obtain the current [SwitchThemeData] object using
/// `SwitchTheme.of(context)`. Instances of [SwitchThemeData] can be customized
/// with [SwitchThemeData.copyWith].
///
/// Typically a [SwitchThemeData] is specified as part of the overall [Theme]
/// with [ThemeData.switchTheme].
///
/// All [SwitchThemeData] properties are `null` by default. When null, the
/// [Switch] will use the values from [ThemeData] if they exist, otherwise it
/// will provide its own defaults based on the overall [Theme]'s colorScheme.
/// See the individual [Switch] properties for details.
///
/// See also:
///
///  * [ThemeData], which describes the overall theme information for the
///    application.
@immutable
class SwitchThemeData with Diagnosticable {
  /// Creates a theme that can be used for [ThemeData.switchTheme].
  const SwitchThemeData({
    this.thumbColor,
    this.trackColor,
42
    this.trackOutlineColor,
43
    this.trackOutlineWidth,
44 45 46 47
    this.materialTapTargetSize,
    this.mouseCursor,
    this.overlayColor,
    this.splashRadius,
48
    this.thumbIcon,
49 50 51 52 53 54 55 56 57 58 59 60
  });

  /// {@macro flutter.material.switch.thumbColor}
  ///
  /// If specified, overrides the default value of [Switch.thumbColor].
  final MaterialStateProperty<Color?>? thumbColor;

  /// {@macro flutter.material.switch.trackColor}
  ///
  /// If specified, overrides the default value of [Switch.trackColor].
  final MaterialStateProperty<Color?>? trackColor;

61 62 63 64 65
  /// {@macro flutter.material.switch.trackOutlineColor}
  ///
  /// If specified, overrides the default value of [Switch.trackOutlineColor].
  final MaterialStateProperty<Color?>? trackOutlineColor;

66 67 68 69 70
  /// {@macro flutter.material.switch.trackOutlineWidth}
  ///
  /// If specified, overrides the default value of [Switch.trackOutlineWidth].
  final MaterialStateProperty<double?>? trackOutlineWidth;

71 72 73 74 75 76 77 78 79 80 81
  /// {@macro flutter.material.switch.materialTapTargetSize}
  ///
  /// If specified, overrides the default value of
  /// [Switch.materialTapTargetSize].
  final MaterialTapTargetSize? materialTapTargetSize;

  /// {@macro flutter.material.switch.mouseCursor}
  ///
  /// If specified, overrides the default value of [Switch.mouseCursor].
  final MaterialStateProperty<MouseCursor?>? mouseCursor;

82
  /// {@macro flutter.material.switch.overlayColor}
83
  ///
84
  /// If specified, overrides the default value of [Switch.overlayColor].
85 86 87 88 89 90 91
  final MaterialStateProperty<Color?>? overlayColor;

  /// {@macro flutter.material.switch.splashRadius}
  ///
  /// If specified, overrides the default value of [Switch.splashRadius].
  final double? splashRadius;

92 93 94 95 96
  /// {@macro flutter.material.switch.thumbIcon}
  ///
  /// It is overridden by [Switch.thumbIcon].
  final MaterialStateProperty<Icon?>? thumbIcon;

97 98 99 100 101
  /// Creates a copy of this object but with the given fields replaced with the
  /// new values.
  SwitchThemeData copyWith({
    MaterialStateProperty<Color?>? thumbColor,
    MaterialStateProperty<Color?>? trackColor,
102
    MaterialStateProperty<Color?>? trackOutlineColor,
103
    MaterialStateProperty<double?>? trackOutlineWidth,
104 105 106 107
    MaterialTapTargetSize? materialTapTargetSize,
    MaterialStateProperty<MouseCursor?>? mouseCursor,
    MaterialStateProperty<Color?>? overlayColor,
    double? splashRadius,
108
    MaterialStateProperty<Icon?>? thumbIcon,
109 110 111 112
  }) {
    return SwitchThemeData(
      thumbColor: thumbColor ?? this.thumbColor,
      trackColor: trackColor ?? this.trackColor,
113
      trackOutlineColor: trackOutlineColor ?? this.trackOutlineColor,
114
      trackOutlineWidth: trackOutlineWidth ?? this.trackOutlineWidth,
115 116 117 118
      materialTapTargetSize: materialTapTargetSize ?? this.materialTapTargetSize,
      mouseCursor: mouseCursor ?? this.mouseCursor,
      overlayColor: overlayColor ?? this.overlayColor,
      splashRadius: splashRadius ?? this.splashRadius,
119
      thumbIcon: thumbIcon ?? this.thumbIcon,
120 121 122 123 124 125 126
    );
  }

  /// Linearly interpolate between two [SwitchThemeData]s.
  ///
  /// {@macro dart.ui.shadow.lerp}
  static SwitchThemeData lerp(SwitchThemeData? a, SwitchThemeData? b, double t) {
127 128 129
    if (identical(a, b) && a != null) {
      return a;
    }
130
    return SwitchThemeData(
131 132
      thumbColor: MaterialStateProperty.lerp<Color?>(a?.thumbColor, b?.thumbColor, t, Color.lerp),
      trackColor: MaterialStateProperty.lerp<Color?>(a?.trackColor, b?.trackColor, t, Color.lerp),
133
      trackOutlineColor: MaterialStateProperty.lerp<Color?>(a?.trackOutlineColor, b?.trackOutlineColor, t, Color.lerp),
134
      trackOutlineWidth: MaterialStateProperty.lerp<double?>(a?.trackOutlineWidth, b?.trackOutlineWidth, t, lerpDouble),
135 136
      materialTapTargetSize: t < 0.5 ? a?.materialTapTargetSize : b?.materialTapTargetSize,
      mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
137
      overlayColor: MaterialStateProperty.lerp<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp),
138
      splashRadius: lerpDouble(a?.splashRadius, b?.splashRadius, t),
139
      thumbIcon: t < 0.5 ? a?.thumbIcon : b?.thumbIcon,
140 141 142 143
    );
  }

  @override
144 145 146
  int get hashCode => Object.hash(
    thumbColor,
    trackColor,
147
    trackOutlineColor,
148
    trackOutlineWidth,
149 150 151 152
    materialTapTargetSize,
    mouseCursor,
    overlayColor,
    splashRadius,
153
    thumbIcon,
154
  );
155 156 157

  @override
  bool operator ==(Object other) {
158
    if (identical(this, other)) {
159
      return true;
160 161
    }
    if (other.runtimeType != runtimeType) {
162
      return false;
163
    }
164 165 166
    return other is SwitchThemeData
      && other.thumbColor == thumbColor
      && other.trackColor == trackColor
167
      && other.trackOutlineColor == trackOutlineColor
168
      && other.trackOutlineWidth == trackOutlineWidth
169 170 171
      && other.materialTapTargetSize == materialTapTargetSize
      && other.mouseCursor == mouseCursor
      && other.overlayColor == overlayColor
172 173
      && other.splashRadius == splashRadius
      && other.thumbIcon == thumbIcon;
174 175 176 177 178 179 180
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('thumbColor', thumbColor, defaultValue: null));
    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('trackColor', trackColor, defaultValue: null));
181
    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('trackOutlineColor', trackOutlineColor, defaultValue: null));
182
    properties.add(DiagnosticsProperty<MaterialStateProperty<double?>>('trackOutlineWidth', trackOutlineWidth, defaultValue: null));
183 184 185 186
    properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize, defaultValue: null));
    properties.add(DiagnosticsProperty<MaterialStateProperty<MouseCursor?>>('mouseCursor', mouseCursor, defaultValue: null));
    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('overlayColor', overlayColor, defaultValue: null));
    properties.add(DoubleProperty('splashRadius', splashRadius, defaultValue: null));
187
    properties.add(DiagnosticsProperty<MaterialStateProperty<Icon?>>('thumbIcon', thumbIcon, defaultValue: null));
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
  }
}

/// Applies a switch theme to descendant [Switch] widgets.
///
/// Descendant widgets obtain the current theme's [SwitchTheme] object using
/// [SwitchTheme.of]. When a widget uses [SwitchTheme.of], it is automatically
/// rebuilt if the theme later changes.
///
/// A switch theme can be specified as part of the overall Material theme using
/// [ThemeData.switchTheme].
///
/// See also:
///
///  * [SwitchThemeData], which describes the actual configuration of a switch
///    theme.
class SwitchTheme extends InheritedWidget {
  /// Constructs a switch theme that configures all descendant [Switch] widgets.
  const SwitchTheme({
207
    super.key,
208
    required this.data,
209 210
    required super.child,
  });
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230

  /// The properties used for all descendant [Switch] widgets.
  final SwitchThemeData data;

  /// Returns the configuration [data] from the closest [SwitchTheme] ancestor.
  /// If there is no ancestor, it returns [ThemeData.switchTheme].
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// SwitchThemeData theme = SwitchTheme.of(context);
  /// ```
  static SwitchThemeData of(BuildContext context) {
    final SwitchTheme? switchTheme = context.dependOnInheritedWidgetOfExactType<SwitchTheme>();
    return switchTheme?.data ?? Theme.of(context).switchTheme;
  }

  @override
  bool updateShouldNotify(SwitchTheme oldWidget) => data != oldWidget.data;
}