forked from firka/flutter
Reverts: flutter/flutter#155476 Initiated by: eyebrowsoffire Reason for reverting: The newly added tests are failing in postsubmit. See https://ci.chromium.org/ui/p/flutter/builders/prod/Windows%20framework_tests_libraries/19062/overview Original PR Author: QuncCccccc Reviewed By: {TahaTesser} This change reverts the following previous change: This PR is to make preparations to make `TabBarTheme` conform to Flutter's conventions for component themes: * Added a `TabBarThemeData` class which defines overrides for the defaults for `TabBar` properties. * Added 2 `TabBarTheme` constructor parameters: `TabBarThemeData? data` and `Widget? child`. This is now the preferred way to configure a `TabBarTheme`: ``` TabBarTheme( data: TabBarThemeData(labelColor: xxx, indicatorColor: xxx, ...), child: TabBar(...) ) ``` These two properties are made nullable to not break existing apps which has customized `ThemeData.tabBarTheme`. * Changed the type of component theme defaults from `TabBarTheme` to `TabBarThemeData`. TODO: * Fix internal failures. * Change the type of `ThemeData.tabBarTheme` from `TabBarTheme` to `TabBarThemeData`. This may cause breaking changes, a migration guide will be created. Addresses the "theme normalization" sub project within https://github.com/flutter/flutter/issues/91772
This commit is contained in:
@@ -12,7 +12,7 @@ class TabsTemplate extends TokenTemplate {
|
||||
|
||||
@override
|
||||
String generate() => '''
|
||||
class _${blockName}PrimaryDefaultsM3 extends TabBarThemeData {
|
||||
class _${blockName}PrimaryDefaultsM3 extends TabBarTheme {
|
||||
_${blockName}PrimaryDefaultsM3(this.context, this.isScrollable)
|
||||
: super(indicatorSize: TabBarIndicatorSize.label);
|
||||
|
||||
@@ -91,7 +91,7 @@ class _${blockName}PrimaryDefaultsM3 extends TabBarThemeData {
|
||||
static const EdgeInsetsGeometry iconMargin = EdgeInsets.only(bottom: 2);
|
||||
}
|
||||
|
||||
class _${blockName}SecondaryDefaultsM3 extends TabBarThemeData {
|
||||
class _${blockName}SecondaryDefaultsM3 extends TabBarTheme {
|
||||
_${blockName}SecondaryDefaultsM3(this.context, this.isScrollable)
|
||||
: super(indicatorSize: TabBarIndicatorSize.tab);
|
||||
|
||||
|
||||
@@ -12,305 +12,22 @@ import 'theme.dart';
|
||||
|
||||
/// Defines a theme for [TabBar] widgets.
|
||||
///
|
||||
/// Descendant widgets obtain the current [TabBarTheme] object using
|
||||
/// `TabBarTheme.of(context)`.
|
||||
/// A tab bar theme describes the color of the tab label and the size/shape of
|
||||
/// the [TabBar.indicator].
|
||||
///
|
||||
/// Descendant widgets obtain the current theme's [TabBarTheme] object using
|
||||
/// `TabBarTheme.of(context)`. Instances of [TabBarTheme] can be customized with
|
||||
/// [TabBarTheme.copyWith].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [TabBarThemeData], which describes the actual configuration of a switch
|
||||
/// theme.
|
||||
@immutable
|
||||
class TabBarTheme extends InheritedTheme with Diagnosticable {
|
||||
/// Creates a tab bar theme that can be used with [ThemeData.tabBarTheme].
|
||||
const TabBarTheme({
|
||||
super.key,
|
||||
Decoration? indicator,
|
||||
Color? indicatorColor,
|
||||
TabBarIndicatorSize? indicatorSize,
|
||||
Color? dividerColor,
|
||||
double? dividerHeight,
|
||||
Color? labelColor,
|
||||
EdgeInsetsGeometry? labelPadding,
|
||||
TextStyle? labelStyle,
|
||||
Color? unselectedLabelColor,
|
||||
TextStyle? unselectedLabelStyle,
|
||||
WidgetStateProperty<Color?>? overlayColor,
|
||||
InteractiveInkFeatureFactory? splashFactory,
|
||||
WidgetStateProperty<MouseCursor?>? mouseCursor,
|
||||
TabAlignment? tabAlignment,
|
||||
TextScaler? textScaler,
|
||||
TabIndicatorAnimation? indicatorAnimation,
|
||||
TabBarThemeData? data,
|
||||
Widget? child,
|
||||
}) : assert(
|
||||
data == null ||
|
||||
(indicator ?? indicatorColor ?? indicatorSize ?? dividerColor ?? dividerHeight
|
||||
?? labelColor ?? labelPadding ?? labelStyle ?? unselectedLabelColor ?? unselectedLabelStyle
|
||||
?? overlayColor ?? splashFactory ?? mouseCursor ?? tabAlignment ?? textScaler
|
||||
?? indicatorAnimation) == null),
|
||||
_indicator = indicator,
|
||||
_indicatorColor = indicatorColor,
|
||||
_indicatorSize = indicatorSize,
|
||||
_dividerColor = dividerColor,
|
||||
_dividerHeight = dividerHeight,
|
||||
_labelColor = labelColor,
|
||||
_labelPadding = labelPadding,
|
||||
_labelStyle = labelStyle,
|
||||
_unselectedLabelColor = unselectedLabelColor,
|
||||
_unselectedLabelStyle = unselectedLabelStyle,
|
||||
_overlayColor = overlayColor,
|
||||
_splashFactory = splashFactory,
|
||||
_mouseCursor = mouseCursor,
|
||||
_tabAlignment = tabAlignment,
|
||||
_textScaler = textScaler,
|
||||
_indicatorAnimation = indicatorAnimation,
|
||||
_data = data,
|
||||
super(child: child ?? const SizedBox());
|
||||
|
||||
final TabBarThemeData? _data;
|
||||
final Decoration? _indicator;
|
||||
final Color? _indicatorColor;
|
||||
final TabBarIndicatorSize? _indicatorSize;
|
||||
final Color? _dividerColor;
|
||||
final double? _dividerHeight;
|
||||
final Color? _labelColor;
|
||||
final EdgeInsetsGeometry? _labelPadding;
|
||||
final TextStyle? _labelStyle;
|
||||
final Color? _unselectedLabelColor;
|
||||
final TextStyle? _unselectedLabelStyle;
|
||||
final MaterialStateProperty<Color?>? _overlayColor;
|
||||
final InteractiveInkFeatureFactory? _splashFactory;
|
||||
final MaterialStateProperty<MouseCursor?>? _mouseCursor;
|
||||
final TabAlignment? _tabAlignment;
|
||||
final TextScaler? _textScaler;
|
||||
final TabIndicatorAnimation? _indicatorAnimation;
|
||||
|
||||
/// Overrides the default value for [TabBar.indicator].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.indicator] property in [data] instead.
|
||||
Decoration? get indicator => _data != null ? _data.indicator : _indicator;
|
||||
|
||||
/// Overrides the default value for [TabBar.indicatorColor].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.indicatorColor] property in [data] instead.
|
||||
Color? get indicatorColor => _data != null ? _data.indicatorColor : _indicatorColor;
|
||||
|
||||
/// Overrides the default value for [TabBar.indicatorSize].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.indicatorSize] property in [data] instead.
|
||||
TabBarIndicatorSize? get indicatorSize => _data != null ? _data.indicatorSize : _indicatorSize;
|
||||
|
||||
/// Overrides the default value for [TabBar.dividerColor].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.dividerColor] property in [data] instead.
|
||||
Color? get dividerColor => _data != null ? _data.dividerColor : _dividerColor;
|
||||
|
||||
/// Overrides the default value for [TabBar.dividerHeight].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.dividerHeight] property in [data] instead.
|
||||
double? get dividerHeight => _data != null ? _data.dividerHeight : _dividerHeight;
|
||||
|
||||
/// Overrides the default value for [TabBar.labelColor].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.labelColor] property in [data] instead.
|
||||
Color? get labelColor => _data != null ? _data.labelColor : _labelColor;
|
||||
|
||||
/// Overrides the default value for [TabBar.labelPadding].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.labelPadding] property in [data] instead.
|
||||
EdgeInsetsGeometry? get labelPadding => _data != null ? _data.labelPadding : _labelPadding;
|
||||
|
||||
/// Overrides the default value for [TabBar.labelStyle].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.labelStyle] property in [data] instead.
|
||||
TextStyle? get labelStyle => _data != null ? _data.labelStyle : _labelStyle;
|
||||
|
||||
/// Overrides the default value for [TabBar.unselectedLabelColor].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.unselectedLabelColor] property in [data] instead.
|
||||
Color? get unselectedLabelColor => _data != null ? _data.unselectedLabelColor : _unselectedLabelColor;
|
||||
|
||||
/// Overrides the default value for [TabBar.unselectedLabelStyle].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.unselectedLabelStyle] property in [data] instead.
|
||||
TextStyle? get unselectedLabelStyle => _data != null ? _data.unselectedLabelStyle : _unselectedLabelStyle;
|
||||
|
||||
/// Overrides the default value for [TabBar.overlayColor].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.overlayColor] property in [data] instead.
|
||||
MaterialStateProperty<Color?>? get overlayColor => _data != null ? _data.overlayColor : _overlayColor;
|
||||
|
||||
/// Overrides the default value for [TabBar.splashFactory].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.splashFactory] property in [data] instead.
|
||||
InteractiveInkFeatureFactory? get splashFactory => _data != null ? _data.splashFactory : _splashFactory;
|
||||
|
||||
/// Overrides the default value of [TabBar.mouseCursor].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.mouseCursor] property in [data] instead.
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor => _data != null ? _data.mouseCursor : _mouseCursor;
|
||||
|
||||
/// Overrides the default value for [TabBar.tabAlignment].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.tabAlignment] property in [data] instead.
|
||||
TabAlignment? get tabAlignment => _data != null ? _data.tabAlignment : _tabAlignment;
|
||||
|
||||
/// Overrides the default value for [TabBar.textScaler].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.textScaler] property in [data] instead.
|
||||
TextScaler? get textScaler => _data != null ? _data.textScaler : _textScaler;
|
||||
|
||||
/// Overrides the default value for [TabBar.indicatorAnimation].
|
||||
///
|
||||
/// This property is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.indicatorAnimation] property in [data] instead.
|
||||
TabIndicatorAnimation? get indicatorAnimation => _data != null ? _data.indicatorAnimation : _indicatorAnimation;
|
||||
|
||||
/// The properties used for all descendant [TabBar] widgets.
|
||||
TabBarThemeData get data => _data ?? TabBarThemeData(
|
||||
indicator: _indicator,
|
||||
indicatorColor: _indicatorColor,
|
||||
indicatorSize: _indicatorSize,
|
||||
dividerColor: _dividerColor,
|
||||
dividerHeight: _dividerHeight,
|
||||
labelColor: _labelColor,
|
||||
labelPadding: _labelPadding,
|
||||
labelStyle: _labelStyle,
|
||||
unselectedLabelColor: _unselectedLabelColor,
|
||||
unselectedLabelStyle: _unselectedLabelStyle,
|
||||
overlayColor: _overlayColor,
|
||||
splashFactory: _splashFactory,
|
||||
mouseCursor: _mouseCursor,
|
||||
tabAlignment: _tabAlignment,
|
||||
textScaler: _textScaler,
|
||||
indicatorAnimation: _indicatorAnimation,
|
||||
);
|
||||
|
||||
/// Creates a copy of this object but with the given fields replaced with the
|
||||
/// new values.
|
||||
///
|
||||
/// This method is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.copyWith] instead.
|
||||
TabBarTheme copyWith({
|
||||
Decoration? indicator,
|
||||
Color? indicatorColor,
|
||||
TabBarIndicatorSize? indicatorSize,
|
||||
Color? dividerColor,
|
||||
double? dividerHeight,
|
||||
Color? labelColor,
|
||||
EdgeInsetsGeometry? labelPadding,
|
||||
TextStyle? labelStyle,
|
||||
Color? unselectedLabelColor,
|
||||
TextStyle? unselectedLabelStyle,
|
||||
MaterialStateProperty<Color?>? overlayColor,
|
||||
InteractiveInkFeatureFactory? splashFactory,
|
||||
MaterialStateProperty<MouseCursor?>? mouseCursor,
|
||||
TabAlignment? tabAlignment,
|
||||
TextScaler? textScaler,
|
||||
TabIndicatorAnimation? indicatorAnimation,
|
||||
}) {
|
||||
return TabBarTheme(
|
||||
indicator: indicator ?? this.indicator,
|
||||
indicatorColor: indicatorColor ?? this.indicatorColor,
|
||||
indicatorSize: indicatorSize ?? this.indicatorSize,
|
||||
dividerColor: dividerColor ?? this.dividerColor,
|
||||
dividerHeight: dividerHeight ?? this.dividerHeight,
|
||||
labelColor: labelColor ?? this.labelColor,
|
||||
labelPadding: labelPadding ?? this.labelPadding,
|
||||
labelStyle: labelStyle ?? this.labelStyle,
|
||||
unselectedLabelColor: unselectedLabelColor ?? this.unselectedLabelColor,
|
||||
unselectedLabelStyle: unselectedLabelStyle ?? this.unselectedLabelStyle,
|
||||
overlayColor: overlayColor ?? this.overlayColor,
|
||||
splashFactory: splashFactory ?? this.splashFactory,
|
||||
mouseCursor: mouseCursor ?? this.mouseCursor,
|
||||
tabAlignment: tabAlignment ?? this.tabAlignment,
|
||||
textScaler: textScaler ?? this.textScaler,
|
||||
indicatorAnimation: indicatorAnimation ?? this.indicatorAnimation,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the closest [TabBarTheme] instance given the build context.
|
||||
static TabBarTheme of(BuildContext context) {
|
||||
final TabBarTheme? tabBarTheme = context.dependOnInheritedWidgetOfExactType<TabBarTheme>();
|
||||
return tabBarTheme ?? Theme.of(context).tabBarTheme;
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two tab bar themes.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
///
|
||||
/// This method is obsolete and will be deprecated in a future release:
|
||||
/// please use the [TabBarThemeData.lerp] instead.
|
||||
static TabBarTheme lerp(TabBarTheme a, TabBarTheme b, double t) {
|
||||
if (identical(a, b)) {
|
||||
return a;
|
||||
}
|
||||
return TabBarTheme(
|
||||
indicator: Decoration.lerp(a.indicator, b.indicator, t),
|
||||
indicatorColor: Color.lerp(a.indicatorColor, b.indicatorColor, t),
|
||||
indicatorSize: t < 0.5 ? a.indicatorSize : b.indicatorSize,
|
||||
dividerColor: Color.lerp(a.dividerColor, b.dividerColor, t),
|
||||
dividerHeight: t < 0.5 ? a.dividerHeight : b.dividerHeight,
|
||||
labelColor: Color.lerp(a.labelColor, b.labelColor, t),
|
||||
labelPadding: EdgeInsetsGeometry.lerp(a.labelPadding, b.labelPadding, t),
|
||||
labelStyle: TextStyle.lerp(a.labelStyle, b.labelStyle, t),
|
||||
unselectedLabelColor: Color.lerp(a.unselectedLabelColor, b.unselectedLabelColor, t),
|
||||
unselectedLabelStyle: TextStyle.lerp(a.unselectedLabelStyle, b.unselectedLabelStyle, t),
|
||||
overlayColor: MaterialStateProperty.lerp<Color?>(a.overlayColor, b.overlayColor, t, Color.lerp),
|
||||
splashFactory: t < 0.5 ? a.splashFactory : b.splashFactory,
|
||||
mouseCursor: t < 0.5 ? a.mouseCursor : b.mouseCursor,
|
||||
tabAlignment: t < 0.5 ? a.tabAlignment : b.tabAlignment,
|
||||
textScaler: t < 0.5 ? a.textScaler : b.textScaler,
|
||||
indicatorAnimation: t < 0.5 ? a.indicatorAnimation : b.indicatorAnimation,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(TabBarTheme oldWidget) => data != oldWidget.data;
|
||||
|
||||
@override
|
||||
Widget wrap(BuildContext context, Widget child) {
|
||||
return TabBarTheme(data: data, child: child);
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines default property values for descendant [TabBar] widgets.
|
||||
///
|
||||
/// Descendant widgets obtain the current [TabBarThemeData] object using
|
||||
/// `TabBarTheme.of(context).data`. Instances of [TabBarThemeData] can be
|
||||
/// customized with [TabBarThemeData.copyWith].
|
||||
///
|
||||
/// Typically a [TabBarThemeData] is specified as part of the overall [Theme]
|
||||
/// with [ThemeData.tabBarTheme].
|
||||
///
|
||||
/// All [TabBarThemeData] properties are `null` by default. When null, the [TabBar]
|
||||
/// will use the values from [ThemeData] if they exist, otherwise it will
|
||||
/// provide its own defaults. See the individual [TabBar] properties for details.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [TabBar], which displays a row of tabs.
|
||||
/// * [TabBar], a widget that displays a horizontal row of tabs.
|
||||
/// * [ThemeData], which describes the overall theme information for the
|
||||
/// application.
|
||||
@immutable
|
||||
class TabBarThemeData with Diagnosticable {
|
||||
class TabBarTheme with Diagnosticable {
|
||||
/// Creates a tab bar theme that can be used with [ThemeData.tabBarTheme].
|
||||
const TabBarThemeData({
|
||||
const TabBarTheme({
|
||||
this.indicator,
|
||||
this.indicatorColor,
|
||||
this.indicatorSize,
|
||||
@@ -391,7 +108,7 @@ class TabBarThemeData with Diagnosticable {
|
||||
|
||||
/// Creates a copy of this object but with the given fields replaced with the
|
||||
/// new values.
|
||||
TabBarThemeData copyWith({
|
||||
TabBarTheme copyWith({
|
||||
Decoration? indicator,
|
||||
Color? indicatorColor,
|
||||
TabBarIndicatorSize? indicatorSize,
|
||||
@@ -409,7 +126,7 @@ class TabBarThemeData with Diagnosticable {
|
||||
TextScaler? textScaler,
|
||||
TabIndicatorAnimation? indicatorAnimation,
|
||||
}) {
|
||||
return TabBarThemeData(
|
||||
return TabBarTheme(
|
||||
indicator: indicator ?? this.indicator,
|
||||
indicatorColor: indicatorColor ?? this.indicatorColor,
|
||||
indicatorSize: indicatorSize ?? this.indicatorSize,
|
||||
@@ -429,14 +146,19 @@ class TabBarThemeData with Diagnosticable {
|
||||
);
|
||||
}
|
||||
|
||||
/// The data from the closest [TabBarTheme] instance given the build context.
|
||||
static TabBarTheme of(BuildContext context) {
|
||||
return Theme.of(context).tabBarTheme;
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two tab bar themes.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
static TabBarThemeData lerp(TabBarThemeData a, TabBarThemeData b, double t) {
|
||||
static TabBarTheme lerp(TabBarTheme a, TabBarTheme b, double t) {
|
||||
if (identical(a, b)) {
|
||||
return a;
|
||||
}
|
||||
return TabBarThemeData(
|
||||
return TabBarTheme(
|
||||
indicator: Decoration.lerp(a.indicator, b.indicator, t),
|
||||
indicatorColor: Color.lerp(a.indicatorColor, b.indicatorColor, t),
|
||||
indicatorSize: t < 0.5 ? a.indicatorSize : b.indicatorSize,
|
||||
@@ -484,7 +206,7 @@ class TabBarThemeData with Diagnosticable {
|
||||
if (other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
return other is TabBarThemeData
|
||||
return other is TabBarTheme
|
||||
&& other.indicator == indicator
|
||||
&& other.indicatorColor == indicatorColor
|
||||
&& other.indicatorSize == indicatorSize
|
||||
@@ -502,25 +224,4 @@ class TabBarThemeData with Diagnosticable {
|
||||
&& other.textScaler == textScaler
|
||||
&& other.indicatorAnimation == indicatorAnimation;
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DiagnosticsProperty<Decoration?>('indicator', indicator, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<Color?>('indicatorColor', indicatorColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TabBarIndicatorSize?>('indicatorSize', indicatorSize, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<Color?>('dividerColor', dividerColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<double?>('dividerHeight', dividerHeight, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<Color?>('labelColor', labelColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<EdgeInsetsGeometry?>('labelPadding', labelPadding, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextStyle?>('labelStyle', labelStyle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<Color?>('unselectedLabelColor', unselectedLabelColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextStyle?>('unselectedLabelStyle', unselectedLabelStyle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>?>('overlayColor', overlayColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<InteractiveInkFeatureFactory?>('splashFactory', splashFactory, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<MouseCursor?>?>('mouseCursor', mouseCursor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TabAlignment?>('tabAlignment', tabAlignment, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextScaler?>('textScaler', textScaler, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TabIndicatorAnimation?>('indicatorAnimation', indicatorAnimation, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ enum TabAlignment {
|
||||
///
|
||||
/// See also:
|
||||
/// * [TabBar], which displays a row of tabs.
|
||||
/// * [TabBarThemeData], which can be used to configure the appearance of the tab
|
||||
/// * [TabBarTheme], which can be used to configure the appearance of the tab
|
||||
/// indicator.
|
||||
enum TabIndicatorAnimation {
|
||||
/// The tab indicator animates linearly.
|
||||
@@ -241,12 +241,12 @@ class _TabStyle extends AnimatedWidget {
|
||||
final bool isPrimary;
|
||||
final Color? labelColor;
|
||||
final Color? unselectedLabelColor;
|
||||
final TabBarThemeData defaults;
|
||||
final TabBarTheme defaults;
|
||||
final Widget child;
|
||||
|
||||
MaterialStateColor _resolveWithLabelColor(BuildContext context) {
|
||||
final ThemeData themeData = Theme.of(context);
|
||||
final TabBarThemeData tabBarTheme = TabBarTheme.of(context).data;
|
||||
final TabBarTheme tabBarTheme = TabBarTheme.of(context);
|
||||
final Animation<double> animation = listenable as Animation<double>;
|
||||
|
||||
// labelStyle.color (and tabBarTheme.labelStyle.color) is not considered
|
||||
@@ -285,7 +285,7 @@ class _TabStyle extends AnimatedWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final TabBarThemeData tabBarTheme = TabBarTheme.of(context).data;
|
||||
final TabBarTheme tabBarTheme = TabBarTheme.of(context);
|
||||
final Animation<double> animation = listenable as Animation<double>;
|
||||
|
||||
final Set<MaterialState> states = isSelected
|
||||
@@ -790,7 +790,7 @@ class _TabBarScrollController extends ScrollController {
|
||||
///
|
||||
/// Requires one of its ancestors to be a [Material] widget.
|
||||
///
|
||||
/// Uses values from [TabBarThemeData] if it is set in the current context.
|
||||
/// Uses values from [TabBarTheme] if it is set in the current context.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This sample shows the implementation of [TabBar] and [TabBarView] using a [DefaultTabController].
|
||||
@@ -954,7 +954,7 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
/// If this parameter is null, then the value of the Theme's indicatorColor
|
||||
/// property is used.
|
||||
///
|
||||
/// If [indicator] is specified or provided from [TabBarThemeData],
|
||||
/// If [indicator] is specified or provided from [TabBarTheme],
|
||||
/// this property is ignored.
|
||||
final Color? indicatorColor;
|
||||
|
||||
@@ -971,7 +971,7 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is false, the default value is 2.0.
|
||||
///
|
||||
/// If [indicator] is specified or provided from [TabBarThemeData],
|
||||
/// If [indicator] is specified or provided from [TabBarTheme],
|
||||
/// this property is ignored.
|
||||
final double indicatorWeight;
|
||||
|
||||
@@ -986,7 +986,7 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
|
||||
/// Defines the appearance of the selected tab indicator.
|
||||
///
|
||||
/// If [indicator] is specified or provided from [TabBarThemeData],
|
||||
/// If [indicator] is specified or provided from [TabBarTheme],
|
||||
/// the [indicatorColor] and [indicatorWeight] properties are ignored.
|
||||
///
|
||||
/// The default, underline-style, selected tab indicator can be defined with
|
||||
@@ -1030,7 +1030,7 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
///
|
||||
/// If the [dividerColor] is [Colors.transparent], then the divider will not be drawn.
|
||||
///
|
||||
/// If null and [ThemeData.useMaterial3] is false, [TabBarThemeData.dividerColor]
|
||||
/// If null and [ThemeData.useMaterial3] is false, [TabBarTheme.dividerColor]
|
||||
/// color is used. If that is null and [ThemeData.useMaterial3] is true,
|
||||
/// [ColorScheme.outlineVariant] will be used, otherwise divider will not be drawn.
|
||||
final Color? dividerColor;
|
||||
@@ -1039,26 +1039,26 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
///
|
||||
/// If the [dividerHeight] is zero or negative, then the divider will not be drawn.
|
||||
///
|
||||
/// If null and [ThemeData.useMaterial3] is true, [TabBarThemeData.dividerHeight] is used.
|
||||
/// If null and [ThemeData.useMaterial3] is true, [TabBarTheme.dividerHeight] is used.
|
||||
/// If that is also null and [ThemeData.useMaterial3] is true, 1.0 will be used.
|
||||
/// Otherwise divider will not be drawn.
|
||||
final double? dividerHeight;
|
||||
|
||||
/// The color of selected tab labels.
|
||||
///
|
||||
/// If null, then [TabBarThemeData.labelColor] is used. If that is also null and
|
||||
/// If null, then [TabBarTheme.labelColor] is used. If that is also null and
|
||||
/// [ThemeData.useMaterial3] is true, [ColorScheme.primary] will be used,
|
||||
/// otherwise the color of the [ThemeData.primaryTextTheme]'s
|
||||
/// [TextTheme.bodyLarge] text color is used.
|
||||
///
|
||||
/// If [labelColor] (or, if null, [TabBarThemeData.labelColor]) is a
|
||||
/// If [labelColor] (or, if null, [TabBarTheme.labelColor]) is a
|
||||
/// [WidgetStateColor], then the effective tab color will depend on the
|
||||
/// [WidgetState.selected] state, i.e. if the [Tab] is selected or not,
|
||||
/// ignoring [unselectedLabelColor] even if it's non-null.
|
||||
///
|
||||
/// When this color or the [TabBarThemeData.labelColor] is specified, it overrides
|
||||
/// When this color or the [TabBarTheme.labelColor] is specified, it overrides
|
||||
/// the [TextStyle.color] specified for the [labelStyle] or the
|
||||
/// [TabBarThemeData.labelStyle].
|
||||
/// [TabBarTheme.labelStyle].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
@@ -1067,19 +1067,19 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
|
||||
/// The color of unselected tab labels.
|
||||
///
|
||||
/// If [labelColor] (or, if null, [TabBarThemeData.labelColor]) is a
|
||||
/// If [labelColor] (or, if null, [TabBarTheme.labelColor]) is a
|
||||
/// [WidgetStateColor], then the unselected tabs are rendered with
|
||||
/// that [WidgetStateColor]'s resolved color for unselected state, even if
|
||||
/// [unselectedLabelColor] is non-null.
|
||||
///
|
||||
/// If null, then [TabBarThemeData.unselectedLabelColor] is used. If that is also
|
||||
/// If null, then [TabBarTheme.unselectedLabelColor] is used. If that is also
|
||||
/// null and [ThemeData.useMaterial3] is true, [ColorScheme.onSurfaceVariant]
|
||||
/// will be used, otherwise unselected tab labels are rendered with
|
||||
/// [labelColor] at 70% opacity.
|
||||
///
|
||||
/// When this color or the [TabBarThemeData.unselectedLabelColor] is specified, it
|
||||
/// When this color or the [TabBarTheme.unselectedLabelColor] is specified, it
|
||||
/// overrides the [TextStyle.color] specified for the [unselectedLabelStyle]
|
||||
/// or the [TabBarThemeData.unselectedLabelStyle].
|
||||
/// or the [TabBarTheme.unselectedLabelStyle].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
@@ -1088,14 +1088,14 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
|
||||
/// The text style of the selected tab labels.
|
||||
///
|
||||
/// The color specified in [labelStyle] and [TabBarThemeData.labelStyle] is used
|
||||
/// to style the label when [labelColor] or [TabBarThemeData.labelColor] are not
|
||||
/// The color specified in [labelStyle] and [TabBarTheme.labelStyle] is used
|
||||
/// to style the label when [labelColor] or [TabBarTheme.labelColor] are not
|
||||
/// specified.
|
||||
///
|
||||
/// If [unselectedLabelStyle] is null, then this text style will be used for
|
||||
/// both selected and unselected label styles.
|
||||
///
|
||||
/// If this property is null, then [TabBarThemeData.labelStyle] will be used.
|
||||
/// If this property is null, then [TabBarTheme.labelStyle] will be used.
|
||||
///
|
||||
/// If that is also null and [ThemeData.useMaterial3] is true, [TextTheme.titleSmall]
|
||||
/// will be used, otherwise the text style of the [ThemeData.primaryTextTheme]'s
|
||||
@@ -1104,11 +1104,11 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
|
||||
/// The text style of the unselected tab labels.
|
||||
///
|
||||
/// The color specified in [unselectedLabelStyle] and [TabBarThemeData.unselectedLabelStyle]
|
||||
/// is used to style the label when [unselectedLabelColor] or [TabBarThemeData.unselectedLabelColor]
|
||||
/// The color specified in [unselectedLabelStyle] and [TabBarTheme.unselectedLabelStyle]
|
||||
/// is used to style the label when [unselectedLabelColor] or [TabBarTheme.unselectedLabelColor]
|
||||
/// are not specified.
|
||||
///
|
||||
/// If this property is null, then [TabBarThemeData.unselectedLabelStyle] will be used.
|
||||
/// If this property is null, then [TabBarTheme.unselectedLabelStyle] will be used.
|
||||
///
|
||||
/// If that is also null and [ThemeData.useMaterial3] is true, [TextTheme.titleSmall]
|
||||
/// will be used, otherwise then the [labelStyle] value is used. If [labelStyle] is null,
|
||||
@@ -1159,7 +1159,7 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
/// * [WidgetState.selected].
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// If null, then the value of [TabBarThemeData.mouseCursor] is used. If
|
||||
/// If null, then the value of [TabBarTheme.mouseCursor] is used. If
|
||||
/// that is also null, then [WidgetStateMouseCursor.clickable] is used.
|
||||
///
|
||||
/// See also:
|
||||
@@ -1244,20 +1244,20 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
/// If [TabBar.isScrollable] is true, only [TabAlignment.start], [TabAlignment.startOffset],
|
||||
/// and [TabAlignment.center] are supported. Otherwise an exception is thrown.
|
||||
///
|
||||
/// If this is null, then the value of [TabBarThemeData.tabAlignment] is used.
|
||||
/// If this is null, then the value of [TabBarTheme.tabAlignment] is used.
|
||||
///
|
||||
/// If [TabBarThemeData.tabAlignment] is null and [ThemeData.useMaterial3] is true,
|
||||
/// If [TabBarTheme.tabAlignment] is null and [ThemeData.useMaterial3] is true,
|
||||
/// then [TabAlignment.startOffset] is used if [isScrollable] is true,
|
||||
/// otherwise [TabAlignment.fill] is used.
|
||||
///
|
||||
/// If [TabBarThemeData.tabAlignment] is null and [ThemeData.useMaterial3] is false,
|
||||
/// If [TabBarTheme.tabAlignment] is null and [ThemeData.useMaterial3] is false,
|
||||
/// then [TabAlignment.center] is used if [isScrollable] is true,
|
||||
/// otherwise [TabAlignment.fill] is used.
|
||||
final TabAlignment? tabAlignment;
|
||||
|
||||
/// Specifies the text scaling behavior for the [Tab] label.
|
||||
///
|
||||
/// If this is null, then the value of [TabBarThemeData.textScaler] is used. If that is
|
||||
/// If this is null, then the value of [TabBarTheme.textScaler] is used. If that is
|
||||
/// also null, then the text scaling behavior is determined by the [MediaQueryData.textScaler]
|
||||
/// from the ambient [MediaQuery], or 1.0 if there is no [MediaQuery] in scope.
|
||||
///
|
||||
@@ -1267,7 +1267,7 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
|
||||
/// Specifies the animation behavior of the tab indicator.
|
||||
///
|
||||
/// If this is null, then the value of [TabBarThemeData.indicatorAnimation] is used.
|
||||
/// If this is null, then the value of [TabBarTheme.indicatorAnimation] is used.
|
||||
/// If that is also null, then the tab indicator will animate linearly if the
|
||||
/// [indicatorSize] is [TabBarIndicatorSize.tab], otherwise it will animate
|
||||
/// with an elastic effect if the [indicatorSize] is [TabBarIndicatorSize.label].
|
||||
@@ -1343,7 +1343,7 @@ class _TabBarState extends State<TabBar> {
|
||||
_labelPaddings = List<EdgeInsetsGeometry>.filled(widget.tabs.length, EdgeInsets.zero, growable: true);
|
||||
}
|
||||
|
||||
TabBarThemeData get _defaults {
|
||||
TabBarTheme get _defaults {
|
||||
if (Theme.of(context).useMaterial3) {
|
||||
return widget._isPrimary
|
||||
? _TabsPrimaryDefaultsM3(context, widget.isScrollable)
|
||||
@@ -1355,7 +1355,7 @@ class _TabBarState extends State<TabBar> {
|
||||
|
||||
Decoration _getIndicator(TabBarIndicatorSize indicatorSize) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final TabBarThemeData tabBarTheme = TabBarTheme.of(context).data;
|
||||
final TabBarTheme tabBarTheme = TabBarTheme.of(context);
|
||||
|
||||
if (widget.indicator != null) {
|
||||
return widget.indicator!;
|
||||
@@ -1626,7 +1626,7 @@ class _TabBarState extends State<TabBar> {
|
||||
widget.onTap?.call(index);
|
||||
}
|
||||
|
||||
Widget _buildStyledTab(Widget child, bool isSelected, Animation<double> animation, TabBarThemeData defaults) {
|
||||
Widget _buildStyledTab(Widget child, bool isSelected, Animation<double> animation, TabBarTheme defaults) {
|
||||
return _TabStyle(
|
||||
animation: animation,
|
||||
isSelected: isSelected,
|
||||
@@ -1687,7 +1687,7 @@ class _TabBarState extends State<TabBar> {
|
||||
assert(debugCheckHasMaterialLocalizations(context));
|
||||
assert(_debugScheduleCheckHasValidTabsCount());
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final TabBarThemeData tabBarTheme = TabBarTheme.of(context).data;
|
||||
final TabBarTheme tabBarTheme = TabBarTheme.of(context);
|
||||
final TabAlignment effectiveTabAlignment = widget.tabAlignment ?? tabBarTheme.tabAlignment ?? _defaults.tabAlignment!;
|
||||
assert(_debugTabAlignmentIsValid(effectiveTabAlignment));
|
||||
|
||||
@@ -1861,7 +1861,7 @@ class _TabBarState extends State<TabBar> {
|
||||
tabBar = CustomPaint(
|
||||
painter: _DividerPainter(
|
||||
dividerColor: dividerColor,
|
||||
dividerHeight: dividerHeight,
|
||||
dividerHeight: widget.dividerHeight ?? tabBarTheme.dividerHeight ?? _defaults.dividerHeight!,
|
||||
),
|
||||
child: tabBar,
|
||||
);
|
||||
@@ -2430,7 +2430,7 @@ class _TabPageSelectorState extends State<TabPageSelector> {
|
||||
}
|
||||
|
||||
// Hand coded defaults based on Material Design 2.
|
||||
class _TabsDefaultsM2 extends TabBarThemeData {
|
||||
class _TabsDefaultsM2 extends TabBarTheme {
|
||||
const _TabsDefaultsM2(this.context, this.isScrollable)
|
||||
: super(indicatorSize: TabBarIndicatorSize.tab);
|
||||
|
||||
@@ -2465,7 +2465,7 @@ class _TabsDefaultsM2 extends TabBarThemeData {
|
||||
// Design token database by the script:
|
||||
// dev/tools/gen_defaults/bin/gen_defaults.dart.
|
||||
|
||||
class _TabsPrimaryDefaultsM3 extends TabBarThemeData {
|
||||
class _TabsPrimaryDefaultsM3 extends TabBarTheme {
|
||||
_TabsPrimaryDefaultsM3(this.context, this.isScrollable)
|
||||
: super(indicatorSize: TabBarIndicatorSize.label);
|
||||
|
||||
@@ -2544,7 +2544,7 @@ class _TabsPrimaryDefaultsM3 extends TabBarThemeData {
|
||||
static const EdgeInsetsGeometry iconMargin = EdgeInsets.only(bottom: 2);
|
||||
}
|
||||
|
||||
class _TabsSecondaryDefaultsM3 extends TabBarThemeData {
|
||||
class _TabsSecondaryDefaultsM3 extends TabBarTheme {
|
||||
_TabsSecondaryDefaultsM3(this.context, this.isScrollable)
|
||||
: super(indicatorSize: TabBarIndicatorSize.tab);
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ final List<SizedBox> _sizedTabs = <SizedBox>[
|
||||
];
|
||||
|
||||
Widget buildTabBar({
|
||||
TabBarThemeData? localTabBarTheme,
|
||||
TabBarTheme? tabBarTheme,
|
||||
bool secondaryTabBar = false,
|
||||
List<Widget> tabs = _tabs,
|
||||
@@ -48,30 +47,31 @@ Widget buildTabBar({
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
Widget tabBar = secondaryTabBar
|
||||
? TabBar.secondary(
|
||||
tabs: tabs,
|
||||
isScrollable: isScrollable,
|
||||
controller: controller,
|
||||
) : TabBar(
|
||||
tabs: tabs,
|
||||
isScrollable: isScrollable,
|
||||
controller: controller,
|
||||
);
|
||||
|
||||
if (localTabBarTheme != null) {
|
||||
tabBar = TabBarTheme(
|
||||
data: localTabBarTheme,
|
||||
child: tabBar,
|
||||
if (secondaryTabBar) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(tabBarTheme: tabBarTheme, useMaterial3: useMaterial3),
|
||||
home: Scaffold(
|
||||
body: RepaintBoundary(
|
||||
key: _painterKey,
|
||||
child: TabBar.secondary(
|
||||
tabs: tabs,
|
||||
isScrollable: isScrollable,
|
||||
controller: controller,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return MaterialApp(
|
||||
theme: ThemeData(tabBarTheme: tabBarTheme, useMaterial3: useMaterial3),
|
||||
home: Scaffold(
|
||||
body: RepaintBoundary(
|
||||
key: _painterKey,
|
||||
child: tabBar,
|
||||
child: TabBar(
|
||||
tabs: tabs,
|
||||
isScrollable: isScrollable,
|
||||
controller: controller,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -89,122 +89,31 @@ RenderParagraph _getText(WidgetTester tester, String text) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('TabBarThemeData copyWith, ==, hashCode, defaults', () {
|
||||
expect(const TabBarThemeData(), const TabBarThemeData().copyWith());
|
||||
expect(const TabBarThemeData().hashCode, const TabBarThemeData().copyWith().hashCode);
|
||||
test('TabBarTheme copyWith, ==, hashCode, defaults', () {
|
||||
expect(const TabBarTheme(), const TabBarTheme().copyWith());
|
||||
expect(const TabBarTheme().hashCode, const TabBarTheme().copyWith().hashCode);
|
||||
|
||||
expect(const TabBarThemeData().indicator, null);
|
||||
expect(const TabBarThemeData().indicatorColor, null);
|
||||
expect(const TabBarThemeData().indicatorSize, null);
|
||||
expect(const TabBarThemeData().dividerColor, null);
|
||||
expect(const TabBarThemeData().dividerHeight, null);
|
||||
expect(const TabBarThemeData().labelColor, null);
|
||||
expect(const TabBarThemeData().labelPadding, null);
|
||||
expect(const TabBarThemeData().labelStyle, null);
|
||||
expect(const TabBarThemeData().unselectedLabelColor, null);
|
||||
expect(const TabBarThemeData().unselectedLabelStyle, null);
|
||||
expect(const TabBarThemeData().overlayColor, null);
|
||||
expect(const TabBarThemeData().splashFactory, null);
|
||||
expect(const TabBarThemeData().mouseCursor, null);
|
||||
expect(const TabBarThemeData().tabAlignment, null);
|
||||
expect(const TabBarThemeData().textScaler, null);
|
||||
expect(const TabBarThemeData().indicatorAnimation, null);
|
||||
expect(const TabBarTheme().indicator, null);
|
||||
expect(const TabBarTheme().indicatorColor, null);
|
||||
expect(const TabBarTheme().indicatorSize, null);
|
||||
expect(const TabBarTheme().dividerColor, null);
|
||||
expect(const TabBarTheme().dividerHeight, null);
|
||||
expect(const TabBarTheme().labelColor, null);
|
||||
expect(const TabBarTheme().labelPadding, null);
|
||||
expect(const TabBarTheme().labelStyle, null);
|
||||
expect(const TabBarTheme().unselectedLabelColor, null);
|
||||
expect(const TabBarTheme().unselectedLabelStyle, null);
|
||||
expect(const TabBarTheme().overlayColor, null);
|
||||
expect(const TabBarTheme().splashFactory, null);
|
||||
expect(const TabBarTheme().mouseCursor, null);
|
||||
expect(const TabBarTheme().tabAlignment, null);
|
||||
expect(const TabBarTheme().textScaler, null);
|
||||
expect(const TabBarTheme().indicatorAnimation, null);
|
||||
});
|
||||
|
||||
test('TabBarThemeData lerp special cases', () {
|
||||
const TabBarThemeData theme = TabBarThemeData();
|
||||
expect(identical(TabBarThemeData.lerp(theme, theme, 0.5), theme), true);
|
||||
});
|
||||
|
||||
testWidgets('Default TabBarThemeData debugFillProperties', (WidgetTester tester) async {
|
||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||
const TabBarThemeData().debugFillProperties(builder);
|
||||
|
||||
final List<String> description = builder.properties
|
||||
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
|
||||
.map((DiagnosticsNode node) => node.toString())
|
||||
.toList();
|
||||
|
||||
expect(description, <String>[]);
|
||||
});
|
||||
|
||||
testWidgets('TabBarThemeData implements debugFillProperties', (WidgetTester tester) async {
|
||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||
const TabBarThemeData(
|
||||
indicator: BoxDecoration(color: Color(0xFF00FF00)),
|
||||
indicatorColor: Colors.red,
|
||||
indicatorSize: TabBarIndicatorSize.label,
|
||||
dividerColor: Color(0xff000001),
|
||||
dividerHeight: 20.5,
|
||||
labelColor: Color(0xff000002),
|
||||
labelPadding: EdgeInsets.all(20.0),
|
||||
labelStyle: TextStyle(color: Colors.amber),
|
||||
unselectedLabelColor: Color(0xff654321),
|
||||
unselectedLabelStyle: TextStyle(color: Colors.blue),
|
||||
overlayColor: WidgetStatePropertyAll<Color>(Colors.yellow),
|
||||
mouseCursor: WidgetStatePropertyAll<MouseCursor>(SystemMouseCursors.contextMenu),
|
||||
tabAlignment: TabAlignment.center,
|
||||
textScaler: TextScaler.noScaling,
|
||||
indicatorAnimation: TabIndicatorAnimation.elastic,
|
||||
).debugFillProperties(builder);
|
||||
final List<String> description = builder.properties
|
||||
.where((DiagnosticsNode n) => !n.isFiltered(DiagnosticLevel.info))
|
||||
.map((DiagnosticsNode n) => n.toString()).toList();
|
||||
expect(description, <String>[
|
||||
'indicator: BoxDecoration(color: Color(0xff00ff00))',
|
||||
'indicatorColor: MaterialColor(primary value: Color(0xfff44336))',
|
||||
'indicatorSize: TabBarIndicatorSize.label',
|
||||
'dividerColor: Color(0xff000001)',
|
||||
'dividerHeight: 20.5',
|
||||
'labelColor: Color(0xff000002)',
|
||||
'labelPadding: EdgeInsets.all(20.0)',
|
||||
'labelStyle: TextStyle(inherit: true, color: MaterialColor(primary value: Color(0xffffc107)))',
|
||||
'unselectedLabelColor: Color(0xff654321)',
|
||||
'unselectedLabelStyle: TextStyle(inherit: true, color: MaterialColor(primary value: Color(0xff2196f3)))',
|
||||
'overlayColor: WidgetStatePropertyAll(MaterialColor(primary value: Color(0xffffeb3b)))',
|
||||
'mouseCursor: WidgetStatePropertyAll(SystemMouseCursor(contextMenu))',
|
||||
'tabAlignment: TabAlignment.center',
|
||||
'textScaler: no scaling',
|
||||
'indicatorAnimation: TabIndicatorAnimation.elastic',
|
||||
]);
|
||||
});
|
||||
|
||||
testWidgets('Local TabBarTheme overrides defaults', (WidgetTester tester) async {
|
||||
const Color indicatorColor = Colors.green;
|
||||
const Color dividerColor = Color(0xff000001);
|
||||
const double dividerHeight = 20.5;
|
||||
const Color labelColor = Color(0xff000002);
|
||||
const TextStyle labelStyle = TextStyle(fontSize: 32.0);
|
||||
const Color unselectedLabelColor = Color(0xff654321);
|
||||
const TextStyle unselectedLabelStyle = TextStyle(fontWeight: FontWeight.bold);
|
||||
|
||||
const TabBarThemeData tabBarTheme = TabBarThemeData(
|
||||
indicatorColor: indicatorColor,
|
||||
dividerColor: dividerColor,
|
||||
dividerHeight: dividerHeight,
|
||||
labelColor: labelColor,
|
||||
labelStyle: labelStyle,
|
||||
unselectedLabelColor: unselectedLabelColor,
|
||||
unselectedLabelStyle: unselectedLabelStyle,
|
||||
);
|
||||
|
||||
// Test default label color and label styles.
|
||||
await tester.pumpWidget(buildTabBar(useMaterial3: true, localTabBarTheme: tabBarTheme));
|
||||
|
||||
final RenderParagraph selectedLabel = _getText(tester, _tab1Text);
|
||||
expect(selectedLabel.text.style!.color, labelColor);
|
||||
expect(selectedLabel.text.style!.fontSize, 32.0);
|
||||
final RenderParagraph unselectedLabel = _getText(tester, _tab2Text);
|
||||
expect(unselectedLabel.text.style!.color, unselectedLabelColor);
|
||||
expect(unselectedLabel.text.style!.fontWeight, FontWeight.bold);
|
||||
|
||||
final RenderBox tabBarBox = tester.firstRenderObject<RenderBox>(find.byType(TabBar));
|
||||
expect(
|
||||
tabBarBox,
|
||||
paints
|
||||
..line(color: dividerColor, strokeWidth: dividerHeight)
|
||||
..rrect(color: indicatorColor)
|
||||
);
|
||||
test('TabBarTheme lerp special cases', () {
|
||||
const TabBarTheme theme = TabBarTheme();
|
||||
expect(identical(TabBarTheme.lerp(theme, theme, 0.5), theme), true);
|
||||
});
|
||||
|
||||
testWidgets('Tab bar defaults (primary)', (WidgetTester tester) async {
|
||||
|
||||
Reference in New Issue
Block a user