From 4da1dec288125ff3384988d035e504f37936cc6d Mon Sep 17 00:00:00 2001 From: yim Date: Fri, 28 Feb 2025 13:54:20 +0800 Subject: [PATCH] Fixed the issue that Slider's secondaryTrackValue is not updated. (#163996) Fixes: #163971 ## 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. - [ ] 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]. - [x] 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]. [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 --------- Co-authored-by: Taha Tesser --- packages/flutter/lib/src/material/slider.dart | 1 + .../flutter/test/material/slider_test.dart | 89 +++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart index d78137a59a..f80e52f1b9 100644 --- a/packages/flutter/lib/src/material/slider.dart +++ b/packages/flutter/lib/src/material/slider.dart @@ -1292,6 +1292,7 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin { return; } _secondaryTrackValue = newValue; + markNeedsPaint(); markNeedsSemanticsUpdate(); } diff --git a/packages/flutter/test/material/slider_test.dart b/packages/flutter/test/material/slider_test.dart index 6e4b77688e..d664a0c30c 100644 --- a/packages/flutter/test/material/slider_test.dart +++ b/packages/flutter/test/material/slider_test.dart @@ -16,6 +16,59 @@ import 'package:flutter_test/flutter_test.dart'; import '../widgets/semantics_tester.dart'; +/// A [RoundedRectSliderTrackShape] that logs its paint. +class LoggingRoundedRectSliderTrackShape extends RoundedRectSliderTrackShape { + LoggingRoundedRectSliderTrackShape({this.secondaryOffsetLog}); + final List? secondaryOffsetLog; + + @override + Rect getPreferredRect({ + required RenderBox parentBox, + Offset offset = Offset.zero, + required SliderThemeData sliderTheme, + bool isEnabled = true, + bool isDiscrete = false, + }) { + return super.getPreferredRect( + parentBox: parentBox, + offset: offset, + sliderTheme: sliderTheme, + isEnabled: isEnabled, + isDiscrete: isDiscrete, + ); + } + + @override + void paint( + PaintingContext context, + Offset offset, { + required RenderBox parentBox, + required SliderThemeData sliderTheme, + required Animation enableAnimation, + required TextDirection textDirection, + required Offset thumbCenter, + Offset? secondaryOffset, + bool isDiscrete = false, + bool isEnabled = false, + double additionalActiveTrackHeight = 2, + }) { + secondaryOffsetLog?.add(secondaryOffset); + super.paint( + context, + offset, + parentBox: parentBox, + sliderTheme: sliderTheme, + enableAnimation: enableAnimation, + textDirection: textDirection, + thumbCenter: thumbCenter, + secondaryOffset: secondaryOffset, + isDiscrete: isDiscrete, + isEnabled: isEnabled, + additionalActiveTrackHeight: additionalActiveTrackHeight, + ); + } +} + // A thumb shape that also logs its repaint center. class LoggingThumbShape extends SliderComponentShape { LoggingThumbShape(this.log); @@ -5179,4 +5232,40 @@ void main() { await gesture.up(); await tester.pumpAndSettle(); }); + + testWidgets('Can update renderObject when secondaryTrackValue is updated', ( + WidgetTester tester, + ) async { + final List log = []; + final LoggingRoundedRectSliderTrackShape loggingTrackShape = LoggingRoundedRectSliderTrackShape( + secondaryOffsetLog: log, + ); + final ThemeData theme = ThemeData(sliderTheme: SliderThemeData(trackShape: loggingTrackShape)); + Widget buildSlider(double? secondaryTrackValue) { + return MaterialApp( + theme: theme, + home: Material( + child: Center( + child: Slider( + value: 0, + secondaryTrackValue: secondaryTrackValue, + onChanged: (double value) {}, + ), + ), + ), + ); + } + + await tester.pumpWidget(buildSlider(null)); + await tester.pumpAndSettle(); + expect(log.last, isNull); + + await tester.pumpWidget(buildSlider(0.2)); + await tester.pumpAndSettle(); + expect(log.last, const Offset(174.4, 300.0)); + + await tester.pumpWidget(buildSlider(0.5)); + await tester.pumpAndSettle(); + expect(log.last, const Offset(400.0, 300.0)); + }); }