Updated Material 3 Progress Indicators Samples (#158925)
Fixes [Update both `ProgressIndicator` for Material 3 redesign](https://github.com/flutter/flutter/issues/141340) > [!IMPORTANT] > ~~This to be merged after https://github.com/flutter/flutter/pull/158104.~~ Merged. ### Description This updates progress indicator samples to include toggle to opt in to the updated Material 3 appearance . ### Preview <img width="753" alt="Screenshot 2024-12-04 at 15 54 50" src="https://github.com/user-attachments/assets/285f2803-1a12-470a-9afe-2abcf0548ff4"> <img width="753" alt="Screenshot 2024-12-04 at 15 58 35" src="https://github.com/user-attachments/assets/9caebec9-f65e-4baa-8e39-9a4a4a72b205"> ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
1856940f66
commit
a6d3bb5cb4
@ -6,10 +6,10 @@ import 'package:flutter/material.dart';
|
||||
|
||||
/// Flutter code sample for [CircularProgressIndicator].
|
||||
|
||||
void main() => runApp(const ProgressIndicatorApp());
|
||||
void main() => runApp(const ProgressIndicatorExampleApp());
|
||||
|
||||
class ProgressIndicatorApp extends StatelessWidget {
|
||||
const ProgressIndicatorApp({super.key});
|
||||
class ProgressIndicatorExampleApp extends StatelessWidget {
|
||||
const ProgressIndicatorExampleApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -28,19 +28,18 @@ class ProgressIndicatorExample extends StatefulWidget {
|
||||
|
||||
class _ProgressIndicatorExampleState extends State<ProgressIndicatorExample> with TickerProviderStateMixin {
|
||||
late AnimationController controller;
|
||||
bool year2023 = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = AnimationController(
|
||||
/// [AnimationController]s can be created with `vsync: this` because of
|
||||
/// [TickerProviderStateMixin].
|
||||
vsync: this,
|
||||
duration: const Duration(seconds: 5),
|
||||
)..addListener(() {
|
||||
setState(() {});
|
||||
});
|
||||
controller.repeat(reverse: true);
|
||||
super.initState();
|
||||
setState(() {});
|
||||
})
|
||||
..repeat(reverse: true);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -52,18 +51,32 @@ class _ProgressIndicatorExampleState extends State<ProgressIndicatorExample> wit
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
spacing: 16.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Circular progress indicator with a fixed color',
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
const Text('Determinate CircularProgressIndicator'),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: CircularProgressIndicator(
|
||||
year2023: year2023,
|
||||
value: controller.value,
|
||||
),
|
||||
),
|
||||
CircularProgressIndicator(
|
||||
value: controller.value,
|
||||
semanticsLabel: 'Circular progress indicator',
|
||||
const Text('Indeterminate CircularProgressIndicator'),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: CircularProgressIndicator(year2023: year2023),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: year2023,
|
||||
title: year2023 ? const Text('Switch to latest M3 style') : const Text('Switch to year2023 M3 style'),
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
year2023 = !year2023;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -6,10 +6,10 @@ import 'package:flutter/material.dart';
|
||||
|
||||
/// Flutter code sample for [CircularProgressIndicator].
|
||||
|
||||
void main() => runApp(const ProgressIndicatorApp());
|
||||
void main() => runApp(const ProgressIndicatorExampleApp());
|
||||
|
||||
class ProgressIndicatorApp extends StatelessWidget {
|
||||
const ProgressIndicatorApp({super.key});
|
||||
class ProgressIndicatorExampleApp extends StatelessWidget {
|
||||
const ProgressIndicatorExampleApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -57,18 +57,17 @@ class _ProgressIndicatorExampleState extends State<ProgressIndicatorExample> wit
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
spacing: 16.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Circular progress indicator',
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
CircularProgressIndicator(
|
||||
value: controller.value,
|
||||
semanticsLabel: 'Circular progress indicator',
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
|
@ -27,9 +27,9 @@ class ProgressIndicatorExample extends StatefulWidget {
|
||||
_ProgressIndicatorExampleState();
|
||||
}
|
||||
|
||||
class _ProgressIndicatorExampleState extends State<ProgressIndicatorExample>
|
||||
with TickerProviderStateMixin {
|
||||
class _ProgressIndicatorExampleState extends State<ProgressIndicatorExample> with TickerProviderStateMixin {
|
||||
late AnimationController controller;
|
||||
bool year2023 = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -54,18 +54,33 @@ class _ProgressIndicatorExampleState extends State<ProgressIndicatorExample>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
spacing: 16.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Text('Determinate LinearProgressIndicator'),
|
||||
LinearProgressIndicator(value: controller.value),
|
||||
const Text('Indeterminate LinearProgressIndicator'),
|
||||
const LinearProgressIndicator(),
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
spacing: 16.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Text('Determinate LinearProgressIndicator'),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: LinearProgressIndicator(
|
||||
year2023: year2023,
|
||||
value: controller.value,
|
||||
),
|
||||
),
|
||||
const Text('Indeterminate LinearProgressIndicator'),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: LinearProgressIndicator(year2023: year2023),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: year2023,
|
||||
title: year2023 ? const Text('Switch to latest M3 style') : const Text('Switch to year2023 M3 style'),
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
year2023 = !year2023;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -58,18 +58,17 @@ class _ProgressIndicatorExampleState extends State<ProgressIndicatorExample>
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
spacing: 16.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Text(
|
||||
'Linear progress indicator',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
LinearProgressIndicator(
|
||||
value: determinate ? controller.value : null,
|
||||
semanticsLabel: 'Linear progress indicator',
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
|
@ -2,23 +2,58 @@
|
||||
// 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_api_samples/material/progress_indicator/circular_progress_indicator.0.dart'
|
||||
as example;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Finds CircularProgressIndicator', (WidgetTester tester) async {
|
||||
testWidgets('Determinate CircularProgressIndicator uses the provided value', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const example.ProgressIndicatorApp(),
|
||||
const example.ProgressIndicatorExampleApp(),
|
||||
);
|
||||
await tester.pump(const Duration(milliseconds: 2500));
|
||||
|
||||
final Finder indicatorFinder = find.byType(CircularProgressIndicator).first;
|
||||
final CircularProgressIndicator progressIndicator = tester.widget(indicatorFinder);
|
||||
expect(progressIndicator.value, equals(0.5));
|
||||
});
|
||||
|
||||
testWidgets('Indeterminate CircularProgressIndicator does not have a value', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const example.ProgressIndicatorExampleApp(),
|
||||
);
|
||||
await tester.pump(const Duration(milliseconds: 2500));
|
||||
|
||||
final Finder indicatorFinder = find.byType(CircularProgressIndicator).last;
|
||||
final CircularProgressIndicator progressIndicator = tester.widget(indicatorFinder);
|
||||
expect(progressIndicator.value, null);
|
||||
});
|
||||
|
||||
testWidgets('Progress indicators year2023 flag can be toggled', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const example.ProgressIndicatorExampleApp(),
|
||||
);
|
||||
|
||||
expect(
|
||||
find.bySemanticsLabel('Circular progress indicator'),
|
||||
findsOneWidget,
|
||||
CircularProgressIndicator determinateIndicator = tester.widget<CircularProgressIndicator>(
|
||||
find.byType(CircularProgressIndicator).first,
|
||||
);
|
||||
expect(determinateIndicator.year2023, true);
|
||||
CircularProgressIndicator indeterminateIndicator = tester.widget<CircularProgressIndicator>(
|
||||
find.byType(CircularProgressIndicator).last,
|
||||
);
|
||||
expect(indeterminateIndicator.year2023, true);
|
||||
|
||||
// Test if CircularProgressIndicator is animating.
|
||||
await tester.pump(const Duration(seconds: 2));
|
||||
expect(tester.hasRunningAnimations, isTrue);
|
||||
await tester.tap(find.byType(SwitchListTile));
|
||||
await tester.pump();
|
||||
|
||||
determinateIndicator = tester.widget<CircularProgressIndicator>(
|
||||
find.byType(CircularProgressIndicator).first,
|
||||
);
|
||||
expect(determinateIndicator.year2023, false);
|
||||
indeterminateIndicator = tester.widget<CircularProgressIndicator>(
|
||||
find.byType(CircularProgressIndicator).last,
|
||||
);
|
||||
expect(indeterminateIndicator.year2023, false);
|
||||
});
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
void main() {
|
||||
testWidgets('Finds CircularProgressIndicator', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const example.ProgressIndicatorApp(),
|
||||
const example.ProgressIndicatorExampleApp(),
|
||||
);
|
||||
|
||||
expect(
|
||||
|
@ -8,33 +8,52 @@ import 'package:flutter_api_samples/material/progress_indicator/linear_progress_
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Determinate and Indeterminate LinearProgressIndicators',
|
||||
(WidgetTester tester) async {
|
||||
testWidgets('Determinate LinearProgressIndicator uses the provided value', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const example.ProgressIndicatorExampleApp(),
|
||||
);
|
||||
await tester.pump(const Duration(milliseconds: 2500));
|
||||
|
||||
final Finder indicatorFinder = find.byType(LinearProgressIndicator).first;
|
||||
final LinearProgressIndicator progressIndicator = tester.widget(indicatorFinder);
|
||||
expect(progressIndicator.value, equals(0.5));
|
||||
});
|
||||
|
||||
testWidgets('Indeterminate LinearProgressIndicator does not have a value', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const example.ProgressIndicatorExampleApp(),
|
||||
);
|
||||
await tester.pump(const Duration(milliseconds: 2500));
|
||||
|
||||
final Finder indicatorFinder = find.byType(LinearProgressIndicator).last;
|
||||
final LinearProgressIndicator progressIndicator = tester.widget(indicatorFinder);
|
||||
expect(progressIndicator.value, null);
|
||||
});
|
||||
|
||||
testWidgets('Progress indicators year2023 flag can be toggled', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const example.ProgressIndicatorExampleApp(),
|
||||
);
|
||||
|
||||
expect(find.text('Determinate LinearProgressIndicator'), findsOneWidget);
|
||||
expect(find.text('Indeterminate LinearProgressIndicator'), findsOneWidget);
|
||||
expect(find.byType(LinearProgressIndicator), findsNWidgets(2));
|
||||
|
||||
// Test determinate LinearProgressIndicator.
|
||||
LinearProgressIndicator determinateIndicator = tester.firstWidget(
|
||||
LinearProgressIndicator determinateIndicator = tester.widget<LinearProgressIndicator>(
|
||||
find.byType(LinearProgressIndicator).first,
|
||||
);
|
||||
expect(determinateIndicator.value, equals(0.0));
|
||||
|
||||
// Advance the animation by 2 seconds.
|
||||
await tester.pump(const Duration(seconds: 2));
|
||||
determinateIndicator = tester.firstWidget(
|
||||
find.byType(LinearProgressIndicator).first,
|
||||
);
|
||||
expect(determinateIndicator.value, equals(0.4));
|
||||
|
||||
// Test indeterminate LinearProgressIndicator.
|
||||
final LinearProgressIndicator indeterminateIndicator = tester.firstWidget(
|
||||
expect(determinateIndicator.year2023, true);
|
||||
LinearProgressIndicator indeterminateIndicator = tester.widget<LinearProgressIndicator>(
|
||||
find.byType(LinearProgressIndicator).last,
|
||||
);
|
||||
expect(indeterminateIndicator.value, null);
|
||||
expect(indeterminateIndicator.year2023, true);
|
||||
|
||||
await tester.tap(find.byType(SwitchListTile));
|
||||
await tester.pump();
|
||||
|
||||
determinateIndicator = tester.widget<LinearProgressIndicator>(
|
||||
find.byType(LinearProgressIndicator).first,
|
||||
);
|
||||
expect(determinateIndicator.year2023, false);
|
||||
indeterminateIndicator = tester.widget<LinearProgressIndicator>(
|
||||
find.byType(LinearProgressIndicator).last,
|
||||
);
|
||||
expect(indeterminateIndicator.year2023, false);
|
||||
});
|
||||
}
|
||||
|
@ -312,6 +312,8 @@ class _LinearProgressIndicatorPainter extends CustomPainter {
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This example showcases determinate and indeterminate [LinearProgressIndicator]s.
|
||||
/// The [LinearProgressIndicator]s will use the 
|
||||
/// when setting the [LinearProgressIndicator.year2023] flag to false.
|
||||
///
|
||||
/// ** See code in examples/api/lib/material/progress_indicator/linear_progress_indicator.0.dart **
|
||||
/// {@end-tool}
|
||||
@ -704,7 +706,9 @@ class _CircularProgressIndicatorPainter extends CustomPainter {
|
||||
/// specify a constant color use: `AlwaysStoppedAnimation<Color>(color)`.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This example shows a [CircularProgressIndicator] with a changing value.
|
||||
/// This example showcases determinate and indeterminate [CircularProgressIndicator]s.
|
||||
/// The [CircularProgressIndicator]s will use the 
|
||||
/// when setting the [CircularProgressIndicator.year2023] flag to false.
|
||||
///
|
||||
/// ** See code in examples/api/lib/material/progress_indicator/circular_progress_indicator.0.dart **
|
||||
/// {@end-tool}
|
||||
|
Loading…
x
Reference in New Issue
Block a user