1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/// @docImport 'elevated_button.dart';
6/// @docImport 'filled_button.dart';
7/// @docImport 'material.dart';
8/// @docImport 'outlined_button.dart';
9library;
10
11import 'dart:ui' show lerpDouble;
12
13import 'package:flutter/foundation.dart';
14import 'package:flutter/widgets.dart';
15
16import 'button_style.dart';
17import 'button_style_button.dart';
18import 'color_scheme.dart';
19import 'colors.dart';
20import 'constants.dart';
21import 'ink_ripple.dart';
22import 'ink_well.dart';
23import 'material_state.dart';
24import 'text_button_theme.dart';
25import 'theme.dart';
26import 'theme_data.dart';
27
28/// A Material Design "Text Button".
29///
30/// Use text buttons on toolbars, in dialogs, or inline with other
31/// content but offset from that content with padding so that the
32/// button's presence is obvious. Text buttons do not have visible
33/// borders and must therefore rely on their position relative to
34/// other content for context. In dialogs and cards, they should be
35/// grouped together in one of the bottom corners. Avoid using text
36/// buttons where they would blend in with other content, for example
37/// in the middle of lists.
38///
39/// A text button is a label [child] displayed on a (zero elevation)
40/// [Material] widget. The label's [Text] and [Icon] widgets are
41/// displayed in the [style]'s [ButtonStyle.foregroundColor]. The
42/// button reacts to touches by filling with the [style]'s
43/// [ButtonStyle.backgroundColor].
44///
45/// The text button's default style is defined by [defaultStyleOf].
46/// The style of this text button can be overridden with its [style]
47/// parameter. The style of all text buttons in a subtree can be
48/// overridden with the [TextButtonTheme] and the style of all of the
49/// text buttons in an app can be overridden with the [Theme]'s
50/// [ThemeData.textButtonTheme] property.
51///
52/// The static [styleFrom] method is a convenient way to create a
53/// text button [ButtonStyle] from simple values.
54///
55/// If the [onPressed] and [onLongPress] callbacks are null, then this
56/// button will be disabled, it will not react to touch.
57///
58/// {@tool dartpad}
59/// This sample shows various ways to configure TextButtons, from the
60/// simplest default appearance to versions that don't resemble
61/// Material Design at all.
62///
63/// ** See code in examples/api/lib/material/text_button/text_button.0.dart **
64/// {@end-tool}
65///
66/// {@tool dartpad}
67/// This sample demonstrates using the [statesController] parameter to create a button
68/// that adds support for [WidgetState.selected].
69///
70/// ** See code in examples/api/lib/material/text_button/text_button.1.dart **
71/// {@end-tool}
72///
73/// See also:
74///
75/// * [ElevatedButton], a filled button whose material elevates when pressed.
76/// * [FilledButton], a filled button that doesn't elevate when pressed.
77/// * [FilledButton.tonal], a filled button variant that uses a secondary fill color.
78/// * [OutlinedButton], a button with an outlined border and no fill color.
79/// * <https://material.io/design/components/buttons.html>
80/// * <https://m3.material.io/components/buttons>
81class TextButton extends ButtonStyleButton {
82 /// Create a [TextButton].
83 const TextButton({
84 super.key,
85 required super.onPressed,
86 super.onLongPress,
87 super.onHover,
88 super.onFocusChange,
89 super.style,
90 super.focusNode,
91 super.autofocus = false,
92 super.clipBehavior,
93 super.statesController,
94 super.isSemanticButton,
95 required Widget super.child,
96 });
97
98 /// Create a text button from a pair of widgets that serve as the button's
99 /// [icon] and [label].
100 ///
101 /// The icon and label are arranged in a row and padded by 8 logical pixels
102 /// at the ends, with an 8 pixel gap in between.
103 ///
104 /// If [icon] is null, will create a [TextButton] instead.
105 ///
106 /// {@macro flutter.material.ButtonStyleButton.iconAlignment}
107 ///
108 factory TextButton.icon({
109 Key? key,
110 required VoidCallback? onPressed,
111 VoidCallback? onLongPress,
112 ValueChanged<bool>? onHover,
113 ValueChanged<bool>? onFocusChange,
114 ButtonStyle? style,
115 FocusNode? focusNode,
116 bool? autofocus,
117 Clip? clipBehavior,
118 MaterialStatesController? statesController,
119 Widget? icon,
120 required Widget label,
121 IconAlignment? iconAlignment,
122 }) {
123 if (icon == null) {
124 return TextButton(
125 key: key,
126 onPressed: onPressed,
127 onLongPress: onLongPress,
128 onHover: onHover,
129 onFocusChange: onFocusChange,
130 style: style,
131 focusNode: focusNode,
132 autofocus: autofocus ?? false,
133 clipBehavior: clipBehavior ?? Clip.none,
134 statesController: statesController,
135 child: label,
136 );
137 }
138 return _TextButtonWithIcon(
139 key: key,
140 onPressed: onPressed,
141 onLongPress: onLongPress,
142 onHover: onHover,
143 onFocusChange: onFocusChange,
144 style: style,
145 focusNode: focusNode,
146 autofocus: autofocus ?? false,
147 clipBehavior: clipBehavior ?? Clip.none,
148 statesController: statesController,
149 icon: icon,
150 label: label,
151 iconAlignment: iconAlignment,
152 );
153 }
154
155 /// A static convenience method that constructs a text button
156 /// [ButtonStyle] given simple values.
157 ///
158 /// The [foregroundColor] and [disabledForegroundColor] colors are used
159 /// to create a [WidgetStateProperty] [ButtonStyle.foregroundColor], and
160 /// a derived [ButtonStyle.overlayColor] if [overlayColor] isn't specified.
161 ///
162 /// The [backgroundColor] and [disabledBackgroundColor] colors are
163 /// used to create a [WidgetStateProperty] [ButtonStyle.backgroundColor].
164 ///
165 /// Similarly, the [enabledMouseCursor] and [disabledMouseCursor]
166 /// parameters are used to construct [ButtonStyle.mouseCursor].
167 ///
168 /// The [iconColor], [disabledIconColor] are used to construct
169 /// [ButtonStyle.iconColor] and [iconSize] is used to construct
170 /// [ButtonStyle.iconSize].
171 ///
172 /// If [iconColor] is null, the button icon will use [foregroundColor]. If [foregroundColor] is also
173 /// null, the button icon will use the default icon color.
174 ///
175 /// If [overlayColor] is specified and its value is [Colors.transparent]
176 /// then the pressed/focused/hovered highlights are effectively defeated.
177 /// Otherwise a [WidgetStateProperty] with the same opacities as the
178 /// default is created.
179 ///
180 /// All of the other parameters are either used directly or used to
181 /// create a [WidgetStateProperty] with a single value for all
182 /// states.
183 ///
184 /// All parameters default to null. By default this method returns
185 /// a [ButtonStyle] that doesn't override anything.
186 ///
187 /// For example, to override the default text and icon colors for a
188 /// [TextButton], as well as its overlay color, with all of the
189 /// standard opacity adjustments for the pressed, focused, and
190 /// hovered states, one could write:
191 ///
192 /// ```dart
193 /// TextButton(
194 /// style: TextButton.styleFrom(foregroundColor: Colors.green),
195 /// child: const Text('Give Kate a mix tape'),
196 /// onPressed: () {
197 /// // ...
198 /// },
199 /// ),
200 /// ```
201 static ButtonStyle styleFrom({
202 Color? foregroundColor,
203 Color? backgroundColor,
204 Color? disabledForegroundColor,
205 Color? disabledBackgroundColor,
206 Color? shadowColor,
207 Color? surfaceTintColor,
208 Color? iconColor,
209 double? iconSize,
210 IconAlignment? iconAlignment,
211 Color? disabledIconColor,
212 Color? overlayColor,
213 double? elevation,
214 TextStyle? textStyle,
215 EdgeInsetsGeometry? padding,
216 Size? minimumSize,
217 Size? fixedSize,
218 Size? maximumSize,
219 BorderSide? side,
220 OutlinedBorder? shape,
221 MouseCursor? enabledMouseCursor,
222 MouseCursor? disabledMouseCursor,
223 VisualDensity? visualDensity,
224 MaterialTapTargetSize? tapTargetSize,
225 Duration? animationDuration,
226 bool? enableFeedback,
227 AlignmentGeometry? alignment,
228 InteractiveInkFeatureFactory? splashFactory,
229 ButtonLayerBuilder? backgroundBuilder,
230 ButtonLayerBuilder? foregroundBuilder,
231 }) {
232 final MaterialStateProperty<Color?>? backgroundColorProp = switch ((
233 backgroundColor,
234 disabledBackgroundColor,
235 )) {
236 (_?, null) => MaterialStatePropertyAll<Color?>(backgroundColor),
237 (_, _) => ButtonStyleButton.defaultColor(backgroundColor, disabledBackgroundColor),
238 };
239 final MaterialStateProperty<Color?>? iconColorProp = switch ((iconColor, disabledIconColor)) {
240 (_?, null) => MaterialStatePropertyAll<Color?>(iconColor),
241 (_, _) => ButtonStyleButton.defaultColor(iconColor, disabledIconColor),
242 };
243 final MaterialStateProperty<Color?>? overlayColorProp = switch ((
244 foregroundColor,
245 overlayColor,
246 )) {
247 (null, null) => null,
248 (_, Color(a: 0.0)) => WidgetStatePropertyAll<Color?>(overlayColor),
249 (_, final Color color) ||
250 (final Color color, _) => WidgetStateProperty<Color?>.fromMap(<WidgetState, Color?>{
251 WidgetState.pressed: color.withOpacity(0.1),
252 WidgetState.hovered: color.withOpacity(0.08),
253 WidgetState.focused: color.withOpacity(0.1),
254 }),
255 };
256
257 return ButtonStyle(
258 textStyle: ButtonStyleButton.allOrNull<TextStyle>(textStyle),
259 foregroundColor: ButtonStyleButton.defaultColor(foregroundColor, disabledForegroundColor),
260 backgroundColor: backgroundColorProp,
261 overlayColor: overlayColorProp,
262 shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
263 surfaceTintColor: ButtonStyleButton.allOrNull<Color>(surfaceTintColor),
264 iconColor: iconColorProp,
265 iconSize: ButtonStyleButton.allOrNull<double>(iconSize),
266 iconAlignment: iconAlignment,
267 elevation: ButtonStyleButton.allOrNull<double>(elevation),
268 padding: ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(padding),
269 minimumSize: ButtonStyleButton.allOrNull<Size>(minimumSize),
270 fixedSize: ButtonStyleButton.allOrNull<Size>(fixedSize),
271 maximumSize: ButtonStyleButton.allOrNull<Size>(maximumSize),
272 side: ButtonStyleButton.allOrNull<BorderSide>(side),
273 shape: ButtonStyleButton.allOrNull<OutlinedBorder>(shape),
274 mouseCursor: WidgetStateProperty<MouseCursor?>.fromMap(<WidgetStatesConstraint, MouseCursor?>{
275 WidgetState.disabled: disabledMouseCursor,
276 WidgetState.any: enabledMouseCursor,
277 }),
278 visualDensity: visualDensity,
279 tapTargetSize: tapTargetSize,
280 animationDuration: animationDuration,
281 enableFeedback: enableFeedback,
282 alignment: alignment,
283 splashFactory: splashFactory,
284 backgroundBuilder: backgroundBuilder,
285 foregroundBuilder: foregroundBuilder,
286 );
287 }
288
289 /// Defines the button's default appearance.
290 ///
291 /// {@template flutter.material.text_button.default_style_of}
292 /// The button [child]'s [Text] and [Icon] widgets are rendered with
293 /// the [ButtonStyle]'s foreground color. The button's [InkWell] adds
294 /// the style's overlay color when the button is focused, hovered
295 /// or pressed. The button's background color becomes its [Material]
296 /// color and is transparent by default.
297 ///
298 /// All of the [ButtonStyle]'s defaults appear below.
299 ///
300 /// In this list "Theme.foo" is shorthand for
301 /// `Theme.of(context).foo`. Color scheme values like
302 /// "onSurface(0.38)" are shorthand for
303 /// `onSurface.withOpacity(0.38)`. [WidgetStateProperty] valued
304 /// properties that are not followed by a sublist have the same
305 /// value for all states, otherwise the values are as specified for
306 /// each state and "others" means all other states.
307 ///
308 /// The "default font size" below refers to the font size specified in the
309 /// [defaultStyleOf] method (or 14.0 if unspecified), scaled by the
310 /// `MediaQuery.textScalerOf(context).scale` method. And the names of the
311 /// EdgeInsets constructors and `EdgeInsetsGeometry.lerp` have been abbreviated
312 /// for readability.
313 ///
314 /// The color of the [ButtonStyle.textStyle] is not used, the
315 /// [ButtonStyle.foregroundColor] color is used instead.
316 /// {@endtemplate}
317 ///
318 /// ## Material 2 defaults
319 ///
320 /// * `textStyle` - Theme.textTheme.button
321 /// * `backgroundColor` - transparent
322 /// * `foregroundColor`
323 /// * disabled - Theme.colorScheme.onSurface(0.38)
324 /// * others - Theme.colorScheme.primary
325 /// * `overlayColor`
326 /// * hovered - Theme.colorScheme.primary(0.08)
327 /// * focused or pressed - Theme.colorScheme.primary(0.12)
328 /// * `shadowColor` - Theme.shadowColor
329 /// * `elevation` - 0
330 /// * `padding`
331 /// * `default font size <= 14` - (horizontal(12), vertical(8))
332 /// * `14 < default font size <= 28` - lerp(all(8), horizontal(8))
333 /// * `28 < default font size <= 36` - lerp(horizontal(8), horizontal(4))
334 /// * `36 < default font size` - horizontal(4)
335 /// * `minimumSize` - Size(64, 36)
336 /// * `fixedSize` - null
337 /// * `maximumSize` - Size.infinite
338 /// * `side` - null
339 /// * `shape` - RoundedRectangleBorder(borderRadius: BorderRadius.circular(4))
340 /// * `mouseCursor`
341 /// * disabled - SystemMouseCursors.basic
342 /// * others - SystemMouseCursors.click
343 /// * `visualDensity` - theme.visualDensity
344 /// * `tapTargetSize` - theme.materialTapTargetSize
345 /// * `animationDuration` - kThemeChangeDuration
346 /// * `enableFeedback` - true
347 /// * `alignment` - Alignment.center
348 /// * `splashFactory` - InkRipple.splashFactory
349 ///
350 /// The default padding values for the [TextButton.icon] factory are slightly different:
351 ///
352 /// * `padding`
353 /// * `default font size <= 14` - all(8)
354 /// * `14 < default font size <= 28 `- lerp(all(8), horizontal(4))
355 /// * `28 < default font size` - horizontal(4)
356 ///
357 /// The default value for `side`, which defines the appearance of the button's
358 /// outline, is null. That means that the outline is defined by the button
359 /// shape's [OutlinedBorder.side]. Typically the default value of an
360 /// [OutlinedBorder]'s side is [BorderSide.none], so an outline is not drawn.
361 ///
362 /// ## Material 3 defaults
363 ///
364 /// If [ThemeData.useMaterial3] is set to true the following defaults will
365 /// be used:
366 ///
367 /// {@template flutter.material.text_button.material3_defaults}
368 /// * `textStyle` - Theme.textTheme.labelLarge
369 /// * `backgroundColor` - transparent
370 /// * `foregroundColor`
371 /// * disabled - Theme.colorScheme.onSurface(0.38)
372 /// * others - Theme.colorScheme.primary
373 /// * `overlayColor`
374 /// * hovered - Theme.colorScheme.primary(0.08)
375 /// * focused or pressed - Theme.colorScheme.primary(0.1)
376 /// * others - null
377 /// * `shadowColor` - Colors.transparent,
378 /// * `surfaceTintColor` - null
379 /// * `elevation` - 0
380 /// * `padding`
381 /// * `default font size <= 14` - lerp(horizontal(12), horizontal(4))
382 /// * `14 < default font size <= 28` - lerp(all(8), horizontal(8))
383 /// * `28 < default font size <= 36` - lerp(horizontal(8), horizontal(4))
384 /// * `36 < default font size` - horizontal(4)
385 /// * `minimumSize` - Size(64, 40)
386 /// * `fixedSize` - null
387 /// * `maximumSize` - Size.infinite
388 /// * `side` - null
389 /// * `shape` - StadiumBorder()
390 /// * `mouseCursor`
391 /// * disabled - SystemMouseCursors.basic
392 /// * others - SystemMouseCursors.click
393 /// * `visualDensity` - theme.visualDensity
394 /// * `tapTargetSize` - theme.materialTapTargetSize
395 /// * `animationDuration` - kThemeChangeDuration
396 /// * `enableFeedback` - true
397 /// * `alignment` - Alignment.center
398 /// * `splashFactory` - Theme.splashFactory
399 ///
400 /// For the [TextButton.icon] factory, the end (generally the right) value of
401 /// `padding` is increased from 12 to 16.
402 /// {@endtemplate}
403 @override
404 ButtonStyle defaultStyleOf(BuildContext context) {
405 final ThemeData theme = Theme.of(context);
406 final ColorScheme colorScheme = theme.colorScheme;
407
408 return Theme.of(context).useMaterial3
409 ? _TextButtonDefaultsM3(context)
410 : styleFrom(
411 foregroundColor: colorScheme.primary,
412 disabledForegroundColor: colorScheme.onSurface.withOpacity(0.38),
413 backgroundColor: Colors.transparent,
414 disabledBackgroundColor: Colors.transparent,
415 shadowColor: theme.shadowColor,
416 elevation: 0,
417 textStyle: theme.textTheme.labelLarge,
418 padding: _scaledPadding(context),
419 minimumSize: const Size(64, 36),
420 maximumSize: Size.infinite,
421 shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
422 enabledMouseCursor: SystemMouseCursors.click,
423 disabledMouseCursor: SystemMouseCursors.basic,
424 visualDensity: theme.visualDensity,
425 tapTargetSize: theme.materialTapTargetSize,
426 animationDuration: kThemeChangeDuration,
427 enableFeedback: true,
428 alignment: Alignment.center,
429 splashFactory: InkRipple.splashFactory,
430 );
431 }
432
433 /// Returns the [TextButtonThemeData.style] of the closest
434 /// [TextButtonTheme] ancestor.
435 @override
436 ButtonStyle? themeStyleOf(BuildContext context) {
437 return TextButtonTheme.of(context).style;
438 }
439}
440
441EdgeInsetsGeometry _scaledPadding(BuildContext context) {
442 final ThemeData theme = Theme.of(context);
443 final double defaultFontSize = theme.textTheme.labelLarge?.fontSize ?? 14.0;
444 final double effectiveTextScale = MediaQuery.textScalerOf(context).scale(defaultFontSize) / 14.0;
445 return ButtonStyleButton.scaledPadding(
446 theme.useMaterial3
447 ? const EdgeInsets.symmetric(horizontal: 12, vertical: 8)
448 : const EdgeInsets.all(8),
449 const EdgeInsets.symmetric(horizontal: 8),
450 const EdgeInsets.symmetric(horizontal: 4),
451 effectiveTextScale,
452 );
453}
454
455class _TextButtonWithIcon extends TextButton {
456 _TextButtonWithIcon({
457 super.key,
458 required super.onPressed,
459 super.onLongPress,
460 super.onHover,
461 super.onFocusChange,
462 super.style,
463 super.focusNode,
464 bool? autofocus,
465 super.clipBehavior,
466 super.statesController,
467 required Widget icon,
468 required Widget label,
469 IconAlignment? iconAlignment,
470 }) : super(
471 autofocus: autofocus ?? false,
472 child: _TextButtonWithIconChild(
473 icon: icon,
474 label: label,
475 buttonStyle: style,
476 iconAlignment: iconAlignment,
477 ),
478 );
479
480 @override
481 ButtonStyle defaultStyleOf(BuildContext context) {
482 final bool useMaterial3 = Theme.of(context).useMaterial3;
483 final ButtonStyle buttonStyle = super.defaultStyleOf(context);
484 final double defaultFontSize =
485 buttonStyle.textStyle?.resolve(const <MaterialState>{})?.fontSize ?? 14.0;
486 final double effectiveTextScale =
487 MediaQuery.textScalerOf(context).scale(defaultFontSize) / 14.0;
488 final EdgeInsetsGeometry scaledPadding = ButtonStyleButton.scaledPadding(
489 useMaterial3 ? const EdgeInsetsDirectional.fromSTEB(12, 8, 16, 8) : const EdgeInsets.all(8),
490 const EdgeInsets.symmetric(horizontal: 4),
491 const EdgeInsets.symmetric(horizontal: 4),
492 effectiveTextScale,
493 );
494 return buttonStyle.copyWith(
495 padding: MaterialStatePropertyAll<EdgeInsetsGeometry>(scaledPadding),
496 );
497 }
498}
499
500class _TextButtonWithIconChild extends StatelessWidget {
501 const _TextButtonWithIconChild({
502 required this.label,
503 required this.icon,
504 required this.buttonStyle,
505 required this.iconAlignment,
506 });
507
508 final Widget label;
509 final Widget icon;
510 final ButtonStyle? buttonStyle;
511 final IconAlignment? iconAlignment;
512
513 @override
514 Widget build(BuildContext context) {
515 final double defaultFontSize =
516 buttonStyle?.textStyle?.resolve(const <MaterialState>{})?.fontSize ?? 14.0;
517 final double scale =
518 clampDouble(MediaQuery.textScalerOf(context).scale(defaultFontSize) / 14.0, 1.0, 2.0) - 1.0;
519 final double gap = lerpDouble(8, 4, scale)!;
520 final TextButtonThemeData textButtonTheme = TextButtonTheme.of(context);
521 final IconAlignment effectiveIconAlignment =
522 iconAlignment ??
523 textButtonTheme.style?.iconAlignment ??
524 buttonStyle?.iconAlignment ??
525 IconAlignment.start;
526 return Row(
527 mainAxisSize: MainAxisSize.min,
528 children:
529 effectiveIconAlignment == IconAlignment.start
530 ? <Widget>[icon, SizedBox(width: gap), Flexible(child: label)]
531 : <Widget>[Flexible(child: label), SizedBox(width: gap), icon],
532 );
533 }
534}
535
536// BEGIN GENERATED TOKEN PROPERTIES - TextButton
537
538// Do not edit by hand. The code between the "BEGIN GENERATED" and
539// "END GENERATED" comments are generated from data in the Material
540// Design token database by the script:
541// dev/tools/gen_defaults/bin/gen_defaults.dart.
542
543// dart format off
544class _TextButtonDefaultsM3 extends ButtonStyle {
545 _TextButtonDefaultsM3(this.context)
546 : super(
547 animationDuration: kThemeChangeDuration,
548 enableFeedback: true,
549 alignment: Alignment.center,
550 );
551
552 final BuildContext context;
553 late final ColorScheme _colors = Theme.of(context).colorScheme;
554
555 @override
556 MaterialStateProperty<TextStyle?> get textStyle =>
557 MaterialStatePropertyAll<TextStyle?>(Theme.of(context).textTheme.labelLarge);
558
559 @override
560 MaterialStateProperty<Color?>? get backgroundColor =>
561 const MaterialStatePropertyAll<Color>(Colors.transparent);
562
563 @override
564 MaterialStateProperty<Color?>? get foregroundColor =>
565 MaterialStateProperty.resolveWith((Set<MaterialState> states) {
566 if (states.contains(MaterialState.disabled)) {
567 return _colors.onSurface.withOpacity(0.38);
568 }
569 return _colors.primary;
570 });
571
572 @override
573 MaterialStateProperty<Color?>? get overlayColor =>
574 MaterialStateProperty.resolveWith((Set<MaterialState> states) {
575 if (states.contains(MaterialState.pressed)) {
576 return _colors.primary.withOpacity(0.1);
577 }
578 if (states.contains(MaterialState.hovered)) {
579 return _colors.primary.withOpacity(0.08);
580 }
581 if (states.contains(MaterialState.focused)) {
582 return _colors.primary.withOpacity(0.1);
583 }
584 return null;
585 });
586
587 @override
588 MaterialStateProperty<Color>? get shadowColor =>
589 const MaterialStatePropertyAll<Color>(Colors.transparent);
590
591 @override
592 MaterialStateProperty<Color>? get surfaceTintColor =>
593 const MaterialStatePropertyAll<Color>(Colors.transparent);
594
595 @override
596 MaterialStateProperty<double>? get elevation =>
597 const MaterialStatePropertyAll<double>(0.0);
598
599 @override
600 MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
601 MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
602
603 @override
604 MaterialStateProperty<Size>? get minimumSize =>
605 const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
606
607 // No default fixedSize
608
609 @override
610 MaterialStateProperty<double>? get iconSize =>
611 const MaterialStatePropertyAll<double>(18.0);
612
613 @override
614 MaterialStateProperty<Color>? get iconColor {
615 return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
616 if (states.contains(MaterialState.disabled)) {
617 return _colors.onSurface.withOpacity(0.38);
618 }
619 if (states.contains(MaterialState.pressed)) {
620 return _colors.primary;
621 }
622 if (states.contains(MaterialState.hovered)) {
623 return _colors.primary;
624 }
625 if (states.contains(MaterialState.focused)) {
626 return _colors.primary;
627 }
628 return _colors.primary;
629 });
630 }
631
632 @override
633 MaterialStateProperty<Size>? get maximumSize =>
634 const MaterialStatePropertyAll<Size>(Size.infinite);
635
636 // No default side
637
638 @override
639 MaterialStateProperty<OutlinedBorder>? get shape =>
640 const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
641
642 @override
643 MaterialStateProperty<MouseCursor?>? get mouseCursor =>
644 MaterialStateProperty.resolveWith((Set<MaterialState> states) {
645 if (states.contains(MaterialState.disabled)) {
646 return SystemMouseCursors.basic;
647 }
648 return SystemMouseCursors.click;
649 });
650
651 @override
652 VisualDensity? get visualDensity => Theme.of(context).visualDensity;
653
654 @override
655 MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
656
657 @override
658 InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
659}
660// dart format on
661
662// END GENERATED TOKEN PROPERTIES - TextButton
663

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com