blob: 7e4a8161a3f2c6d066574b7dc970e476081bfb58 [file] [log] [blame]
// 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 'navigation_drawer.dart';
import 'theme.dart';
// Examples can assume:
// late BuildContext context;
/// Defines default property values for descendant [NavigationDrawer]
/// widgets.
///
/// Descendant widgets obtain the current [NavigationDrawerThemeData] object
/// using `NavigationDrawerTheme.of(context)`. Instances of
/// [NavigationDrawerThemeData] can be customized with
/// [NavigationDrawerThemeData.copyWith].
///
/// Typically a [NavigationDrawerThemeData] is specified as part of the
/// overall [Theme] with [ThemeData.navigationDrawerTheme]. Alternatively, a
/// [NavigationDrawerTheme] inherited widget can be used to theme [NavigationDrawer]s
/// in a subtree of widgets.
///
/// All [NavigationDrawerThemeData] properties are `null` by default.
/// When null, the [NavigationDrawer] will provide its own defaults based on the
/// overall [Theme]'s textTheme and colorScheme. See the individual
/// [NavigationDrawer] properties for details.
///
/// See also:
///
/// * [ThemeData], which describes the overall theme information for the
/// application.
@immutable
class NavigationDrawerThemeData with Diagnosticable {
/// Creates a theme that can be used for [ThemeData.navigationDrawerTheme] and
/// [NavigationDrawerTheme].
const NavigationDrawerThemeData({
this.tileHeight,
this.backgroundColor,
this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.indicatorColor,
this.indicatorShape,
this.indicatorSize,
this.labelTextStyle,
this.iconTheme,
});
/// Overrides the default height of [NavigationDrawerDestination].
final double? tileHeight;
/// Overrides the default value of [NavigationDrawer.backgroundColor].
final Color? backgroundColor;
/// Overrides the default value of [NavigationDrawer.elevation].
final double? elevation;
/// Overrides the default value of [NavigationDrawer.shadowColor].
final Color? shadowColor;
/// Overrides the default value of [NavigationDrawer.surfaceTintColor].
final Color? surfaceTintColor;
/// Overrides the default value of [NavigationDrawer]'s selection indicator.
final Color? indicatorColor;
/// Overrides the default shape of the [NavigationDrawer]'s selection indicator.
final ShapeBorder? indicatorShape;
/// Overrides the default size of the [NavigationDrawer]'s selection indicator.
final Size? indicatorSize;
/// The style to merge with the default text style for
/// [NavigationDestination] labels.
///
/// You can use this to specify a different style when the label is selected.
final MaterialStateProperty<TextStyle?>? labelTextStyle;
/// The theme to merge with the default icon theme for
/// [NavigationDestination] icons.
///
/// You can use this to specify a different icon theme when the icon is
/// selected.
final MaterialStateProperty<IconThemeData?>? iconTheme;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
NavigationDrawerThemeData copyWith({
double? tileHeight,
Color? backgroundColor,
double? elevation,
Color? shadowColor,
Color? surfaceTintColor,
Color? indicatorColor,
ShapeBorder? indicatorShape,
Size? indicatorSize,
MaterialStateProperty<TextStyle?>? labelTextStyle,
MaterialStateProperty<IconThemeData?>? iconTheme,
}) {
return NavigationDrawerThemeData(
tileHeight: tileHeight ?? this.tileHeight,
backgroundColor: backgroundColor ?? this.backgroundColor,
elevation: elevation ?? this.elevation,
shadowColor: shadowColor ?? this.shadowColor,
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
indicatorColor: indicatorColor ?? this.indicatorColor,
indicatorShape: indicatorShape ?? this.indicatorShape,
indicatorSize: indicatorSize ?? this.indicatorSize,
labelTextStyle: labelTextStyle ?? this.labelTextStyle,
iconTheme: iconTheme ?? this.iconTheme,
);
}
/// Linearly interpolate between two navigation rail themes.
///
/// If both arguments are null then null is returned.
///
/// {@macro dart.ui.shadow.lerp}
static NavigationDrawerThemeData? lerp(
NavigationDrawerThemeData? a, NavigationDrawerThemeData? b, double t) {
assert(t != null);
if (a == null && b == null) {
return null;
}
return NavigationDrawerThemeData(
tileHeight: lerpDouble(a?.tileHeight, b?.tileHeight, t),
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t),
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
indicatorColor: Color.lerp(a?.indicatorColor, b?.indicatorColor, t),
indicatorShape: ShapeBorder.lerp(a?.indicatorShape, b?.indicatorShape, t),
indicatorSize: Size.lerp(a?.indicatorSize, a?.indicatorSize, t),
labelTextStyle: MaterialStateProperty.lerp<TextStyle?>(
a?.labelTextStyle, b?.labelTextStyle, t, TextStyle.lerp),
iconTheme: MaterialStateProperty.lerp<IconThemeData?>(
a?.iconTheme, b?.iconTheme, t, IconThemeData.lerp),
);
}
@override
int get hashCode => Object.hash(
tileHeight,
backgroundColor,
elevation,
shadowColor,
surfaceTintColor,
indicatorColor,
indicatorShape,
indicatorSize,
labelTextStyle,
iconTheme,
);
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
return other is NavigationDrawerThemeData &&
other.tileHeight == tileHeight &&
other.backgroundColor == backgroundColor &&
other.elevation == elevation &&
other.shadowColor == shadowColor &&
other.surfaceTintColor == surfaceTintColor &&
other.indicatorColor == indicatorColor &&
other.indicatorShape == indicatorShape &&
other.indicatorSize == indicatorSize &&
other.labelTextStyle == labelTextStyle &&
other.iconTheme == iconTheme;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
.add(DoubleProperty('tileHeight', tileHeight, defaultValue: null));
properties.add(
ColorProperty('backgroundColor', backgroundColor, defaultValue: null));
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor,
defaultValue: null));
properties.add(
ColorProperty('indicatorColor', indicatorColor, defaultValue: null));
properties.add(DiagnosticsProperty<ShapeBorder>(
'indicatorShape', indicatorShape,
defaultValue: null));
properties.add(DiagnosticsProperty<Size>('indicatorSize', indicatorSize,
defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<TextStyle?>>(
'labelTextStyle', labelTextStyle,
defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<IconThemeData?>>(
'iconTheme', iconTheme,
defaultValue: null));
}
}
/// An inherited widget that defines visual properties for [NavigationDrawer]s and
/// [NavigationDestination]s in this widget's subtree.
///
/// Values specified here are used for [NavigationDrawer] properties that are not
/// given an explicit non-null value.
///
/// See also:
///
/// * [ThemeData.navigationDrawerTheme], which describes the
/// [NavigationDrawerThemeData] in the overall theme for the application.
class NavigationDrawerTheme extends InheritedTheme {
/// Creates a navigation rail theme that controls the
/// [NavigationDrawerThemeData] properties for a [NavigationDrawer].
///
/// The data argument must not be null.
const NavigationDrawerTheme({
super.key,
required this.data,
required super.child,
}) : assert(data != null);
/// Specifies the background color, label text style, icon theme, and label
/// type values for descendant [NavigationDrawer] widgets.
final NavigationDrawerThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [NavigationDrawerTheme] widget, then
/// [ThemeData.navigationDrawerTheme] is used.
static NavigationDrawerThemeData of(BuildContext context) {
final NavigationDrawerTheme? navigationDrawerTheme =
context.dependOnInheritedWidgetOfExactType<NavigationDrawerTheme>();
return navigationDrawerTheme?.data ??
Theme.of(context).navigationDrawerTheme;
}
@override
Widget wrap(BuildContext context, Widget child) {
return NavigationDrawerTheme(data: data, child: child);
}
@override
bool updateShouldNotify(NavigationDrawerTheme oldWidget) =>
data != oldWidget.data;
}