Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
5a600456
Unverified
Commit
5a600456
authored
Nov 10, 2022
by
Hans Muller
Committed by
GitHub
Nov 10, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reland: Adds support for the Material Badge widget, BadgeTheme, BadgeThemeData (#114560) (#115002)
Requires G3Fix cl/486997831
parent
19b351b0
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
796 additions
and
0 deletions
+796
-0
gen_defaults.dart
dev/tools/gen_defaults/bin/gen_defaults.dart
+4
-0
badge_template.dart
dev/tools/gen_defaults/lib/badge_template.dart
+36
-0
material.dart
packages/flutter/lib/material.dart
+2
-0
badge.dart
packages/flutter/lib/src/material/badge.dart
+190
-0
badge_theme.dart
packages/flutter/lib/src/material/badge_theme.dart
+183
-0
theme_data.dart
packages/flutter/lib/src/material/theme_data.dart
+15
-0
badge_test.dart
packages/flutter/test/material/badge_test.dart
+206
-0
badge_theme_test.dart
packages/flutter/test/material/badge_theme_test.dart
+155
-0
theme_data_test.dart
packages/flutter/test/material/theme_data_test.dart
+5
-0
No files found.
dev/tools/gen_defaults/bin/gen_defaults.dart
View file @
5a600456
...
...
@@ -19,6 +19,7 @@ import 'dart:io';
import
'package:gen_defaults/action_chip_template.dart'
;
import
'package:gen_defaults/app_bar_template.dart'
;
import
'package:gen_defaults/badge_template.dart'
;
import
'package:gen_defaults/banner_template.dart'
;
import
'package:gen_defaults/bottom_app_bar_template.dart'
;
import
'package:gen_defaults/bottom_sheet_template.dart'
;
...
...
@@ -54,6 +55,7 @@ Future<void> main(List<String> args) async {
const
List
<
String
>
tokenFiles
=
<
String
>[
'badge.json'
,
'banner.json'
,
'badge.json'
,
'bottom_app_bar.json'
,
'button_elevated.json'
,
'button_filled.json'
,
...
...
@@ -125,6 +127,8 @@ Future<void> main(List<String> args) async {
ActionChipTemplate
(
'Chip'
,
'
$materialLib
/chip.dart'
,
tokens
).
updateFile
();
ActionChipTemplate
(
'ActionChip'
,
'
$materialLib
/action_chip.dart'
,
tokens
).
updateFile
();
AppBarTemplate
(
'AppBar'
,
'
$materialLib
/app_bar.dart'
,
tokens
).
updateFile
();
BottomAppBarTemplate
(
'BottomAppBar'
,
'
$materialLib
/bottom_app_bar.dart'
,
tokens
).
updateFile
();
BadgeTemplate
(
'Badge'
,
'
$materialLib
/badge.dart'
,
tokens
).
updateFile
();
BannerTemplate
(
'Banner'
,
'
$materialLib
/banner.dart'
,
tokens
).
updateFile
();
BottomAppBarTemplate
(
'BottomAppBar'
,
'
$materialLib
/bottom_app_bar.dart'
,
tokens
).
updateFile
();
BottomSheetTemplate
(
'BottomSheet'
,
'
$materialLib
/bottom_sheet.dart'
,
tokens
).
updateFile
();
...
...
dev/tools/gen_defaults/lib/badge_template.dart
0 → 100644
View file @
5a600456
// 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
'template.dart'
;
class
BadgeTemplate
extends
TokenTemplate
{
const
BadgeTemplate
(
super
.
blockName
,
super
.
fileName
,
super
.
tokens
,
{
super
.
colorSchemePrefix
=
'_colors.'
,
});
@override
String
generate
()
=>
'''
class _
${blockName}
DefaultsM3 extends BadgeThemeData {
_
${blockName}
DefaultsM3(this.context) : super(
smallSize:
${tokens["md.comp.badge.size"]}
,
largeSize:
${tokens["md.comp.badge.large.size"]}
,
padding: const EdgeInsets.symmetric(horizontal: 4),
alignment: const AlignmentDirectional(12, -4),
);
final BuildContext context;
late final ThemeData _theme = Theme.of(context);
late final ColorScheme _colors = _theme.colorScheme;
@override
Color? get backgroundColor =>
${color("md.comp.badge.color")}
;
@override
Color? get textColor =>
${color("md.comp.badge.large.label-text.color")}
;
@override
TextStyle? get textStyle =>
${textStyle("md.comp.badge.large.label-text")}
;
}
'''
;
}
packages/flutter/lib/material.dart
View file @
5a600456
...
...
@@ -30,6 +30,8 @@ export 'src/material/app_bar_theme.dart';
export
'src/material/arc.dart'
;
export
'src/material/autocomplete.dart'
;
export
'src/material/back_button.dart'
;
export
'src/material/badge.dart'
;
export
'src/material/badge_theme.dart'
;
export
'src/material/banner.dart'
;
export
'src/material/banner_theme.dart'
;
export
'src/material/bottom_app_bar.dart'
;
...
...
packages/flutter/lib/src/material/badge.dart
0 → 100644
View file @
5a600456
// 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
'package:flutter/widgets.dart'
;
import
'badge_theme.dart'
;
import
'color_scheme.dart'
;
import
'theme.dart'
;
/// A Material Design "badge".
///
/// A badge's [label] conveys a small amount of information about its
/// [child], like a count or status. If the label is null then this is
/// a "small" badge that's displayed as a [smallSize] diameter filled
/// circle. Otherwise this is a [StadiumBorder] shaped "large" badge
/// with height [largeSize].
///
/// Badges are typically used to decorate the icon within a
/// BottomNavigationBarItem] or a [NavigationRailDestination]
/// or a button's icon, as in [TextButton.icon]. The badge's default
/// configuration is intended to work well with a default sized (24)
/// [Icon].
class
Badge
extends
StatelessWidget
{
/// Create a Badge that stacks [label] on top of [child].
///
/// If [label] is null then just a filled circle is displayed. Otherwise
/// the [label] is displayed within a [StadiumBorder] shaped area.
const
Badge
({
super
.
key
,
this
.
backgroundColor
,
this
.
textColor
,
this
.
smallSize
,
this
.
largeSize
,
this
.
textStyle
,
this
.
padding
,
this
.
alignment
,
this
.
label
,
this
.
child
,
});
/// The badge's fill color.
///
/// Defaults to the [BadgeTheme]'s background color, or
/// [ColorScheme.errorColor] if the theme value is null.
final
Color
?
backgroundColor
;
/// The color of the badge's [label] text.
///
/// This color overrides the color of the label's [textStyle].
///
/// Defaults to the [BadgeTheme]'s foreground color, or
/// [ColorScheme.onError] if the theme value is null.
final
Color
?
textColor
;
/// The diameter of the badge if [label] is null.
///
/// Defaults to the [BadgeTheme]'s small size, or 6 if the theme value
/// is null.
final
double
?
smallSize
;
/// The badge's height if [label] is non-null.
///
/// Defaults to the [BadgeTheme]'s large size, or 16 if the theme value
/// is null. If the default value is overridden then it may be useful to
/// also override [padding] and [alignment].
final
double
?
largeSize
;
/// The [DefaultTextStyle] for the badge's label.
///
/// The text style's color is overwritten by the [textColor].
///
/// This value is only used if [label] is non-null.
///
/// Defaults to the [BadgeTheme]'s text style, or the overall theme's
/// [TextTheme.labelSmall] if the badge theme's value is null. If
/// the default text style is overridden then it may be useful to
/// also override [largeSize], [padding], and [alignment].
final
TextStyle
?
textStyle
;
/// The padding added to the badge's label.
///
/// This value is only used if [label] is non-null.
///
/// Defaults to the [BadgeTheme]'s padding, or 4 pixels on the
/// left and right if the theme's value is null.
final
EdgeInsetsGeometry
?
padding
;
/// The location of the [label] relative to the [child].
///
/// This value is only used if [label] is non-null.
///
/// Defaults to the [BadgeTheme]'s alignment, or `start = 12`
/// and `top = -4` if the theme's value is null.
final
AlignmentDirectional
?
alignment
;
/// The badge's content, typically a [Text] widget that contains 1 to 4
/// characters.
///
/// If the label is null then this is a "small" badge that's
/// displayed as a [smallSize] diameter filled circle. Otherwise
/// this is a [StadiumBorder] shaped "large" badge with height [largeSize].
final
Widget
?
label
;
/// The widget that the badge is stacked on top of.
///
/// Typically this is an default sized [Icon] that's part of a
/// [BottomNavigationBarItem] or a [NavigationRailDestination].
final
Widget
?
child
;
@override
Widget
build
(
BuildContext
context
)
{
final
BadgeThemeData
badgeTheme
=
BadgeTheme
.
of
(
context
);
final
BadgeThemeData
defaults
=
_BadgeDefaultsM3
(
context
);
final
double
effectiveSmallSize
=
smallSize
??
badgeTheme
.
smallSize
??
defaults
.
smallSize
!;
final
double
effectiveLargeSize
=
largeSize
??
badgeTheme
.
largeSize
??
defaults
.
largeSize
!;
final
Widget
badge
=
DefaultTextStyle
(
style:
(
textStyle
??
badgeTheme
.
textStyle
??
defaults
.
textStyle
!).
copyWith
(
color:
textColor
??
badgeTheme
.
textColor
??
defaults
.
textColor
!,
),
child:
IntrinsicWidth
(
child:
Container
(
height:
label
==
null
?
effectiveSmallSize
:
effectiveLargeSize
,
clipBehavior:
Clip
.
antiAlias
,
decoration:
ShapeDecoration
(
color:
backgroundColor
??
badgeTheme
.
backgroundColor
??
defaults
.
backgroundColor
!,
shape:
const
StadiumBorder
(),
),
padding:
label
==
null
?
null
:
(
padding
??
badgeTheme
.
padding
??
defaults
.
padding
!),
alignment:
label
==
null
?
null
:
Alignment
.
center
,
child:
label
??
SizedBox
(
width:
effectiveSmallSize
,
height:
effectiveSmallSize
),
),
),
);
if
(
child
==
null
)
{
return
badge
;
}
final
AlignmentDirectional
effectiveAlignment
=
alignment
??
badgeTheme
.
alignment
??
defaults
.
alignment
!;
return
Stack
(
clipBehavior:
Clip
.
none
,
children:
<
Widget
>[
child
!,
Positioned
.
directional
(
textDirection:
Directionality
.
of
(
context
),
start:
label
==
null
?
null
:
effectiveAlignment
.
start
,
end:
label
==
null
?
0
:
null
,
top:
label
==
null
?
0
:
effectiveAlignment
.
y
,
child:
badge
,
),
],
);
}
}
// BEGIN GENERATED TOKEN PROPERTIES - Badge
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: v0_137
class
_BadgeDefaultsM3
extends
BadgeThemeData
{
_BadgeDefaultsM3
(
this
.
context
)
:
super
(
smallSize:
6.0
,
largeSize:
16.0
,
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
4
),
alignment:
const
AlignmentDirectional
(
12
,
-
4
),
);
final
BuildContext
context
;
late
final
ThemeData
_theme
=
Theme
.
of
(
context
);
late
final
ColorScheme
_colors
=
_theme
.
colorScheme
;
@override
Color
?
get
backgroundColor
=>
_colors
.
error
;
@override
Color
?
get
textColor
=>
_colors
.
onError
;
@override
TextStyle
?
get
textStyle
=>
Theme
.
of
(
context
).
textTheme
.
labelSmall
;
}
// END GENERATED TOKEN PROPERTIES - Badge
packages/flutter/lib/src/material/badge_theme.dart
0 → 100644
View file @
5a600456
// 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/widgets.dart'
;
import
'theme.dart'
;
// Examples can assume:
// late BuildContext context;
/// Overrides the default properties values for descendant [Badge] widgets.
///
/// Descendant widgets obtain the current [BadgeThemeData] object
/// using `BadgeTheme.of(context)`. Instances of [BadgeThemeData] can
/// be customized with [BadgeThemeData.copyWith].
///
/// Typically a [BadgeThemeData] is specified as part of the
/// overall [Theme] with [ThemeData.badgeTheme].
///
/// All [BadgeThemeData] properties are `null` by default.
/// When null, the [Badge] will use the values from [ThemeData]
/// if they exist, otherwise it will provide its own defaults.
///
/// See also:
///
/// * [ThemeData], which describes the overall theme information for the
/// application.
@immutable
class
BadgeThemeData
with
Diagnosticable
{
/// Creates the set of color, style, and size properties used to configure [Badge].
const
BadgeThemeData
({
this
.
backgroundColor
,
this
.
textColor
,
this
.
smallSize
,
this
.
largeSize
,
this
.
textStyle
,
this
.
padding
,
this
.
alignment
,
});
/// Overrides the default value for [Badge.backgroundColor].
final
Color
?
backgroundColor
;
/// Overrides the default value for [Badge.textColor].
final
Color
?
textColor
;
/// Overrides the default value for [Badge.smallSize].
final
double
?
smallSize
;
/// Overrides the default value for [Badge.largeSize].
final
double
?
largeSize
;
/// Overrides the default value for [Badge.textStyle].
final
TextStyle
?
textStyle
;
/// Overrides the default value for [Badge.padding].
final
EdgeInsetsGeometry
?
padding
;
/// Overrides the default value for [Badge.alignment].
final
AlignmentDirectional
?
alignment
;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
BadgeThemeData
copyWith
({
Color
?
backgroundColor
,
Color
?
textColor
,
double
?
smallSize
,
double
?
largeSize
,
TextStyle
?
textStyle
,
EdgeInsetsGeometry
?
padding
,
AlignmentDirectional
?
alignment
,
})
{
return
BadgeThemeData
(
backgroundColor:
backgroundColor
??
this
.
backgroundColor
,
textColor:
textColor
??
this
.
textColor
,
smallSize:
smallSize
??
this
.
smallSize
,
largeSize:
largeSize
??
this
.
largeSize
,
textStyle:
textStyle
??
this
.
textStyle
,
padding:
padding
??
this
.
padding
,
alignment:
alignment
??
this
.
alignment
,
);
}
/// Linearly interpolate between two [Badge] themes.
static
BadgeThemeData
lerp
(
BadgeThemeData
?
a
,
BadgeThemeData
?
b
,
double
t
)
{
return
BadgeThemeData
(
backgroundColor:
Color
.
lerp
(
a
?.
backgroundColor
,
b
?.
backgroundColor
,
t
),
textColor:
Color
.
lerp
(
a
?.
textColor
,
b
?.
textColor
,
t
),
smallSize:
lerpDouble
(
a
?.
smallSize
,
b
?.
smallSize
,
t
),
largeSize:
lerpDouble
(
a
?.
largeSize
,
b
?.
largeSize
,
t
),
textStyle:
TextStyle
.
lerp
(
a
?.
textStyle
,
b
?.
textStyle
,
t
),
padding:
EdgeInsetsGeometry
.
lerp
(
a
?.
padding
,
b
?.
padding
,
t
),
alignment:
AlignmentDirectional
.
lerp
(
a
?.
alignment
,
b
?.
alignment
,
t
),
);
}
@override
int
get
hashCode
=>
Object
.
hash
(
backgroundColor
,
textColor
,
smallSize
,
largeSize
,
textStyle
,
padding
,
alignment
,
);
@override
bool
operator
==(
Object
other
)
{
if
(
identical
(
this
,
other
))
{
return
true
;
}
if
(
other
.
runtimeType
!=
runtimeType
)
{
return
false
;
}
return
other
is
BadgeThemeData
&&
other
.
backgroundColor
==
backgroundColor
&&
other
.
textColor
==
textColor
&&
other
.
smallSize
==
smallSize
&&
other
.
largeSize
==
largeSize
&&
other
.
textStyle
==
textStyle
&&
other
.
padding
==
padding
&&
other
.
alignment
==
alignment
;
}
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
super
.
debugFillProperties
(
properties
);
properties
.
add
(
ColorProperty
(
'backgroundColor'
,
backgroundColor
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'textColor'
,
textColor
,
defaultValue:
null
));
properties
.
add
(
DoubleProperty
(
'smallSize'
,
smallSize
,
defaultValue:
null
));
properties
.
add
(
DoubleProperty
(
'largeSize'
,
largeSize
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'textStyle'
,
textStyle
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
EdgeInsetsGeometry
>(
'padding'
,
padding
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
AlignmentDirectional
>(
'alignment'
,
alignment
,
defaultValue:
null
));
}
}
/// An inherited widget that overrides the default color style, and size
/// parameters for [Badge]s in this widget's subtree.
///
/// Values specified here override the defaults for [Badge] properties which
/// are not given an explicit non-null value.
class
BadgeTheme
extends
InheritedTheme
{
/// Creates a theme that overrides the default color parameters for [Badge]s
/// in this widget's subtree.
const
BadgeTheme
({
super
.
key
,
required
this
.
data
,
required
super
.
child
,
})
:
assert
(
data
!=
null
);
/// Specifies the default color and size overrides for descendant [Badge] widgets.
final
BadgeThemeData
data
;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [BadgeTheme] widget, then
/// [ThemeData.badgeTheme] is used.
///
/// Typical usage is as follows:
///
/// ```dart
/// BadgeThemeData theme = BadgeTheme.of(context);
/// ```
static
BadgeThemeData
of
(
BuildContext
context
)
{
final
BadgeTheme
?
badgeTheme
=
context
.
dependOnInheritedWidgetOfExactType
<
BadgeTheme
>();
return
badgeTheme
?.
data
??
Theme
.
of
(
context
).
badgeTheme
;
}
@override
Widget
wrap
(
BuildContext
context
,
Widget
child
)
{
return
BadgeTheme
(
data:
data
,
child:
child
);
}
@override
bool
updateShouldNotify
(
BadgeTheme
oldWidget
)
=>
data
!=
oldWidget
.
data
;
}
packages/flutter/lib/src/material/theme_data.dart
View file @
5a600456
...
...
@@ -8,6 +8,7 @@ import 'package:flutter/cupertino.dart';
import
'package:flutter/foundation.dart'
;
import
'app_bar_theme.dart'
;
import
'badge_theme.dart'
;
import
'banner_theme.dart'
;
import
'bottom_app_bar_theme.dart'
;
import
'bottom_navigation_bar_theme.dart'
;
...
...
@@ -331,6 +332,7 @@ class ThemeData with Diagnosticable {
Typography
?
typography
,
// COMPONENT THEMES
AppBarTheme
?
appBarTheme
,
BadgeThemeData
?
badgeTheme
,
MaterialBannerThemeData
?
bannerTheme
,
BottomAppBarTheme
?
bottomAppBarTheme
,
BottomNavigationBarThemeData
?
bottomNavigationBarTheme
,
...
...
@@ -583,6 +585,7 @@ class ThemeData with Diagnosticable {
// COMPONENT THEMES
appBarTheme
??=
const
AppBarTheme
();
badgeTheme
??=
const
BadgeThemeData
();
bannerTheme
??=
const
MaterialBannerThemeData
();
bottomAppBarTheme
??=
const
BottomAppBarTheme
();
bottomNavigationBarTheme
??=
const
BottomNavigationBarThemeData
();
...
...
@@ -676,6 +679,7 @@ class ThemeData with Diagnosticable {
primaryIconTheme:
primaryIconTheme
,
// COMPONENT THEMES
appBarTheme:
appBarTheme
,
badgeTheme:
badgeTheme
,
bannerTheme:
bannerTheme
,
bottomAppBarTheme:
bottomAppBarTheme
,
bottomNavigationBarTheme:
bottomNavigationBarTheme
,
...
...
@@ -786,6 +790,7 @@ class ThemeData with Diagnosticable {
required
this
.
typography
,
// COMPONENT THEMES
required
this
.
appBarTheme
,
required
this
.
badgeTheme
,
required
this
.
bannerTheme
,
required
this
.
bottomAppBarTheme
,
required
this
.
bottomNavigationBarTheme
,
...
...
@@ -954,6 +959,7 @@ class ThemeData with Diagnosticable {
assert
(
typography
!=
null
),
// COMPONENT THEMES
assert
(
appBarTheme
!=
null
),
assert
(
badgeTheme
!=
null
),
assert
(
bannerTheme
!=
null
),
assert
(
bottomAppBarTheme
!=
null
),
assert
(
bottomNavigationBarTheme
!=
null
),
...
...
@@ -1487,6 +1493,9 @@ class ThemeData with Diagnosticable {
/// textTheme of [AppBar]s.
final
AppBarTheme
appBarTheme
;
/// A theme for customizing the color of [Badge]s.
final
BadgeThemeData
badgeTheme
;
/// A theme for customizing the color and text style of a [MaterialBanner].
final
MaterialBannerThemeData
bannerTheme
;
...
...
@@ -1842,6 +1851,7 @@ class ThemeData with Diagnosticable {
Typography
?
typography
,
// COMPONENT THEMES
AppBarTheme
?
appBarTheme
,
BadgeThemeData
?
badgeTheme
,
MaterialBannerThemeData
?
bannerTheme
,
BottomAppBarTheme
?
bottomAppBarTheme
,
BottomNavigationBarThemeData
?
bottomNavigationBarTheme
,
...
...
@@ -2003,6 +2013,7 @@ class ThemeData with Diagnosticable {
typography:
typography
??
this
.
typography
,
// COMPONENT THEMES
appBarTheme:
appBarTheme
??
this
.
appBarTheme
,
badgeTheme:
badgeTheme
??
this
.
badgeTheme
,
bannerTheme:
bannerTheme
??
this
.
bannerTheme
,
bottomAppBarTheme:
bottomAppBarTheme
??
this
.
bottomAppBarTheme
,
bottomNavigationBarTheme:
bottomNavigationBarTheme
??
this
.
bottomNavigationBarTheme
,
...
...
@@ -2206,6 +2217,7 @@ class ThemeData with Diagnosticable {
typography:
Typography
.
lerp
(
a
.
typography
,
b
.
typography
,
t
),
// COMPONENT THEMES
appBarTheme:
AppBarTheme
.
lerp
(
a
.
appBarTheme
,
b
.
appBarTheme
,
t
),
badgeTheme:
BadgeThemeData
.
lerp
(
a
.
badgeTheme
,
b
.
badgeTheme
,
t
),
bannerTheme:
MaterialBannerThemeData
.
lerp
(
a
.
bannerTheme
,
b
.
bannerTheme
,
t
),
bottomAppBarTheme:
BottomAppBarTheme
.
lerp
(
a
.
bottomAppBarTheme
,
b
.
bottomAppBarTheme
,
t
),
bottomNavigationBarTheme:
BottomNavigationBarThemeData
.
lerp
(
a
.
bottomNavigationBarTheme
,
b
.
bottomNavigationBarTheme
,
t
),
...
...
@@ -2311,6 +2323,7 @@ class ThemeData with Diagnosticable {
other
.
typography
==
typography
&&
// COMPONENT THEMES
other
.
appBarTheme
==
appBarTheme
&&
other
.
badgeTheme
==
badgeTheme
&&
other
.
bannerTheme
==
bannerTheme
&&
other
.
bottomAppBarTheme
==
bottomAppBarTheme
&&
other
.
bottomNavigationBarTheme
==
bottomNavigationBarTheme
&&
...
...
@@ -2413,6 +2426,7 @@ class ThemeData with Diagnosticable {
typography
,
// COMPONENT THEMES
appBarTheme
,
badgeTheme
,
bannerTheme
,
bottomAppBarTheme
,
bottomNavigationBarTheme
,
...
...
@@ -2517,6 +2531,7 @@ class ThemeData with Diagnosticable {
properties
.
add
(
DiagnosticsProperty
<
Typography
>(
'typography'
,
typography
,
defaultValue:
defaultData
.
typography
,
level:
DiagnosticLevel
.
debug
));
// COMPONENT THEMES
properties
.
add
(
DiagnosticsProperty
<
AppBarTheme
>(
'appBarTheme'
,
appBarTheme
,
defaultValue:
defaultData
.
appBarTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
BadgeThemeData
>(
'badgeTheme'
,
badgeTheme
,
defaultValue:
defaultData
.
badgeTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
MaterialBannerThemeData
>(
'bannerTheme'
,
bannerTheme
,
defaultValue:
defaultData
.
bannerTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
BottomAppBarTheme
>(
'bottomAppBarTheme'
,
bottomAppBarTheme
,
defaultValue:
defaultData
.
bottomAppBarTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
BottomNavigationBarThemeData
>(
'bottomNavigationBarTheme'
,
bottomNavigationBarTheme
,
defaultValue:
defaultData
.
bottomNavigationBarTheme
,
level:
DiagnosticLevel
.
debug
));
...
...
packages/flutter/test/material/badge_test.dart
0 → 100644
View file @
5a600456
// 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
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'../rendering/mock_canvas.dart'
;
void
main
(
)
{
testWidgets
(
'Large Badge defaults'
,
(
WidgetTester
tester
)
async
{
late
final
ThemeData
theme
;
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
.
light
(
useMaterial3:
true
),
home:
Align
(
alignment:
Alignment
.
topLeft
,
child:
Builder
(
builder:
(
BuildContext
context
)
{
// theme.textTtheme is updated when the MaterialApp is built.
theme
=
Theme
.
of
(
context
);
return
const
Badge
(
label:
Text
(
'0'
),
child:
Icon
(
Icons
.
add
),
);
},
),
),
),
);
expect
(
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
'0'
)).
text
.
style
,
theme
.
textTheme
.
labelSmall
!.
copyWith
(
color:
theme
.
colorScheme
.
onError
),
);
// default badge alignment = AlignmentDirectional(12, -4)
// default padding = EdgeInsets.symmetric(horizontal: 4)
// default largeSize = 16
// '0'.width = 12
// icon.width = 24
expect
(
tester
.
getSize
(
find
.
byType
(
Badge
)),
const
Size
(
24
,
24
));
// default Icon size
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Badge
)),
Offset
.
zero
);
// x = alignment.start + padding.left
// y = alignment.top
expect
(
tester
.
getTopLeft
(
find
.
text
(
'0'
)),
const
Offset
(
16
,
-
4
));
final
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
Badge
));
// '0'.width = 12
// L = alignment.start
// T = alignment.top
// R = L + '0'.width + padding.width
// B = T + largeSize, R = largeSize/2
expect
(
box
,
paints
..
rrect
(
rrect:
RRect
.
fromLTRBR
(
12
,
-
4
,
32
,
12
,
const
Radius
.
circular
(
8
)),
color:
theme
.
colorScheme
.
error
));
});
testWidgets
(
'Large Badge defaults with RTL'
,
(
WidgetTester
tester
)
async
{
late
final
ThemeData
theme
;
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
.
light
(
useMaterial3:
true
),
home:
Directionality
(
textDirection:
TextDirection
.
rtl
,
child:
Align
(
alignment:
Alignment
.
topLeft
,
child:
Builder
(
builder:
(
BuildContext
context
)
{
// theme.textTtheme is updated when the MaterialApp is built.
theme
=
Theme
.
of
(
context
);
return
const
Badge
(
label:
Text
(
'0'
),
child:
Icon
(
Icons
.
add
),
);
},
),
),
),
),
);
expect
(
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
'0'
)).
text
.
style
,
theme
.
textTheme
.
labelSmall
!.
copyWith
(
color:
theme
.
colorScheme
.
onError
),
);
// default badge alignment = AlignmentDirectional(12, -4)
// default padding = EdgeInsets.symmetric(horizontal: 4)
// default largeSize = 16
// '0'.width = 12
// icon.width = 24
expect
(
tester
.
getSize
(
find
.
byType
(
Badge
)),
const
Size
(
24
,
24
));
// default Icon size
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Badge
)),
Offset
.
zero
);
// x = icon.width - alignment.start - '0'.width - padding.right
// y = alignment.top
expect
(
tester
.
getTopLeft
(
find
.
text
(
'0'
)),
const
Offset
(-
4
,
-
4
));
final
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
Badge
));
// L = icon.width - alignment.start - '0.width' - padding.width
// T = alignment.top
// R = L + '0.width' + padding.width
// B = T + largeSize
// R = largeSize/2
expect
(
box
,
paints
..
rrect
(
rrect:
RRect
.
fromLTRBR
(-
8
,
-
4
,
12
,
12
,
const
Radius
.
circular
(
8
)),
color:
theme
.
colorScheme
.
error
));
});
testWidgets
(
'Small Badge defaults'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
.
light
(
useMaterial3:
true
);
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
theme
,
home:
const
Align
(
alignment:
Alignment
.
topLeft
,
child:
Badge
(
child:
Icon
(
Icons
.
add
),
),
),
),
);
// default badge location is end=0, top=0
// default padding = EdgeInsets.symmetric(horizontal: 4)
// default smallSize = 6
// icon.width = 24
expect
(
tester
.
getSize
(
find
.
byType
(
Badge
)),
const
Size
(
24
,
24
));
// default Icon size
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Badge
)),
Offset
.
zero
);
final
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
Badge
));
// L = icon.size.width - smallSize
// T = 0
// R = icon.size.width
// B = smallSize
expect
(
box
,
paints
..
rrect
(
rrect:
RRect
.
fromLTRBR
(
18
,
0
,
24
,
6
,
const
Radius
.
circular
(
3
)),
color:
theme
.
colorScheme
.
error
));
});
testWidgets
(
'Small Badge RTL defaults'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
.
light
(
useMaterial3:
true
);
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
theme
,
home:
const
Directionality
(
textDirection:
TextDirection
.
rtl
,
child:
Align
(
alignment:
Alignment
.
topLeft
,
child:
Badge
(
child:
Icon
(
Icons
.
add
),
),
),
),
),
);
// default badge location is end=0, top=0
// default smallSize = 6
// icon.width = 24
expect
(
tester
.
getSize
(
find
.
byType
(
Badge
)),
const
Size
(
24
,
24
));
// default Icon size
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Badge
)),
Offset
.
zero
);
final
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
Badge
));
// L = 0
// T = 0
// R = smallSize
// B = smallSize
expect
(
box
,
paints
..
rrect
(
rrect:
RRect
.
fromLTRBR
(
0
,
0
,
6
,
6
,
const
Radius
.
circular
(
3
)),
color:
theme
.
colorScheme
.
error
));
});
testWidgets
(
'Large Badge textStyle and colors'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
.
light
(
useMaterial3:
true
);
const
Color
green
=
Color
(
0xff00ff00
);
const
Color
black
=
Color
(
0xff000000
);
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
theme
,
home:
const
Align
(
alignment:
Alignment
.
topLeft
,
child:
Badge
(
textColor:
green
,
backgroundColor:
black
,
textStyle:
TextStyle
(
fontSize:
10
),
label:
Text
(
'0'
),
child:
Icon
(
Icons
.
add
),
),
),
),
);
final
TextStyle
textStyle
=
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
'0'
)).
text
.
style
!;
expect
(
textStyle
.
fontSize
,
10
);
expect
(
textStyle
.
color
,
green
);
expect
(
tester
.
renderObject
(
find
.
byType
(
Badge
)),
paints
..
rrect
(
color:
black
));
});
}
packages/flutter/test/material/badge_theme_test.dart
0 → 100644
View file @
5a600456
// 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
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'../rendering/mock_canvas.dart'
;
void
main
(
)
{
test
(
'BadgeThemeData copyWith, ==, hashCode basics'
,
()
{
expect
(
const
BadgeThemeData
(),
const
BadgeThemeData
().
copyWith
());
expect
(
const
BadgeThemeData
().
hashCode
,
const
BadgeThemeData
().
copyWith
().
hashCode
);
});
test
(
'BadgeThemeData defaults'
,
()
{
const
BadgeThemeData
themeData
=
BadgeThemeData
();
expect
(
themeData
.
backgroundColor
,
null
);
expect
(
themeData
.
textColor
,
null
);
expect
(
themeData
.
smallSize
,
null
);
expect
(
themeData
.
largeSize
,
null
);
expect
(
themeData
.
textStyle
,
null
);
expect
(
themeData
.
padding
,
null
);
expect
(
themeData
.
alignment
,
null
);
});
testWidgets
(
'Default BadgeThemeData debugFillProperties'
,
(
WidgetTester
tester
)
async
{
final
DiagnosticPropertiesBuilder
builder
=
DiagnosticPropertiesBuilder
();
const
BadgeThemeData
().
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
(
'BadgeThemeData implements debugFillProperties'
,
(
WidgetTester
tester
)
async
{
final
DiagnosticPropertiesBuilder
builder
=
DiagnosticPropertiesBuilder
();
const
BadgeThemeData
(
backgroundColor:
Color
(
0xfffffff0
),
textColor:
Color
(
0xfffffff1
),
smallSize:
1
,
largeSize:
2
,
textStyle:
TextStyle
(
fontSize:
4
),
padding:
EdgeInsets
.
all
(
5
),
alignment:
AlignmentDirectional
(
6
,
7
),
).
debugFillProperties
(
builder
);
final
List
<
String
>
description
=
builder
.
properties
.
where
((
DiagnosticsNode
node
)
=>
!
node
.
isFiltered
(
DiagnosticLevel
.
info
))
.
map
((
DiagnosticsNode
node
)
=>
node
.
toString
())
.
toList
();
expect
(
description
,
<
String
>[
'backgroundColor: Color(0xfffffff0)'
,
'textColor: Color(0xfffffff1)'
,
'smallSize: 1.0'
,
'largeSize: 2.0'
,
'textStyle: TextStyle(inherit: true, size: 4.0)'
,
'padding: EdgeInsets.all(5.0)'
,
'alignment: AlignmentDirectional(6.0, 7.0)'
]);
});
testWidgets
(
'Badge uses ThemeData badge theme'
,
(
WidgetTester
tester
)
async
{
const
Color
green
=
Color
(
0xff00ff00
);
const
Color
black
=
Color
(
0xff000000
);
const
BadgeThemeData
badgeTheme
=
BadgeThemeData
(
backgroundColor:
green
,
textColor:
black
,
smallSize:
5
,
largeSize:
20
,
textStyle:
TextStyle
(
fontSize:
12
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
5
),
alignment:
AlignmentDirectional
(
24
,
0
),
);
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
.
light
(
useMaterial3:
true
).
copyWith
(
badgeTheme:
badgeTheme
,
),
home:
const
Scaffold
(
body:
Badge
(
label:
Text
(
'1234'
),
child:
Icon
(
Icons
.
add
),
),
),
),
);
// text width = 48 = fontSize * 4, text height = fontSize
expect
(
tester
.
getSize
(
find
.
text
(
'1234'
)),
const
Size
(
48
,
12
));
// x = 29 = alignment.start + padding.left, y = 4 = (largeSize - fontSize) / 2
expect
(
tester
.
getTopLeft
(
find
.
text
(
'1234'
)),
const
Offset
(
29
,
4
));
expect
(
tester
.
getSize
(
find
.
byType
(
Badge
)),
const
Size
(
24
,
24
));
// default Icon size
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Badge
)),
Offset
.
zero
);
final
TextStyle
textStyle
=
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
'1234'
)).
text
.
style
!;
expect
(
textStyle
.
fontSize
,
12
);
expect
(
textStyle
.
color
,
black
);
final
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
Badge
));
// L = alignment.start, T = alignment.top, R = L + fontSize * 4 + padding.width, B = largeSize R = largeSize/2
expect
(
box
,
paints
..
rrect
(
rrect:
RRect
.
fromLTRBR
(
24
,
0
,
82
,
20
,
const
Radius
.
circular
(
10
)),
color:
green
));
});
// This test is essentially the same as 'Badge uses ThemeData badge theme'. In
// this case the theme is introduced with the BadgeTheme widget instead of
// ThemeData.badgeTheme.
testWidgets
(
'Badge uses BadgeTheme'
,
(
WidgetTester
tester
)
async
{
const
Color
green
=
Color
(
0xff00ff00
);
const
Color
black
=
Color
(
0xff000000
);
const
BadgeThemeData
badgeTheme
=
BadgeThemeData
(
backgroundColor:
green
,
textColor:
black
,
smallSize:
5
,
largeSize:
20
,
textStyle:
TextStyle
(
fontSize:
12
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
5
),
alignment:
AlignmentDirectional
(
24
,
0
),
);
await
tester
.
pumpWidget
(
const
MaterialApp
(
home:
BadgeTheme
(
data:
badgeTheme
,
child:
Scaffold
(
body:
Badge
(
label:
Text
(
'1234'
),
child:
Icon
(
Icons
.
add
),
),
),
),
),
);
expect
(
tester
.
getSize
(
find
.
text
(
'1234'
)),
const
Size
(
48
,
12
));
expect
(
tester
.
getTopLeft
(
find
.
text
(
'1234'
)),
const
Offset
(
29
,
4
));
expect
(
tester
.
getSize
(
find
.
byType
(
Badge
)),
const
Size
(
24
,
24
));
// default Icon size
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Badge
)),
Offset
.
zero
);
final
TextStyle
textStyle
=
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
'1234'
)).
text
.
style
!;
expect
(
textStyle
.
fontSize
,
12
);
expect
(
textStyle
.
color
,
black
);
final
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
Badge
));
expect
(
box
,
paints
..
rrect
(
rrect:
RRect
.
fromLTRBR
(
24
,
0
,
82
,
20
,
const
Radius
.
circular
(
10
)),
color:
green
));
});
}
packages/flutter/test/material/theme_data_test.dart
View file @
5a600456
...
...
@@ -770,6 +770,7 @@ void main() {
typography:
Typography
.
material2018
(),
// COMPONENT THEMES
appBarTheme:
const
AppBarTheme
(
backgroundColor:
Colors
.
black
),
badgeTheme:
const
BadgeThemeData
(
backgroundColor:
Colors
.
black
),
bannerTheme:
const
MaterialBannerThemeData
(
backgroundColor:
Colors
.
black
),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
black
),
bottomNavigationBarTheme:
const
BottomNavigationBarThemeData
(
type:
BottomNavigationBarType
.
fixed
),
...
...
@@ -887,6 +888,7 @@ void main() {
// COMPONENT THEMES
appBarTheme:
const
AppBarTheme
(
backgroundColor:
Colors
.
white
),
badgeTheme:
const
BadgeThemeData
(
backgroundColor:
Colors
.
black
),
bannerTheme:
const
MaterialBannerThemeData
(
backgroundColor:
Colors
.
white
),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
white
),
bottomNavigationBarTheme:
const
BottomNavigationBarThemeData
(
type:
BottomNavigationBarType
.
shifting
),
...
...
@@ -990,6 +992,7 @@ void main() {
// COMPONENT THEMES
appBarTheme:
otherTheme
.
appBarTheme
,
badgeTheme:
otherTheme
.
badgeTheme
,
bannerTheme:
otherTheme
.
bannerTheme
,
bottomAppBarTheme:
otherTheme
.
bottomAppBarTheme
,
bottomNavigationBarTheme:
otherTheme
.
bottomNavigationBarTheme
,
...
...
@@ -1092,6 +1095,7 @@ void main() {
// COMPONENT THEMES
expect
(
themeDataCopy
.
appBarTheme
,
equals
(
otherTheme
.
appBarTheme
));
expect
(
themeDataCopy
.
badgeTheme
,
equals
(
otherTheme
.
badgeTheme
));
expect
(
themeDataCopy
.
bannerTheme
,
equals
(
otherTheme
.
bannerTheme
));
expect
(
themeDataCopy
.
bottomAppBarTheme
,
equals
(
otherTheme
.
bottomAppBarTheme
));
expect
(
themeDataCopy
.
bottomNavigationBarTheme
,
equals
(
otherTheme
.
bottomNavigationBarTheme
));
...
...
@@ -1230,6 +1234,7 @@ void main() {
'primaryIconTheme'
,
// COMPONENT THEMES
'appBarTheme'
,
'badgeTheme'
,
'bannerTheme'
,
'bottomAppBarTheme'
,
'bottomNavigationBarTheme'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment