Repository navigation
Fix/slider long label 63293 - #185149
Fix/slider long label 63293#185149mbcorona wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a horizontal buffer for value indicator labels in RangeSlider and Slider to prevent screen overflow. It implements a safeMaxWidth constraint during text layout, adds ellipsis support for truncated labels, and includes regression tests. The review feedback recommends replacing the deprecated textScaleFactor property with the modern textScaler API in both slider implementations.
| labelPainter | ||
| ..text = TextSpan(style: _sliderTheme.valueIndicatorTextStyle, text: text) | ||
| ..textDirection = textDirection | ||
| ..textScaleFactor = textScaleFactor | ||
| ..layout(); | ||
| ..maxLines = 1 | ||
| ..ellipsis = | ||
| '\u2026' // Standard Unicode ellipsis | ||
| ..layout(maxWidth: safeMaxWidth); |
There was a problem hiding this comment.
The textScaleFactor property on TextPainter is deprecated in favor of textScaler. Since you are already modifying this block to improve label layout, it's a good opportunity to update to the modern API. You can use TextScaler.linear(textScaleFactor) to maintain the current behavior while removing the deprecation warning.
labelPainter
..text = TextSpan(style: _sliderTheme.valueIndicatorTextStyle, text: text)
..textDirection = textDirection
..textScaler = TextScaler.linear(textScaleFactor)
..maxLines = 1
..ellipsis = '\u2026' // Standard Unicode ellipsis
..layout(maxWidth: safeMaxWidth);There was a problem hiding this comment.
I think this is a valid comment. We can change
..textScaleFactor = textScaleFactor to ..textScaler = TextScaler.linear(textScaleFactor). Same for Slider
| _labelPainter | ||
| ..text = TextSpan(style: _sliderTheme.valueIndicatorTextStyle, text: label) | ||
| ..textDirection = textDirection | ||
| ..textScaleFactor = textScaleFactor | ||
| ..layout(); | ||
| ..maxLines = 1 | ||
| ..ellipsis = | ||
| '\u2026' // Standard Unicode ellipsis | ||
| ..layout(maxWidth: safeMaxWidth); |
There was a problem hiding this comment.
The textScaleFactor property on TextPainter is deprecated. Using textScaler is preferred in modern Flutter code. Since textScaleFactor is available as a double in this context, you can wrap it with TextScaler.linear().
_labelPainter
..text = TextSpan(style: _sliderTheme.valueIndicatorTextStyle, text: label)
..textDirection = textDirection
..textScaler = TextScaler.linear(textScaleFactor)
..maxLines = 1
..ellipsis = '\u2026' // Standard Unicode ellipsis
..layout(maxWidth: safeMaxWidth);cbface7 to
27df1a9
Compare
QuncCccccc
left a comment
There was a problem hiding this comment.
Thanks for the fix:)! The code change looks good. I just left some comments regarding the changes in tests.
| ], | ||
| color: const Color(0xf55f5f5f), | ||
| ) | ||
| ..path(color: const Color(0xf55f5f5f)) |
There was a problem hiding this comment.
We should verify that the indicator actually scales instead of just checking the color. The purpose of this test is to check whether the indicator scales as the text scales.
| ], | ||
| color: const Color(0xf55f5f5f), | ||
| ) | ||
| ..path(color: const Color(0xf55f5f5f)) |
There was a problem hiding this comment.
I've just pushed a new commit that fixes this. Instead of looking for pixel coordinates, the test now intercepts the Canvas Path and extracts its bounds (getBounds()). It then dynamically asserts that both the width and height of the path are strictly greater when the textScaleFactor is increased to 2.0 (pathBounds2.width > pathBounds1.width).
| ], | ||
| color: const Color(0xf55f5f5f), | ||
| ) | ||
| ..path(color: const Color(0xf55f5f5f)) |
| labelPainter | ||
| ..text = TextSpan(style: _sliderTheme.valueIndicatorTextStyle, text: text) | ||
| ..textDirection = textDirection | ||
| ..textScaleFactor = textScaleFactor | ||
| ..layout(); | ||
| ..maxLines = 1 | ||
| ..ellipsis = | ||
| '\u2026' // Standard Unicode ellipsis | ||
| ..layout(maxWidth: safeMaxWidth); |
There was a problem hiding this comment.
I think this is a valid comment. We can change
..textScaleFactor = textScaleFactor to ..textScaler = TextScaler.linear(textScaleFactor). Same for Slider
QuncCccccc
left a comment
There was a problem hiding this comment.
Thanks for addressing the comments. One comment I left is to add a conditional check when we set maxWidth below. Let me know if there's any questions!
| builder: (BuildContext context, StateSetter setState) { | ||
| return MediaQuery( | ||
| data: MediaQueryData(textScaler: TextScaler.linear(textScaleFactor)), | ||
| data: MediaQuery.of( |
There was a problem hiding this comment.
MediaQuery Mocking: The new safeMaxWidth relies on MediaQuery.sizeOf(context).width. Several tests were mocking MediaQueryData from scratch without providing a size (defaulting to Size.zero). This caused the text constraint to evaluate to 0.0, shrinking the bubble and failing the tests. These were updated to use MediaQuery.of(context).copyWith(...) so they properly inherit the default test window dimensions (800x600).
I see why we made this change. To avoid future tests or app fail because of this, I think it would be safer to keep the defensive guard check (screenSize.width.isFinite && screenSize.width > 0 ? ... : double.infinity) in ..layout(maxWidth: xxx) for both Slider and RangeSlider. WDYT:)
| ], | ||
| color: const Color(0xf55f5f5f), | ||
| ) | ||
| ..something((Symbol method, List<dynamic> arguments) { |
There was a problem hiding this comment.
Can we just let the test fail, then see the new coordinates in the error output, and update the hardcoded numbers in the test (like how this test originally did)? I think that would be more straightforward to check whether the path change in some unexpected way. WDYT?
998a0db to
1701413
Compare
|
@QuncCccccc I've added the screenSize.width.isFinite && screenSize.width > 0 guard check for maxWidth in both slider.dart and range_slider.dart. Regarding the test coordinates: I tried reverting to the hardcoded Offset checks, but ran into a framework limitation. Because Path is an opaque engine object, flutter_test doesn't expose the vertices in the PaintPattern diff when an includes matcher fails (it just outputs * drawPath(Path, Paint(...))). Since hardcoding sub-pixel coordinates is what made these tests brittle to layout and scaling shifts in the first place, I removed the includes coordinate checks entirely. The tests still correctly verify that the indicator path color and paragraph are painted for both scale factors, but without relying on unmaintainable coordinate math. Let me know if this approach works for you! |
QuncCccccc
left a comment
There was a problem hiding this comment.
I've added the screenSize.width.isFinite && screenSize.width > 0 guard check for maxWidth in both slider.dart and range_slider.dart.
I think since we added this check, we don't need to update the existing tests now. Overall looks good to me:)!
| final logPainters = <TextPainter>[]; | ||
| final shape = LoggingRangeSliderValueIndicatorShape(<InlineSpan>[], logPainters); | ||
|
|
||
| const String longLabelStart = |
There was a problem hiding this comment.
HI @QuncCccccc , thanks for pointing out this, i have removed the type annotation.
There was a problem hiding this comment.
Once we reverted the changes on the existing tests, I think we are good to go:)!
* Updated documentation for `_kValueIndicatorHorizontalBuffer` to clarify the 64.0 heuristic. * Added unit tests to `slider_test.dart` and `range_slider_test.dart` utilizing custom value indicator shapes to capture and verify `TextPainter` layout constraints. * Refactored brittle `Path` offset expectations in `slider_test.dart` to use robust `paints` matchers. * Updated `MediaQuery` mocks in `slider_test.dart` to use `.copyWith()` so screen size defaults are properly inherited by the new `safeMaxWidth` calculation.
3fe0c11 to
7b90a9c
Compare
8a4a3d5 to
4487ed6
Compare
|
An existing Git SHA, To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with |
|
Since this PR is ready to land but we are still waiting for the code freeze, I'm going to mark this PR as draft for now. Once the decoupling has done, we can copy the change and create another PR over there:)! |
|
I've marked this PR as not ready to port to flutter/packages yet. |
|
Ported to flutter/packages#12572, following the instructions in |
…reen" (#12572) Ports flutter/flutter#185149 from flutter/flutter to flutter/packages, following the porting instructions in flutter/flutter#188444. Long text in a `Slider` or `RangeSlider` label clipped off the edges of the screen. This limits the label's `maxWidth` to the screen width minus a calculated horizontal buffer (`_kValueIndicatorHorizontalBuffer`), forces `maxLines = 1`, and applies the Unicode ellipsis (`\u2026`), so the text no longer expands past the screen boundary and the bubble shape no longer breaks vertically. A `screenSize.width.isFinite && screenSize.width > 0` guard keeps the constraint inert when no valid size is available. The original PR was reviewed and approved by @QuncCccccc. No merge commits were included; the five commits cherry-picked onto `material_ui` with no conflicts. Validation: - `dart format --set-exit-if-changed` on the four changed files - `git diff --check` - `flutter test test/slider_test.dart test/range_slider_test.dart` Fixes flutter/flutter#63293 ## Pre-Review Checklist **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
…er#191734) flutter/packages@df2ba94...740f093 2026-08-25 srawlins@google.com [cupertino_ui] Remove unused parameters from constructors of generic classes. (flutter/packages#12457) 2026-08-25 srawlins@google.com [material_ui] Remove unused parameters from constructors of generic classes. (flutter/packages#12458) 2026-08-25 6655696+guidezpl@users.noreply.github.com Ignore shared code for iOS platform implementation of Google Maps plugin (flutter/packages#12529) 2026-08-25 136096126+glitchfl@users.noreply.github.com [cross_file] fixed `readAsString` decoding in-memory bytes as UTF-16 (flutter/packages#12479) 2026-08-25 lozhkovoi@gmail.com [cupertino_ui] Remove two items assert to allow CupertinoTabBar to have one tab (flutter/packages#12546) 2026-08-25 huahua8893@sina.cn [cupertino_ui] Fix covered sheet revealing root route through top gap (flutter/packages#12530) 2026-08-25 fluttergithubbot@gmail.com Sync release-go_router-18.0.0 to main (flutter/packages#12575) 2026-08-25 fluttergithubbot@gmail.com Sync release-material_ui-1.1.0 to main (flutter/packages#12577) 2026-08-25 fluttergithubbot@gmail.com Sync release-cupertino_ui-1.0.1 to main (flutter/packages#12576) 2026-08-24 41930132+hellohuanlin@users.noreply.github.com [quick_actions_ios]unskip XCUITests (flutter/packages#12436) 2026-08-24 karthimanikuttan001@gmail.com Fix RangeSlider thumb overlay remains visible after touch interaction ends (flutter/packages#12560) 2026-08-24 victor.orozco@cloudsufi.com [google_sign_in] Increase iOS coverage tests (flutter/packages#12484) 2026-08-24 269567208+reidbaker-agent@users.noreply.github.com [camera_android_camerax] Migrate from dart_skills_lint to skills_lint (flutter/packages#12543) 2026-08-24 74037732+developerashkan@users.noreply.github.com [go_router] Clarify onEnter/redirect ordering, add regression test (flutter/packages#12337) 2026-08-24 brunocorona.alcantar@gmail.com [material_ui] Port flutter/flutter flutter#185149 "Slider label clips the screen" (flutter/packages#12572) 2026-08-24 engine-flutter-autoroll@skia.org Roll Flutter from 65c9a8d to 9a82789 (17 revisions) (flutter/packages#12578) 2026-08-24 stuartmorgan@google.com [tool] Fix dart_test.yaml parsing (flutter/packages#12574) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…reen" (flutter#12572) Ports flutter/flutter#185149 from flutter/flutter to flutter/packages, following the porting instructions in flutter/flutter#188444. Long text in a `Slider` or `RangeSlider` label clipped off the edges of the screen. This limits the label's `maxWidth` to the screen width minus a calculated horizontal buffer (`_kValueIndicatorHorizontalBuffer`), forces `maxLines = 1`, and applies the Unicode ellipsis (`\u2026`), so the text no longer expands past the screen boundary and the bubble shape no longer breaks vertically. A `screenSize.width.isFinite && screenSize.width > 0` guard keeps the constraint inert when no valid size is available. The original PR was reviewed and approved by @QuncCccccc. No merge commits were included; the five commits cherry-picked onto `material_ui` with no conflicts. Validation: - `dart format --set-exit-if-changed` on the four changed files - `git diff --check` - `flutter test test/slider_test.dart test/range_slider_test.dart` Fixes flutter/flutter#63293 ## Pre-Review Checklist **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.

Replaces #184208 to clean up a messy git history after a bad local merge.
This PR addresses the issue where long text in a
SliderorRangeSliderlabel clips off the edges of the screen.Following the discussion in the original issue and previous PR, this limits the label's
maxWidthtoscreenSize.widthminus a calculated horizontal buffer (_kValueIndicatorHorizontalBuffer). It also forcesmaxLines = 1and applies the Unicode ellipsis (\u2026). This prevents the text from expanding beyond the screen boundaries and prevents the bubble shape from breaking vertically.All previous feedback from @QuncCccccc has been addressed, including:
SliderandRangeSliderusing custom value indicator shapes to capture theTextPainterwidth.Fixes #63293
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.
Code Freeze Note: As discussed with @QuncCccccc in #184208, this PR is being opened to finalize the review process. We can mark it as a draft until the Material library migration to
flutter/packagesis complete, and then port it over.Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.