This repository was archived by the owner on Feb 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reland: Adds support for the Material Badge widget, BadgeTheme, Badge…
…ThemeData (#114560) (#115002) Requires G3Fix cl/486997831
- Loading branch information
1 parent
19b351b
commit 5a60045
Showing
9 changed files
with
796 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// 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")}; | ||
} | ||
'''; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
// 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 |
Oops, something went wrong.