| // 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 'list_tile.dart'; |
| import 'material_state.dart'; |
| import 'theme.dart'; |
| import 'theme_data.dart'; |
| |
| // Examples can assume: |
| // late BuildContext context; |
| |
| /// Used with [ListTileTheme] to define default property values for |
| /// descendant [ListTile] widgets, as well as classes that build |
| /// [ListTile]s, like [CheckboxListTile], [RadioListTile], and |
| /// [SwitchListTile]. |
| /// |
| /// Descendant widgets obtain the current [ListTileThemeData] object |
| /// using `ListTileTheme.of(context)`. Instances of |
| /// [ListTileThemeData] can be customized with |
| /// [ListTileThemeData.copyWith]. |
| /// |
| /// A [ListTileThemeData] is often specified as part of the |
| /// overall [Theme] with [ThemeData.listTileTheme]. |
| /// |
| /// All [ListTileThemeData] properties are `null` by default. |
| /// When a theme property is null, the [ListTile] will provide its own |
| /// default based on the overall [Theme]'s textTheme and |
| /// colorScheme. See the individual [ListTile] properties for details. |
| /// |
| /// The [Drawer] widget specifies a list tile theme for its children that |
| /// defines [style] to be [ListTileStyle.drawer]. |
| /// |
| /// See also: |
| /// |
| /// * [ThemeData], which describes the overall theme information for the |
| /// application. |
| @immutable |
| class ListTileThemeData with Diagnosticable { |
| /// Creates a [ListTileThemeData]. |
| const ListTileThemeData ({ |
| this.dense, |
| this.shape, |
| this.style, |
| this.selectedColor, |
| this.iconColor, |
| this.textColor, |
| this.titleTextStyle, |
| this.subtitleTextStyle, |
| this.leadingAndTrailingTextStyle, |
| this.contentPadding, |
| this.tileColor, |
| this.selectedTileColor, |
| this.horizontalTitleGap, |
| this.minVerticalPadding, |
| this.minLeadingWidth, |
| this.enableFeedback, |
| this.mouseCursor, |
| this.visualDensity, |
| this.titleAlignment, |
| }); |
| |
| /// Overrides the default value of [ListTile.dense]. |
| final bool? dense; |
| |
| /// Overrides the default value of [ListTile.shape]. |
| final ShapeBorder? shape; |
| |
| /// Overrides the default value of [ListTile.style]. |
| final ListTileStyle? style; |
| |
| /// Overrides the default value of [ListTile.selectedColor]. |
| final Color? selectedColor; |
| |
| /// Overrides the default value of [ListTile.iconColor]. |
| final Color? iconColor; |
| |
| /// Overrides the default value of [ListTile.textColor]. |
| final Color? textColor; |
| |
| /// Overrides the default value of [ListTile.titleTextStyle]. |
| final TextStyle? titleTextStyle; |
| |
| /// Overrides the default value of [ListTile.subtitleTextStyle]. |
| final TextStyle? subtitleTextStyle; |
| |
| /// Overrides the default value of [ListTile.leadingAndTrailingTextStyle]. |
| final TextStyle? leadingAndTrailingTextStyle; |
| |
| /// Overrides the default value of [ListTile.contentPadding]. |
| final EdgeInsetsGeometry? contentPadding; |
| |
| /// Overrides the default value of [ListTile.tileColor]. |
| final Color? tileColor; |
| |
| /// Overrides the default value of [ListTile.selectedTileColor]. |
| final Color? selectedTileColor; |
| |
| /// Overrides the default value of [ListTile.horizontalTitleGap]. |
| final double? horizontalTitleGap; |
| |
| /// Overrides the default value of [ListTile.minVerticalPadding]. |
| final double? minVerticalPadding; |
| |
| /// Overrides the default value of [ListTile.minLeadingWidth]. |
| final double? minLeadingWidth; |
| |
| /// Overrides the default value of [ListTile.enableFeedback]. |
| final bool? enableFeedback; |
| |
| /// If specified, overrides the default value of [ListTile.mouseCursor]. |
| final MaterialStateProperty<MouseCursor?>? mouseCursor; |
| |
| /// If specified, overrides the default value of [ListTile.visualDensity]. |
| final VisualDensity? visualDensity; |
| |
| /// If specified, overrides the default value of [ListTile.titleAlignment]. |
| final ListTileTitleAlignment? titleAlignment; |
| |
| /// Creates a copy of this object with the given fields replaced with the |
| /// new values. |
| ListTileThemeData copyWith({ |
| bool? dense, |
| ShapeBorder? shape, |
| ListTileStyle? style, |
| Color? selectedColor, |
| Color? iconColor, |
| Color? textColor, |
| TextStyle? titleTextStyle, |
| TextStyle? subtitleTextStyle, |
| TextStyle? leadingAndTrailingTextStyle, |
| EdgeInsetsGeometry? contentPadding, |
| Color? tileColor, |
| Color? selectedTileColor, |
| double? horizontalTitleGap, |
| double? minVerticalPadding, |
| double? minLeadingWidth, |
| bool? enableFeedback, |
| MaterialStateProperty<MouseCursor?>? mouseCursor, |
| bool? isThreeLine, |
| VisualDensity? visualDensity, |
| ListTileTitleAlignment? titleAlignment, |
| }) { |
| return ListTileThemeData( |
| dense: dense ?? this.dense, |
| shape: shape ?? this.shape, |
| style: style ?? this.style, |
| selectedColor: selectedColor ?? this.selectedColor, |
| iconColor: iconColor ?? this.iconColor, |
| textColor: textColor ?? this.textColor, |
| titleTextStyle: titleTextStyle ?? this.titleTextStyle, |
| subtitleTextStyle: subtitleTextStyle ?? this.subtitleTextStyle, |
| leadingAndTrailingTextStyle: leadingAndTrailingTextStyle ?? this.leadingAndTrailingTextStyle, |
| contentPadding: contentPadding ?? this.contentPadding, |
| tileColor: tileColor ?? this.tileColor, |
| selectedTileColor: selectedTileColor ?? this.selectedTileColor, |
| horizontalTitleGap: horizontalTitleGap ?? this.horizontalTitleGap, |
| minVerticalPadding: minVerticalPadding ?? this.minVerticalPadding, |
| minLeadingWidth: minLeadingWidth ?? this.minLeadingWidth, |
| enableFeedback: enableFeedback ?? this.enableFeedback, |
| mouseCursor: mouseCursor ?? this.mouseCursor, |
| visualDensity: visualDensity ?? this.visualDensity, |
| titleAlignment: titleAlignment ?? this.titleAlignment, |
| ); |
| } |
| |
| /// Linearly interpolate between ListTileThemeData objects. |
| static ListTileThemeData? lerp(ListTileThemeData? a, ListTileThemeData? b, double t) { |
| if (identical(a, b)) { |
| return a; |
| } |
| return ListTileThemeData( |
| dense: t < 0.5 ? a?.dense : b?.dense, |
| shape: ShapeBorder.lerp(a?.shape, b?.shape, t), |
| style: t < 0.5 ? a?.style : b?.style, |
| selectedColor: Color.lerp(a?.selectedColor, b?.selectedColor, t), |
| iconColor: Color.lerp(a?.iconColor, b?.iconColor, t), |
| textColor: Color.lerp(a?.textColor, b?.textColor, t), |
| titleTextStyle: TextStyle.lerp(a?.titleTextStyle, b?.titleTextStyle, t), |
| subtitleTextStyle: TextStyle.lerp(a?.subtitleTextStyle, b?.subtitleTextStyle, t), |
| leadingAndTrailingTextStyle: TextStyle.lerp(a?.leadingAndTrailingTextStyle, b?.leadingAndTrailingTextStyle, t), |
| contentPadding: EdgeInsetsGeometry.lerp(a?.contentPadding, b?.contentPadding, t), |
| tileColor: Color.lerp(a?.tileColor, b?.tileColor, t), |
| selectedTileColor: Color.lerp(a?.selectedTileColor, b?.selectedTileColor, t), |
| horizontalTitleGap: lerpDouble(a?.horizontalTitleGap, b?.horizontalTitleGap, t), |
| minVerticalPadding: lerpDouble(a?.minVerticalPadding, b?.minVerticalPadding, t), |
| minLeadingWidth: lerpDouble(a?.minLeadingWidth, b?.minLeadingWidth, t), |
| enableFeedback: t < 0.5 ? a?.enableFeedback : b?.enableFeedback, |
| mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor, |
| visualDensity: t < 0.5 ? a?.visualDensity : b?.visualDensity, |
| titleAlignment: t < 0.5 ? a?.titleAlignment : b?.titleAlignment, |
| ); |
| } |
| |
| @override |
| int get hashCode => Object.hash( |
| dense, |
| shape, |
| style, |
| selectedColor, |
| iconColor, |
| textColor, |
| titleTextStyle, |
| subtitleTextStyle, |
| leadingAndTrailingTextStyle, |
| contentPadding, |
| tileColor, |
| selectedTileColor, |
| horizontalTitleGap, |
| minVerticalPadding, |
| minLeadingWidth, |
| enableFeedback, |
| mouseCursor, |
| visualDensity, |
| titleAlignment, |
| ); |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| return other is ListTileThemeData |
| && other.dense == dense |
| && other.shape == shape |
| && other.style == style |
| && other.selectedColor == selectedColor |
| && other.iconColor == iconColor |
| && other.titleTextStyle == titleTextStyle |
| && other.subtitleTextStyle == subtitleTextStyle |
| && other.leadingAndTrailingTextStyle == leadingAndTrailingTextStyle |
| && other.textColor == textColor |
| && other.contentPadding == contentPadding |
| && other.tileColor == tileColor |
| && other.selectedTileColor == selectedTileColor |
| && other.horizontalTitleGap == horizontalTitleGap |
| && other.minVerticalPadding == minVerticalPadding |
| && other.minLeadingWidth == minLeadingWidth |
| && other.enableFeedback == enableFeedback |
| && other.mouseCursor == mouseCursor |
| && other.visualDensity == visualDensity |
| && other.titleAlignment == titleAlignment; |
| } |
| |
| @override |
| void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
| super.debugFillProperties(properties); |
| properties.add(DiagnosticsProperty<bool>('dense', dense, defaultValue: null)); |
| properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null)); |
| properties.add(EnumProperty<ListTileStyle>('style', style, defaultValue: null)); |
| properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null)); |
| properties.add(ColorProperty('iconColor', iconColor, defaultValue: null)); |
| properties.add(ColorProperty('textColor', textColor, defaultValue: null)); |
| properties.add(DiagnosticsProperty<TextStyle>('titleTextStyle', titleTextStyle, defaultValue: null)); |
| properties.add(DiagnosticsProperty<TextStyle>('subtitleTextStyle', subtitleTextStyle, defaultValue: null)); |
| properties.add(DiagnosticsProperty<TextStyle>('leadingAndTrailingTextStyle', leadingAndTrailingTextStyle, defaultValue: null)); |
| properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('contentPadding', contentPadding, defaultValue: null)); |
| properties.add(ColorProperty('tileColor', tileColor, defaultValue: null)); |
| properties.add(ColorProperty('selectedTileColor', selectedTileColor, defaultValue: null)); |
| properties.add(DoubleProperty('horizontalTitleGap', horizontalTitleGap, defaultValue: null)); |
| properties.add(DoubleProperty('minVerticalPadding', minVerticalPadding, defaultValue: null)); |
| properties.add(DoubleProperty('minLeadingWidth', minLeadingWidth, defaultValue: null)); |
| properties.add(DiagnosticsProperty<bool>('enableFeedback', enableFeedback, defaultValue: null)); |
| properties.add(DiagnosticsProperty<MaterialStateProperty<MouseCursor?>>('mouseCursor', mouseCursor, defaultValue: null)); |
| properties.add(DiagnosticsProperty<VisualDensity>('visualDensity', visualDensity, defaultValue: null)); |
| properties.add(DiagnosticsProperty<ListTileTitleAlignment>('titleAlignment', titleAlignment, defaultValue: null)); |
| } |
| } |
| |
| /// An inherited widget that defines color and style parameters for [ListTile]s |
| /// in this widget's subtree. |
| /// |
| /// Values specified here are used for [ListTile] properties that are not given |
| /// an explicit non-null value. |
| /// |
| /// The [Drawer] widget specifies a tile theme for its children which sets |
| /// [style] to [ListTileStyle.drawer]. |
| class ListTileTheme extends InheritedTheme { |
| /// Creates a list tile theme that defines the color and style parameters for |
| /// descendant [ListTile]s. |
| /// |
| /// Only the [data] parameter should be used. The other parameters are |
| /// redundant (are now obsolete) and will be deprecated in a future update. |
| const ListTileTheme({ |
| super.key, |
| ListTileThemeData? data, |
| bool? dense, |
| ShapeBorder? shape, |
| ListTileStyle? style, |
| Color? selectedColor, |
| Color? iconColor, |
| Color? textColor, |
| EdgeInsetsGeometry? contentPadding, |
| Color? tileColor, |
| Color? selectedTileColor, |
| bool? enableFeedback, |
| MaterialStateProperty<MouseCursor?>? mouseCursor, |
| double? horizontalTitleGap, |
| double? minVerticalPadding, |
| double? minLeadingWidth, |
| required super.child, |
| }) : assert( |
| data == null || |
| (shape ?? |
| selectedColor ?? |
| iconColor ?? |
| textColor ?? |
| contentPadding ?? |
| tileColor ?? |
| selectedTileColor ?? |
| enableFeedback ?? |
| mouseCursor ?? |
| horizontalTitleGap ?? |
| minVerticalPadding ?? |
| minLeadingWidth) == null), |
| _data = data, |
| _dense = dense, |
| _shape = shape, |
| _style = style, |
| _selectedColor = selectedColor, |
| _iconColor = iconColor, |
| _textColor = textColor, |
| _contentPadding = contentPadding, |
| _tileColor = tileColor, |
| _selectedTileColor = selectedTileColor, |
| _enableFeedback = enableFeedback, |
| _mouseCursor = mouseCursor, |
| _horizontalTitleGap = horizontalTitleGap, |
| _minVerticalPadding = minVerticalPadding, |
| _minLeadingWidth = minLeadingWidth; |
| |
| final ListTileThemeData? _data; |
| final bool? _dense; |
| final ShapeBorder? _shape; |
| final ListTileStyle? _style; |
| final Color? _selectedColor; |
| final Color? _iconColor; |
| final Color? _textColor; |
| final EdgeInsetsGeometry? _contentPadding; |
| final Color? _tileColor; |
| final Color? _selectedTileColor; |
| final double? _horizontalTitleGap; |
| final double? _minVerticalPadding; |
| final double? _minLeadingWidth; |
| final bool? _enableFeedback; |
| final MaterialStateProperty<MouseCursor?>? _mouseCursor; |
| |
| /// The configuration of this theme. |
| ListTileThemeData get data { |
| return _data ?? ListTileThemeData( |
| dense: _dense, |
| shape: _shape, |
| style: _style, |
| selectedColor: _selectedColor, |
| iconColor: _iconColor, |
| textColor: _textColor, |
| contentPadding: _contentPadding, |
| tileColor: _tileColor, |
| selectedTileColor: _selectedTileColor, |
| enableFeedback: _enableFeedback, |
| mouseCursor: _mouseCursor, |
| horizontalTitleGap: _horizontalTitleGap, |
| minVerticalPadding: _minVerticalPadding, |
| minLeadingWidth: _minLeadingWidth, |
| ); |
| } |
| |
| /// Overrides the default value of [ListTile.dense]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.dense] property instead. |
| bool? get dense => _data != null ? _data!.dense : _dense; |
| |
| /// Overrides the default value of [ListTile.shape]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.shape] property instead. |
| ShapeBorder? get shape => _data != null ? _data!.shape : _shape; |
| |
| /// Overrides the default value of [ListTile.style]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.style] property instead. |
| ListTileStyle? get style => _data != null ? _data!.style : _style; |
| |
| /// Overrides the default value of [ListTile.selectedColor]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.selectedColor] property instead. |
| Color? get selectedColor => _data != null ? _data!.selectedColor : _selectedColor; |
| |
| /// Overrides the default value of [ListTile.iconColor]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.iconColor] property instead. |
| Color? get iconColor => _data != null ? _data!.iconColor : _iconColor; |
| |
| /// Overrides the default value of [ListTile.textColor]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.textColor] property instead. |
| Color? get textColor => _data != null ? _data!.textColor : _textColor; |
| |
| /// Overrides the default value of [ListTile.contentPadding]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.contentPadding] property instead. |
| EdgeInsetsGeometry? get contentPadding => _data != null ? _data!.contentPadding : _contentPadding; |
| |
| /// Overrides the default value of [ListTile.tileColor]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.tileColor] property instead. |
| Color? get tileColor => _data != null ? _data!.tileColor : _tileColor; |
| |
| /// Overrides the default value of [ListTile.selectedTileColor]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.selectedTileColor] property instead. |
| Color? get selectedTileColor => _data != null ? _data!.selectedTileColor : _selectedTileColor; |
| |
| /// Overrides the default value of [ListTile.horizontalTitleGap]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.horizontalTitleGap] property instead. |
| double? get horizontalTitleGap => _data != null ? _data!.horizontalTitleGap : _horizontalTitleGap; |
| |
| /// Overrides the default value of [ListTile.minVerticalPadding]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.minVerticalPadding] property instead. |
| double? get minVerticalPadding => _data != null ? _data!.minVerticalPadding : _minVerticalPadding; |
| |
| /// Overrides the default value of [ListTile.minLeadingWidth]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.minLeadingWidth] property instead. |
| double? get minLeadingWidth => _data != null ? _data!.minLeadingWidth : _minLeadingWidth; |
| |
| /// Overrides the default value of [ListTile.enableFeedback]. |
| /// |
| /// This property is obsolete: please use the [data] |
| /// [ListTileThemeData.enableFeedback] property instead. |
| bool? get enableFeedback => _data != null ? _data!.enableFeedback : _enableFeedback; |
| |
| /// The [data] property of the closest instance of this class that |
| /// encloses the given context. |
| /// |
| /// If there is no enclosing [ListTileTheme] widget, then |
| /// [ThemeData.listTileTheme] is used (see [Theme.of]). |
| /// |
| /// Typical usage is as follows: |
| /// |
| /// ```dart |
| /// ListTileThemeData theme = ListTileTheme.of(context); |
| /// ``` |
| static ListTileThemeData of(BuildContext context) { |
| final ListTileTheme? result = context.dependOnInheritedWidgetOfExactType<ListTileTheme>(); |
| return result?.data ?? Theme.of(context).listTileTheme; |
| } |
| |
| /// Creates a list tile theme that controls the color and style parameters for |
| /// [ListTile]s, and merges in the current list tile theme, if any. |
| /// |
| /// The [child] argument must not be null. |
| static Widget merge({ |
| Key? key, |
| bool? dense, |
| ShapeBorder? shape, |
| ListTileStyle? style, |
| Color? selectedColor, |
| Color? iconColor, |
| Color? textColor, |
| TextStyle? titleTextStyle, |
| TextStyle? subtitleTextStyle, |
| TextStyle? leadingAndTrailingTextStyle, |
| EdgeInsetsGeometry? contentPadding, |
| Color? tileColor, |
| Color? selectedTileColor, |
| bool? enableFeedback, |
| double? horizontalTitleGap, |
| double? minVerticalPadding, |
| double? minLeadingWidth, |
| ListTileTitleAlignment? titleAlignment, |
| MaterialStateProperty<MouseCursor?>? mouseCursor, |
| VisualDensity? visualDensity, |
| required Widget child, |
| }) { |
| return Builder( |
| builder: (BuildContext context) { |
| final ListTileThemeData parent = ListTileTheme.of(context); |
| return ListTileTheme( |
| key: key, |
| data: ListTileThemeData( |
| dense: dense ?? parent.dense, |
| shape: shape ?? parent.shape, |
| style: style ?? parent.style, |
| selectedColor: selectedColor ?? parent.selectedColor, |
| iconColor: iconColor ?? parent.iconColor, |
| textColor: textColor ?? parent.textColor, |
| titleTextStyle: titleTextStyle ?? parent.titleTextStyle, |
| subtitleTextStyle: subtitleTextStyle ?? parent.subtitleTextStyle, |
| leadingAndTrailingTextStyle: leadingAndTrailingTextStyle ?? parent.leadingAndTrailingTextStyle, |
| contentPadding: contentPadding ?? parent.contentPadding, |
| tileColor: tileColor ?? parent.tileColor, |
| selectedTileColor: selectedTileColor ?? parent.selectedTileColor, |
| enableFeedback: enableFeedback ?? parent.enableFeedback, |
| horizontalTitleGap: horizontalTitleGap ?? parent.horizontalTitleGap, |
| minVerticalPadding: minVerticalPadding ?? parent.minVerticalPadding, |
| minLeadingWidth: minLeadingWidth ?? parent.minLeadingWidth, |
| titleAlignment: titleAlignment ?? parent.titleAlignment, |
| mouseCursor: mouseCursor ?? parent.mouseCursor, |
| visualDensity: visualDensity ?? parent.visualDensity, |
| ), |
| child: child, |
| ); |
| }, |
| ); |
| } |
| |
| @override |
| Widget wrap(BuildContext context, Widget child) { |
| return ListTileTheme( |
| data: ListTileThemeData( |
| dense: dense, |
| shape: shape, |
| style: style, |
| selectedColor: selectedColor, |
| iconColor: iconColor, |
| textColor: textColor, |
| contentPadding: contentPadding, |
| tileColor: tileColor, |
| selectedTileColor: selectedTileColor, |
| enableFeedback: enableFeedback, |
| horizontalTitleGap: horizontalTitleGap, |
| minVerticalPadding: minVerticalPadding, |
| minLeadingWidth: minLeadingWidth, |
| ), |
| child: child, |
| ); |
| } |
| |
| @override |
| bool updateShouldNotify(ListTileTheme oldWidget) => data != oldWidget.data; |
| } |