From aaa4a528395fdda20b62c1008d916d82577292a0 Mon Sep 17 00:00:00 2001 From: Taha Tesser Date: Thu, 1 Dec 2022 02:00:19 +0200 Subject: [PATCH] Add Material 3 `Slider` example (#115638) * Add Material 3 `Slider` example * Update doc * Update test titles --- .../api/lib/material/slider/slider.0.dart | 47 +++++++------- .../api/lib/material/slider/slider.1.dart | 63 ++++++++----------- .../api/lib/material/slider/slider.2.dart | 63 +++++++++++++++++++ .../test/material/slider/slider.0_test.dart | 29 +++++++++ .../test/material/slider/slider.1_test.dart | 26 +++----- .../test/material/slider/slider.2_test.dart | 35 +++++++++++ packages/flutter/lib/src/material/slider.dart | 11 +++- 7 files changed, 193 insertions(+), 81 deletions(-) create mode 100644 examples/api/lib/material/slider/slider.2.dart create mode 100644 examples/api/test/material/slider/slider.0_test.dart create mode 100644 examples/api/test/material/slider/slider.2_test.dart diff --git a/examples/api/lib/material/slider/slider.0.dart b/examples/api/lib/material/slider/slider.0.dart index 8d7babef1cb8..f179bd356afd 100644 --- a/examples/api/lib/material/slider/slider.0.dart +++ b/examples/api/lib/material/slider/slider.0.dart @@ -6,47 +6,44 @@ import 'package:flutter/material.dart'; -void main() => runApp(const MyApp()); +void main() => runApp(const SliderApp()); -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - static const String _title = 'Flutter Code Sample'; +class SliderApp extends StatelessWidget { + const SliderApp({super.key}); @override Widget build(BuildContext context) { - return MaterialApp( - title: _title, - home: Scaffold( - appBar: AppBar(title: const Text(_title)), - body: const MyStatefulWidget(), - ), + return const MaterialApp( + home: SliderExample(), ); } } -class MyStatefulWidget extends StatefulWidget { - const MyStatefulWidget({super.key}); +class SliderExample extends StatefulWidget { + const SliderExample({super.key}); @override - State createState() => _MyStatefulWidgetState(); + State createState() => _SliderExampleState(); } -class _MyStatefulWidgetState extends State { +class _SliderExampleState extends State { double _currentSliderValue = 20; @override Widget build(BuildContext context) { - return Slider( - value: _currentSliderValue, - max: 100, - divisions: 5, - label: _currentSliderValue.round().toString(), - onChanged: (double value) { - setState(() { - _currentSliderValue = value; - }); - }, + return Scaffold( + appBar: AppBar(title: const Text('Slider')), + body: Slider( + value: _currentSliderValue, + max: 100, + divisions: 5, + label: _currentSliderValue.round().toString(), + onChanged: (double value) { + setState(() { + _currentSliderValue = value; + }); + }, + ), ); } } diff --git a/examples/api/lib/material/slider/slider.1.dart b/examples/api/lib/material/slider/slider.1.dart index 2c7d5f82639b..9d032bf5486a 100644 --- a/examples/api/lib/material/slider/slider.1.dart +++ b/examples/api/lib/material/slider/slider.1.dart @@ -6,61 +6,48 @@ import 'package:flutter/material.dart'; -void main() => runApp(const MyApp()); +void main() => runApp(const SliderApp()); -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - static const String _title = 'Flutter Code Sample'; +class SliderApp extends StatelessWidget { + const SliderApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( - title: _title, - home: Scaffold( - appBar: AppBar(title: const Text(_title)), - body: const MyStatefulWidget(), + theme: ThemeData( + colorSchemeSeed: const Color(0xff6750a4), + useMaterial3: true, ), + home: const SliderExample(), ); } } -class MyStatefulWidget extends StatefulWidget { - const MyStatefulWidget({super.key}); +class SliderExample extends StatefulWidget { + const SliderExample({super.key}); @override - State createState() => _MyStatefulWidgetState(); + State createState() => _SliderExampleState(); } -class _MyStatefulWidgetState extends State { - double _currentSliderPrimaryValue = 0.2; - double _currentSliderSecondaryValue = 0.5; +class _SliderExampleState extends State { + double _currentSliderValue = 20; @override Widget build(BuildContext context) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Slider( - value: _currentSliderPrimaryValue, - secondaryTrackValue: _currentSliderSecondaryValue, - label: _currentSliderPrimaryValue.round().toString(), - onChanged: (double value) { - setState(() { - _currentSliderPrimaryValue = value; - }); - }, - ), - Slider( - value: _currentSliderSecondaryValue, - label: _currentSliderSecondaryValue.round().toString(), - onChanged: (double value) { - setState(() { - _currentSliderSecondaryValue = value; - }); - }, - ), - ], + return Scaffold( + appBar: AppBar(title: const Text('Slider')), + body: Slider( + value: _currentSliderValue, + max: 100, + divisions: 5, + label: _currentSliderValue.round().toString(), + onChanged: (double value) { + setState(() { + _currentSliderValue = value; + }); + }, + ), ); } } diff --git a/examples/api/lib/material/slider/slider.2.dart b/examples/api/lib/material/slider/slider.2.dart new file mode 100644 index 000000000000..0ac2c1e9761c --- /dev/null +++ b/examples/api/lib/material/slider/slider.2.dart @@ -0,0 +1,63 @@ +// 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. + +/// Flutter code sample for [Slider]. + +import 'package:flutter/material.dart'; + +void main() => runApp(const SliderApp()); + +class SliderApp extends StatelessWidget { + const SliderApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + home: SliderExample(), + ); + } +} + +class SliderExample extends StatefulWidget { + const SliderExample({super.key}); + + @override + State createState() => _SliderExampleState(); +} + +class _SliderExampleState extends State { + double _currentSliderPrimaryValue = 0.2; + double _currentSliderSecondaryValue = 0.5; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Slider')), + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Slider( + value: _currentSliderPrimaryValue, + secondaryTrackValue: _currentSliderSecondaryValue, + label: _currentSliderPrimaryValue.round().toString(), + onChanged: (double value) { + setState(() { + _currentSliderPrimaryValue = value; + }); + }, + ), + Slider( + value: _currentSliderSecondaryValue, + label: _currentSliderSecondaryValue.round().toString(), + onChanged: (double value) { + setState(() { + _currentSliderSecondaryValue = value; + }); + }, + ), + ], + ), + ); + } +} diff --git a/examples/api/test/material/slider/slider.0_test.dart b/examples/api/test/material/slider/slider.0_test.dart new file mode 100644 index 000000000000..8ab403e3eb0e --- /dev/null +++ b/examples/api/test/material/slider/slider.0_test.dart @@ -0,0 +1,29 @@ +// 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_api_samples/material/slider/slider.0.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Slider can change its value', (WidgetTester tester) async { + await tester.pumpWidget( + const example.SliderApp(), + ); + + expect(find.byType(Slider), findsOneWidget); + + final Finder sliderFinder = find.byType(Slider); + + Slider slider = tester.widget(sliderFinder); + expect(slider.value, 20); + + final Offset center = tester.getCenter(sliderFinder); + await tester.tapAt(Offset(center.dx + 100, center.dy)); + await tester.pump(); + + slider = tester.widget(sliderFinder); + expect(slider.value, 60.0); + }); +} diff --git a/examples/api/test/material/slider/slider.1_test.dart b/examples/api/test/material/slider/slider.1_test.dart index df884ccbf235..3cdfc5cdb7ca 100644 --- a/examples/api/test/material/slider/slider.1_test.dart +++ b/examples/api/test/material/slider/slider.1_test.dart @@ -7,29 +7,23 @@ import 'package:flutter_api_samples/material/slider/slider.1.dart' as example; import 'package:flutter_test/flutter_test.dart'; void main() { - testWidgets('Slider shows secondary track', (WidgetTester tester) async { + testWidgets('Slider can change its value', (WidgetTester tester) async { await tester.pumpWidget( - const example.MyApp(), + const example.SliderApp(), ); - expect(find.byType(Slider), findsNWidgets(2)); + expect(find.byType(Slider), findsOneWidget); - final Finder slider1Finder = find.byType(Slider).at(0); - final Finder slider2Finder = find.byType(Slider).at(1); + final Finder sliderFinder = find.byType(Slider); - Slider slider1 = tester.widget(slider1Finder); - Slider slider2 = tester.widget(slider2Finder); - expect(slider1.secondaryTrackValue, slider2.value); + Slider slider = tester.widget(sliderFinder); + expect(slider.value, 20); - const double targetValue = 0.8; - final Rect rect = tester.getRect(slider2Finder); - final Offset target = Offset(rect.left + (rect.right - rect.left) * targetValue, rect.top + (rect.bottom - rect.top) / 2); - await tester.tapAt(target); + final Offset center = tester.getCenter(sliderFinder); + await tester.tapAt(Offset(center.dx + 100, center.dy)); await tester.pump(); - slider1 = tester.widget(slider1Finder); - slider2 = tester.widget(slider2Finder); - expect(slider1.secondaryTrackValue, closeTo(targetValue, 0.05)); - expect(slider1.secondaryTrackValue, slider2.value); + slider = tester.widget(sliderFinder); + expect(slider.value, 60.0); }); } diff --git a/examples/api/test/material/slider/slider.2_test.dart b/examples/api/test/material/slider/slider.2_test.dart new file mode 100644 index 000000000000..1ec99374587e --- /dev/null +++ b/examples/api/test/material/slider/slider.2_test.dart @@ -0,0 +1,35 @@ +// 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_api_samples/material/slider/slider.2.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Slider shows secondary track', (WidgetTester tester) async { + await tester.pumpWidget( + const example.SliderApp(), + ); + + expect(find.byType(Slider), findsNWidgets(2)); + + final Finder slider1Finder = find.byType(Slider).at(0); + final Finder slider2Finder = find.byType(Slider).at(1); + + Slider slider1 = tester.widget(slider1Finder); + Slider slider2 = tester.widget(slider2Finder); + expect(slider1.secondaryTrackValue, slider2.value); + + const double targetValue = 0.8; + final Rect rect = tester.getRect(slider2Finder); + final Offset target = Offset(rect.left + (rect.right - rect.left) * targetValue, rect.top + (rect.bottom - rect.top) / 2); + await tester.tapAt(target); + await tester.pump(); + + slider1 = tester.widget(slider1Finder); + slider2 = tester.widget(slider2Finder); + expect(slider1.secondaryTrackValue, closeTo(targetValue, 0.05)); + expect(slider1.secondaryTrackValue, slider2.value); + }); +} diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart index f9abab6d10e7..3703f9030d53 100644 --- a/packages/flutter/lib/src/material/slider.dart +++ b/packages/flutter/lib/src/material/slider.dart @@ -41,7 +41,7 @@ enum _SliderType { material, adaptive } /// {@youtube 560 315 https://www.youtube.com/watch?v=ufb4gIPDmEs} /// /// {@tool dartpad} -/// ![A slider widget, consisting of 5 divisions and showing the default value +/// ![A legacy slider widget, consisting of 5 divisions and showing the default value /// indicator.](https://flutter.github.io/assets-for-api-docs/assets/material/slider.png) /// /// The Sliders value is part of the Stateful widget subclass to change the value @@ -51,10 +51,17 @@ enum _SliderType { material, adaptive } /// {@end-tool} /// /// {@tool dartpad} +/// This sample shows the creation of a [Slider] using [ThemeData.useMaterial3] flag, +/// as described in: https://m3.material.io/components/sliders/overview. +/// +/// ** See code in examples/api/lib/material/slider/slider.1.dart ** +/// {@end-tool} +/// +/// {@tool dartpad} /// This example shows a [Slider] widget using the [Slider.secondaryTrackValue] /// to show a secondary track in the slider. /// -/// ** See code in examples/api/lib/material/slider/slider.1.dart ** +/// ** See code in examples/api/lib/material/slider/slider.2.dart ** /// {@end-tool} /// /// A slider can be used to select from either a continuous or a discrete set of