Unverified Commit e2ddeb04 authored by Darren Austin's avatar Darren Austin Committed by GitHub

Added a ProgressIndicatorTheme. (#81075)

parent 4ff17343
......@@ -109,6 +109,7 @@ export 'src/material/paginated_data_table.dart';
export 'src/material/popup_menu.dart';
export 'src/material/popup_menu_theme.dart';
export 'src/material/progress_indicator.dart';
export 'src/material/progress_indicator_theme.dart';
export 'src/material/radio.dart';
export 'src/material/radio_list_tile.dart';
export 'src/material/radio_theme.dart';
......
......@@ -7,7 +7,9 @@ import 'dart:math' as math;
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'color_scheme.dart';
import 'material.dart';
import 'progress_indicator_theme.dart';
import 'theme.dart';
const double _kMinCircularProgressIndicatorSize = 36.0;
......@@ -24,7 +26,7 @@ enum _ActivityIndicatorType { material, adaptive }
///
/// See also:
///
/// * <https://material.io/design/components/progress-indicators.html>
/// * <https://material.io/components/progress-indicators>
abstract class ProgressIndicator extends StatefulWidget {
/// Creates a progress indicator.
///
......@@ -63,25 +65,29 @@ abstract class ProgressIndicator extends StatefulWidget {
/// The progress indicator's background color.
///
/// The current theme's [ColorScheme.background] by default.
///
/// This property is ignored if used in an adaptive constructor inside an iOS
/// environment.
/// It is up to the subclass to implement this in whatever way makes sense
/// for the given use case. See the subclass documentation for details.
final Color? backgroundColor;
/// {@template flutter.progress_indicator.ProgressIndicator.color}
/// The progress indicator's color.
///
/// This is only used if [valueColor] is null. If [color] is also null,
/// then it defaults to the current theme's [ColorScheme.primary] by default.
/// This is only used if [ProgressIndicator.valueColor] is null.
/// If [ProgressIndicator.color] is also null, then the ambient
/// [ProgressIndicatorThemeData.color] will be used. If that
/// is null then the current theme's [ColorScheme.primary] will
/// be used by default.
///
/// This property is ignored if used in an adaptive constructor inside an iOS
/// environment.
/// {@endtemplate}
final Color? color;
/// The progress indicator's color as an animated value.
///
/// If null, the progress indicator is rendered with [color], or if that is
/// also null then with the current theme's [ColorScheme.primary].
/// If null, the progress indicator is rendered with [color]. If that is null,
/// then it will use the ambient [ProgressIndicatorThemeData.color]. If that
/// is also null then it defaults to the current theme's [ColorScheme.primary].
///
/// This property is ignored if used in an adaptive constructor inside an iOS
/// environment.
......@@ -116,8 +122,13 @@ abstract class ProgressIndicator extends StatefulWidget {
/// {@endtemplate}
final String? semanticsValue;
Color _getBackgroundColor(BuildContext context) => backgroundColor ?? Theme.of(context).colorScheme.background;
Color _getValueColor(BuildContext context) => valueColor?.value ?? color ?? Theme.of(context).colorScheme.primary;
Color _getValueColor(BuildContext context) {
return
valueColor?.value ??
color ??
ProgressIndicatorTheme.of(context).color ??
Theme.of(context).colorScheme.primary;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
......@@ -320,18 +331,36 @@ class LinearProgressIndicator extends ProgressIndicator {
String? semanticsValue,
}) : assert(minHeight == null || minHeight > 0),
super(
key: key,
value: value,
backgroundColor: backgroundColor,
color: color,
valueColor: valueColor,
semanticsLabel: semanticsLabel,
semanticsValue: semanticsValue,
);
/// The minimum height of the line used to draw the indicator.
key: key,
value: value,
backgroundColor: backgroundColor,
color: color,
valueColor: valueColor,
semanticsLabel: semanticsLabel,
semanticsValue: semanticsValue,
);
/// {@template flutter.material.LinearProgressIndicator.trackColor}
/// Color of the track being filled by the linear indicator.
///
/// This defaults to 4dp.
/// If [LinearProgressIndicator.backgroundColor] is null then the
/// ambient [ProgressIndicatorThemeData.linearTrackColor] will be used.
/// If that is null, then the ambient theme's [ColorScheme.background]
/// will be used to draw the track.
///
/// This property is ignored if used in an adaptive constructor inside an iOS
/// environment.
/// {@endtemplate}
@override
Color? get backgroundColor => super.backgroundColor;
/// {@template flutter.material.LinearProgressIndicator.minHeight}
/// The minimum height of the line used to draw the linear indicator.
///
/// If [LinearProgressIndicator.minHeight] is null then it will use the
/// ambient [ProgressIndicatorThemeData.linearMinHeight]. If that is null
/// it will use 4dp.
/// {@endtemplate}
final double? minHeight;
@override
......@@ -368,16 +397,23 @@ class _LinearProgressIndicatorState extends State<LinearProgressIndicator> with
}
Widget _buildIndicator(BuildContext context, double animationValue, TextDirection textDirection) {
final ProgressIndicatorThemeData indicatorTheme = ProgressIndicatorTheme.of(context);
final Color trackColor =
widget.backgroundColor ??
indicatorTheme.linearTrackColor ??
Theme.of(context).colorScheme.background;
final double minHeight = widget.minHeight ?? indicatorTheme.linearMinHeight ?? 4.0;
return widget._buildSemanticsWrapper(
context: context,
child: Container(
constraints: BoxConstraints(
minWidth: double.infinity,
minHeight: widget.minHeight ?? 4.0,
minHeight: minHeight,
),
child: CustomPaint(
painter: _LinearProgressIndicatorPainter(
backgroundColor: widget._getBackgroundColor(context),
backgroundColor: trackColor,
valueColor: widget._getValueColor(context),
value: widget.value, // may be null
animationValue: animationValue, // ignored if widget.value is not null
......@@ -598,6 +634,19 @@ class CircularProgressIndicator extends ProgressIndicator {
final _ActivityIndicatorType _indicatorType;
/// {@template flutter.material.CircularProgressIndicator.trackColor}
/// Color of the circular track being filled by the circular indicator.
///
/// If [CircularProgressIndicator.backgroundColor] is null then the
/// ambient [ProgressIndicatorThemeData.circularTrackColor] will be used.
/// If that is null, then the track will not be painted.
///
/// This property is ignored if used in an adaptive constructor inside an iOS
/// environment.
/// {@endtemplate}
@override
Color? get backgroundColor => super.backgroundColor;
/// The width of the line used to draw the circle.
///
/// This property is ignored if used in an adaptive constructor inside an iOS
......@@ -658,6 +707,8 @@ class _CircularProgressIndicatorState extends State<CircularProgressIndicator> w
}
Widget _buildMaterialIndicator(BuildContext context, double headValue, double tailValue, double offsetValue, double rotationValue) {
final Color? trackColor = widget.backgroundColor ?? ProgressIndicatorTheme.of(context).circularTrackColor;
return widget._buildSemanticsWrapper(
context: context,
child: Container(
......@@ -667,7 +718,7 @@ class _CircularProgressIndicatorState extends State<CircularProgressIndicator> w
),
child: CustomPaint(
painter: _CircularProgressIndicatorPainter(
backgroundColor: widget.backgroundColor,
backgroundColor: trackColor,
valueColor: widget._getValueColor(context),
value: widget.value, // may be null
headValue: headValue, // remaining arguments are ignored if widget.value is not null
......@@ -803,6 +854,7 @@ class RefreshProgressIndicator extends CircularProgressIndicator {
Key? key,
double? value,
Color? backgroundColor,
Color? color,
Animation<Color?>? valueColor,
double strokeWidth = 2.0, // Different default than CircularProgressIndicator.
String? semanticsLabel,
......@@ -811,12 +863,23 @@ class RefreshProgressIndicator extends CircularProgressIndicator {
key: key,
value: value,
backgroundColor: backgroundColor,
color: color,
valueColor: valueColor,
strokeWidth: strokeWidth,
semanticsLabel: semanticsLabel,
semanticsValue: semanticsValue,
);
/// {@template flutter.material.RefreshProgressIndicator.backgroundColor}
/// Background color of that fills the circle under the refresh indicator.
///
/// If [RefreshIndicator.backgroundColor] is null then the
/// ambient [ProgressIndicatorThemeData.refreshBackgroundColor] will be used.
/// If that is null, then the ambient theme's [ThemeData.canvasColor]
/// will be used.
/// {@endtemplate}
@override
Color? get backgroundColor => super.backgroundColor;
@override
_RefreshProgressIndicatorState createState() => _RefreshProgressIndicatorState();
}
......@@ -840,6 +903,10 @@ class _RefreshProgressIndicatorState extends _CircularProgressIndicatorState {
@override
Widget _buildMaterialIndicator(BuildContext context, double headValue, double tailValue, double offsetValue, double rotationValue) {
final double arrowheadScale = widget.value == null ? 0.0 : (widget.value! * 2.0).clamp(0.0, 1.0);
final Color backgroundColor =
widget.backgroundColor ??
ProgressIndicatorTheme.of(context).refreshBackgroundColor ??
Theme.of(context).canvasColor;
return widget._buildSemanticsWrapper(
context: context,
child: Container(
......@@ -848,7 +915,7 @@ class _RefreshProgressIndicatorState extends _CircularProgressIndicatorState {
margin: const EdgeInsets.all(4.0), // accommodate the shadow
child: Material(
type: MaterialType.circle,
color: widget.backgroundColor ?? Theme.of(context).canvasColor,
color: backgroundColor,
elevation: 2.0,
child: Padding(
padding: const EdgeInsets.all(12.0),
......
// 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';
@immutable
/// Defines the visual properties of [ProgressIndicator] widgets.
///
/// Used by [ProgressIndicatorTheme] to control the visual properties of
/// progress indicators in a widget subtree.
///
/// To obtain this configuration, use [ProgressIndicatorTheme.of] to access
/// the closest ancestor [ProgressIndicatorTheme] of the current [BuildContext].
///
/// See also:
///
/// * [ProgressIndicatorTheme], an [InheritedWidget] that propagates the
/// theme down its subtree.
/// * [ThemeData.progressIndicatorTheme], which describes the defaults for
/// any progress indicators as part of the application's [ThemeData].
class ProgressIndicatorThemeData with Diagnosticable {
/// Creates the set of properties used to configure [ProgressIndicator] widgets.
const ProgressIndicatorThemeData({
this.color,
this.linearTrackColor,
this.linearMinHeight,
this.circularTrackColor,
this.refreshBackgroundColor,
});
/// The color of the [ProgressIndicator]'s indicator.
///
/// If null, then it will use [ColorScheme.primary] of the ambient
/// [ThemeData.colorScheme].
///
/// See also:
///
/// * [ProgressIndicator.color], which specifies the indicator color for a
/// specific progress indicator.
/// * [ProgressIndicator.valueColor], which specifies the indicator color
/// a an animated color.
final Color? color;
/// {@macro flutter.material.LinearProgressIndicator.trackColor}
final Color? linearTrackColor;
/// {@macro flutter.material.LinearProgressIndicator.minHeight}
final double? linearMinHeight;
/// {@macro flutter.material.CircularProgressIndicator.trackColor}
final Color? circularTrackColor;
/// {@macro flutter.material.RefreshProgressIndicator.backgroundColor}
final Color? refreshBackgroundColor;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
ProgressIndicatorThemeData copyWith({
Color? color,
Color? linearTrackColor,
double? linearMinHeight,
Color? circularTrackColor,
Color? refreshBackgroundColor,
}) {
return ProgressIndicatorThemeData(
color: color ?? this.color,
linearTrackColor : linearTrackColor ?? this.linearTrackColor,
linearMinHeight : linearMinHeight ?? this.linearMinHeight,
circularTrackColor : circularTrackColor ?? this.circularTrackColor,
refreshBackgroundColor : refreshBackgroundColor ?? this.refreshBackgroundColor,
);
}
/// Linearly interpolate between two progress indicator themes.
///
/// If both arguments are null, then null is returned.
static ProgressIndicatorThemeData? lerp(ProgressIndicatorThemeData? a, ProgressIndicatorThemeData? b, double t) {
if (a == null && b == null)
return null;
assert(t != null);
return ProgressIndicatorThemeData(
color: Color.lerp(a?.color, b?.color, t),
linearTrackColor : Color.lerp(a?.linearTrackColor, b?.linearTrackColor, t),
linearMinHeight : lerpDouble(a?.linearMinHeight, b?.linearMinHeight, t),
circularTrackColor : Color.lerp(a?.circularTrackColor, b?.circularTrackColor, t),
refreshBackgroundColor : Color.lerp(a?.refreshBackgroundColor, b?.refreshBackgroundColor, t),
);
}
@override
int get hashCode {
return hashValues(
color,
linearTrackColor,
linearMinHeight,
circularTrackColor,
refreshBackgroundColor,
);
}
@override
bool operator==(Object other) {
if (identical(this, other))
return true;
if (other.runtimeType != runtimeType)
return false;
return other is ProgressIndicatorThemeData
&& other.color == color
&& other.linearTrackColor == linearTrackColor
&& other.linearMinHeight == linearMinHeight
&& other.circularTrackColor == circularTrackColor
&& other.refreshBackgroundColor == refreshBackgroundColor;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(ColorProperty('color', color, defaultValue: null));
properties.add(ColorProperty('linearTrackColor', linearTrackColor, defaultValue: null));
properties.add(DoubleProperty('linearMinHeight', linearMinHeight, defaultValue: null));
properties.add(ColorProperty('circularTrackColor', circularTrackColor, defaultValue: null));
properties.add(ColorProperty('refreshBackgroundColor', refreshBackgroundColor, defaultValue: null));
}
}
/// An inherited widget that defines the configuration for
/// [ProgressIndicator]s in this widget's subtree.
///
/// Values specified here are used for [ProgressIndicator] properties that are not
/// given an explicit non-null value.
///
/// {@tool snippet}
///
/// Here is an example of a progress indicator theme that applies a red indicator
/// color with a slightly transparent red for the background track color.
///
/// ```dart
/// ProgressIndicatorTheme(
/// data: ProgressIndicatorThemeData(
/// color: Colors.red,
/// backgroundColor: Colors.red.withOpacity(0.25),
/// ),
/// child: LinearProgressIndicator()
/// ),
/// ```
/// {@end-tool}
class ProgressIndicatorTheme extends InheritedTheme {
/// Creates a theme that controls the configurations for [ProgressIndicator]
/// widgets.
const ProgressIndicatorTheme({
Key? key,
required this.data,
required Widget child,
}) : assert(data != null), super(key: key, child: child);
/// The properties for descendant [ProgressIndicator] widgets.
final ProgressIndicatorThemeData data;
/// Returns the [data] from the closest [ProgressIndicatorTheme] ancestor. If
/// there is no ancestor, it returns [ThemeData.progressIndicatorTheme].
///
/// Typical usage is as follows:
///
/// ```dart
/// ProgressIndicatorThemeData theme = ProgressIndicatorTheme.of(context);
/// ```
static ProgressIndicatorThemeData of(BuildContext context) {
final ProgressIndicatorTheme? progressIndicatorTheme = context.dependOnInheritedWidgetOfExactType<ProgressIndicatorTheme>();
return progressIndicatorTheme?.data ?? Theme.of(context).progressIndicatorTheme;
}
@override
Widget wrap(BuildContext context, Widget child) {
final ProgressIndicatorTheme? ancestorTheme = context.findAncestorWidgetOfExactType<ProgressIndicatorTheme>();
return identical(this, ancestorTheme) ? child : ProgressIndicatorTheme(data: data, child: child);
}
@override
bool updateShouldNotify(ProgressIndicatorTheme oldWidget) => data != oldWidget.data;
}
......@@ -31,6 +31,7 @@ import 'navigation_rail_theme.dart';
import 'outlined_button_theme.dart';
import 'page_transitions_theme.dart';
import 'popup_menu_theme.dart';
import 'progress_indicator_theme.dart';
import 'radio_theme.dart';
import 'scrollbar_theme.dart';
import 'slider_theme.dart';
......@@ -306,6 +307,7 @@ class ThemeData with Diagnosticable {
CheckboxThemeData? checkboxTheme,
RadioThemeData? radioTheme,
SwitchThemeData? switchTheme,
ProgressIndicatorThemeData? progressIndicatorTheme,
bool? fixTextFieldOutlineLabel,
@Deprecated(
'No longer used by the framework, please remove any reference to it. '
......@@ -443,6 +445,7 @@ class ThemeData with Diagnosticable {
checkboxTheme ??= const CheckboxThemeData();
radioTheme ??= const RadioThemeData();
switchTheme ??= const SwitchThemeData();
progressIndicatorTheme ??= const ProgressIndicatorThemeData();
fixTextFieldOutlineLabel ??= false;
useTextSelectionTheme ??= true;
......@@ -523,6 +526,7 @@ class ThemeData with Diagnosticable {
checkboxTheme: checkboxTheme,
radioTheme: radioTheme,
switchTheme: switchTheme,
progressIndicatorTheme: progressIndicatorTheme,
fixTextFieldOutlineLabel: fixTextFieldOutlineLabel,
useTextSelectionTheme: useTextSelectionTheme,
);
......@@ -626,6 +630,7 @@ class ThemeData with Diagnosticable {
required this.checkboxTheme,
required this.radioTheme,
required this.switchTheme,
required this.progressIndicatorTheme,
required this.fixTextFieldOutlineLabel,
@Deprecated(
'No longer used by the framework, please remove any reference to it. '
......@@ -704,6 +709,7 @@ class ThemeData with Diagnosticable {
assert(checkboxTheme != null),
assert(radioTheme != null),
assert(switchTheme != null),
assert(progressIndicatorTheme != null),
assert(fixTextFieldOutlineLabel != null),
assert(useTextSelectionTheme != null);
......@@ -1208,6 +1214,9 @@ class ThemeData with Diagnosticable {
/// A theme for customizing the appearance and layout of [Switch] widgets.
final SwitchThemeData switchTheme;
/// A theme for customizing the appearance and layout of [ProgressIndicator] widgets.
final ProgressIndicatorThemeData progressIndicatorTheme;
/// A temporary flag to allow apps to opt-in to a
/// [small fix](https://github.com/flutter/flutter/issues/54028) for the Y
/// coordinate of the floating label in a [TextField] [OutlineInputBorder].
......@@ -1322,6 +1331,7 @@ class ThemeData with Diagnosticable {
CheckboxThemeData? checkboxTheme,
RadioThemeData? radioTheme,
SwitchThemeData? switchTheme,
ProgressIndicatorThemeData? progressIndicatorTheme,
bool? fixTextFieldOutlineLabel,
@Deprecated(
'No longer used by the framework, please remove any reference to it. '
......@@ -1406,6 +1416,7 @@ class ThemeData with Diagnosticable {
checkboxTheme: checkboxTheme ?? this.checkboxTheme,
radioTheme: radioTheme ?? this.radioTheme,
switchTheme: switchTheme ?? this.switchTheme,
progressIndicatorTheme: progressIndicatorTheme ?? this.progressIndicatorTheme,
fixTextFieldOutlineLabel: fixTextFieldOutlineLabel ?? this.fixTextFieldOutlineLabel,
useTextSelectionTheme: useTextSelectionTheme ?? this.useTextSelectionTheme,
);
......@@ -1564,6 +1575,7 @@ class ThemeData with Diagnosticable {
checkboxTheme: CheckboxThemeData.lerp(a.checkboxTheme, b.checkboxTheme, t),
radioTheme: RadioThemeData.lerp(a.radioTheme, b.radioTheme, t),
switchTheme: SwitchThemeData.lerp(a.switchTheme, b.switchTheme, t),
progressIndicatorTheme: ProgressIndicatorThemeData.lerp(a.progressIndicatorTheme, b.progressIndicatorTheme, t)!,
fixTextFieldOutlineLabel: t < 0.5 ? a.fixTextFieldOutlineLabel : b.fixTextFieldOutlineLabel,
useTextSelectionTheme: t < 0.5 ? a.useTextSelectionTheme : b.useTextSelectionTheme,
);
......@@ -1650,6 +1662,7 @@ class ThemeData with Diagnosticable {
&& other.checkboxTheme == checkboxTheme
&& other.radioTheme == radioTheme
&& other.switchTheme == switchTheme
&& other.progressIndicatorTheme == progressIndicatorTheme
&& other.fixTextFieldOutlineLabel == fixTextFieldOutlineLabel
&& other.useTextSelectionTheme == useTextSelectionTheme;
}
......@@ -1735,6 +1748,7 @@ class ThemeData with Diagnosticable {
checkboxTheme,
radioTheme,
switchTheme,
progressIndicatorTheme,
fixTextFieldOutlineLabel,
useTextSelectionTheme,
];
......@@ -1818,6 +1832,7 @@ class ThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<CheckboxThemeData>('checkboxTheme', checkboxTheme, defaultValue: defaultData.checkboxTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<RadioThemeData>('radioTheme', radioTheme, defaultValue: defaultData.radioTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<SwitchThemeData>('switchTheme', switchTheme, defaultValue: defaultData.switchTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<ProgressIndicatorThemeData>('progressIndicatorTheme', progressIndicatorTheme, defaultValue: defaultData.progressIndicatorTheme, level: DiagnosticLevel.debug));
}
}
......
......@@ -62,7 +62,32 @@ void main() {
),
),
);
expect(
find.byType(LinearProgressIndicator),
paints
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 200.0, 2.0))
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 50.0, 2.0)),
);
// Same test, but using the theme
await tester.pumpWidget(
Theme(
data: ThemeData(
progressIndicatorTheme: const ProgressIndicatorThemeData(
linearMinHeight: 2.0,
),
),
child: const Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: SizedBox(
width: 200.0,
child: LinearProgressIndicator(value: 0.25),
),
),
),
),
);
expect(
find.byType(LinearProgressIndicator),
paints
......@@ -251,6 +276,39 @@ void main() {
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 200.0, 4.0))
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 50.0, 4.0), color: primaryColor),
);
// With ProgressIndicatorTheme colors
const Color indicatorColor = Color(0xff0000ff);
await tester.pumpWidget(
Theme(
data: ThemeData(
progressIndicatorTheme: const ProgressIndicatorThemeData(
color: indicatorColor,
linearTrackColor: Colors.black,
),
),
child: const Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: SizedBox(
width: 200.0,
child: LinearProgressIndicator(
value: 0.25,
),
),
),
),
),
);
// Should use the progress indicator theme colors
expect(
find.byType(LinearProgressIndicator),
paints
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 200.0, 4.0))
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 50.0, 4.0), color: indicatorColor),
);
});
testWidgets('LinearProgressIndicator with animation with null colors', (WidgetTester tester) async {
......@@ -367,6 +425,77 @@ void main() {
));
expect(find.byType(CircularProgressIndicator), paintsExactlyCountTimes(#drawArc, 2));
expect(find.byType(CircularProgressIndicator), paints..arc(color: green)..arc(color: blue));
// With ProgressIndicatorTheme
await tester.pumpWidget(Theme(
data: ThemeData(progressIndicatorTheme: const ProgressIndicatorThemeData(
color: green,
circularTrackColor: blue,
)),
child: const CircularProgressIndicator(),
));
expect(find.byType(CircularProgressIndicator), paintsExactlyCountTimes(#drawArc, 2));
expect(find.byType(CircularProgressIndicator), paints..arc(color: blue)..arc(color: green));
});
testWidgets('RefreshProgressIndicator paint colors', (WidgetTester tester) async {
const Color green = Color(0xFF00FF00);
const Color blue = Color(0xFF0000FF);
const Color red = Color(0xFFFF0000);
// With valueColor & color provided
await tester.pumpWidget(const RefreshProgressIndicator(
color: red,
valueColor: AlwaysStoppedAnimation<Color>(blue),
));
expect(find.byType(RefreshProgressIndicator), paintsExactlyCountTimes(#drawArc, 1));
expect(find.byType(RefreshProgressIndicator), paints..arc(color: blue));
// With just color provided
await tester.pumpWidget(const RefreshProgressIndicator(
color: red,
));
expect(find.byType(RefreshProgressIndicator), paintsExactlyCountTimes(#drawArc, 1));
expect(find.byType(RefreshProgressIndicator), paints..arc(color: red));
// With no color provided
await tester.pumpWidget(Theme(
data: ThemeData(colorScheme: ColorScheme.fromSwatch().copyWith(primary: green)),
child: const RefreshProgressIndicator(),
));
expect(find.byType(RefreshProgressIndicator), paintsExactlyCountTimes(#drawArc, 1));
expect(find.byType(RefreshProgressIndicator), paints..arc(color: green));
// With background
await tester.pumpWidget(const RefreshProgressIndicator(
color: blue,
backgroundColor: green,
));
expect(find.byType(RefreshProgressIndicator), paintsExactlyCountTimes(#drawArc, 1));
expect(find.byType(RefreshProgressIndicator), paints..arc(color: blue));
final Material backgroundMaterial = tester.widget(find.descendant(
of: find.byType(RefreshProgressIndicator),
matching: find.byType(Material)
));
expect(backgroundMaterial.type, MaterialType.circle);
expect(backgroundMaterial.color, green);
// With ProgressIndicatorTheme
await tester.pumpWidget(Theme(
data: ThemeData(progressIndicatorTheme: const ProgressIndicatorThemeData(
color: green,
refreshBackgroundColor: blue,
)),
child: const RefreshProgressIndicator(),
));
expect(find.byType(RefreshProgressIndicator), paintsExactlyCountTimes(#drawArc, 1));
expect(find.byType(RefreshProgressIndicator), paints..arc(color: green));
final Material themeBackgroundMaterial = tester.widget(find.descendant(
of: find.byType(RefreshProgressIndicator),
matching: find.byType(Material)
));
expect(themeBackgroundMaterial.type, MaterialType.circle);
expect(themeBackgroundMaterial.color, blue);
});
testWidgets('Indeterminate RefreshProgressIndicator keeps spinning until end of time (approximate)', (WidgetTester tester) async {
......
......@@ -762,6 +762,7 @@ void main() {
checkboxTheme: const CheckboxThemeData(),
radioTheme: const RadioThemeData(),
switchTheme: const SwitchThemeData(),
progressIndicatorTheme: const ProgressIndicatorThemeData(),
fixTextFieldOutlineLabel: false,
useTextSelectionTheme: false,
);
......
......@@ -316,6 +316,7 @@ void main() {
checkboxTheme: const CheckboxThemeData(),
radioTheme: const RadioThemeData(),
switchTheme: const SwitchThemeData(),
progressIndicatorTheme: const ProgressIndicatorThemeData(),
fixTextFieldOutlineLabel: false,
useTextSelectionTheme: false,
);
......@@ -409,6 +410,7 @@ void main() {
checkboxTheme: const CheckboxThemeData(),
radioTheme: const RadioThemeData(),
switchTheme: const SwitchThemeData(),
progressIndicatorTheme: const ProgressIndicatorThemeData(),
fixTextFieldOutlineLabel: true,
useTextSelectionTheme: true,
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment