Fix Slider renders track when track colors are transparent (#161814)

### Description

Fixes [`Slider` with transparent track colors and custom `trackHeight`
cannot reach the extreme ends
](https://github.com/flutter/flutter/issues/161210)

### Code Sample

<details>
<summary>expand to view the code sample</summary> 

```dart
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  double _value = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: Column(
            spacing: 20,
            mainAxisSize: MainAxisSize.min,
            children: [
              SizedBox(
                height: 4,
                width: 400,
                child: DecoratedBox(
                  decoration: const BoxDecoration(
                    gradient:
                        LinearGradient(colors: [Colors.yellow, Colors.green]),
                  ),
                  child: SliderTheme(
                    data: const SliderThemeData(
                      trackHeight: 200,
                      activeTrackColor: Colors.transparent,
                      inactiveTrackColor: Colors.transparent,
                      padding: EdgeInsets.zero,
                    ),
                    child: Slider(
                      value: _value,
                      max: 100,
                      onChanged: (double value) {
                        setState(() {
                          _value = value;
                        });
                      },
                    ),
                  ),
                ),
              ),
              Text('Slider value: ${_value.roundToDouble()}')
            ],
          ),
        ),
      ),
    );
  }
}

```

</details>


### Before

<img width="728" alt="Screenshot 2025-01-17 at 16 32 00"
src="https://github.com/user-attachments/assets/378a31b2-b897-4bf8-9067-66539239af09"
/>

### After

<img width="728" alt="Screenshot 2025-01-17 at 16 31 33"
src="https://github.com/user-attachments/assets/aef12d5e-a0cc-4947-8f72-2024edf29f14"
/>



## 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].
- [ ] 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:
Taha Tesser 2025-02-06 22:42:02 +02:00 committed by GitHub
parent 1b095a030d
commit 58b7ee137e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 1 deletions

View File

@ -1840,10 +1840,17 @@ mixin BaseSliderTrackShape {
final double thumbWidth = sliderTheme.thumbShape!.getPreferredSize(isEnabled, isDiscrete).width; final double thumbWidth = sliderTheme.thumbShape!.getPreferredSize(isEnabled, isDiscrete).width;
final double overlayWidth = final double overlayWidth =
sliderTheme.overlayShape!.getPreferredSize(isEnabled, isDiscrete).width; sliderTheme.overlayShape!.getPreferredSize(isEnabled, isDiscrete).width;
final double trackHeight = sliderTheme.trackHeight!; double trackHeight = sliderTheme.trackHeight!;
assert(overlayWidth >= 0); assert(overlayWidth >= 0);
assert(trackHeight >= 0); assert(trackHeight >= 0);
// If the track colors are transparent, then override only the track height
// to maintain overall Slider width.
if (sliderTheme.activeTrackColor == Colors.transparent &&
sliderTheme.inactiveTrackColor == Colors.transparent) {
trackHeight = 0;
}
final double trackLeft = final double trackLeft =
offset.dx + (sliderTheme.padding == null ? math.max(overlayWidth / 2, thumbWidth / 2) : 0); offset.dx + (sliderTheme.padding == null ? math.max(overlayWidth / 2, thumbWidth / 2) : 0);
final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2; final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;

View File

@ -3009,6 +3009,47 @@ void main() {
); );
}); });
// Regression test for https://github.com/flutter/flutter/issues/161210
testWidgets(
'Slider with transparent track colors and custom track height can reach extreme ends',
(WidgetTester tester) async {
const double sliderPadding = 24.0;
final ThemeData theme = ThemeData(
sliderTheme: const SliderThemeData(
trackHeight: 100,
activeTrackColor: Colors.transparent,
inactiveTrackColor: Colors.transparent,
),
);
Widget buildSlider({required double value}) {
return MaterialApp(
theme: theme,
home: Material(
child: SizedBox(width: 300, child: Slider(value: value, onChanged: (double value) {})),
),
);
}
await tester.pumpWidget(buildSlider(value: 0));
MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
expect(
material,
paints..circle(x: sliderPadding, y: 300.0, color: theme.colorScheme.primary),
);
await tester.pumpWidget(buildSlider(value: 1));
material = Material.of(tester.element(find.byType(Slider)));
expect(
material,
paints..circle(x: 800.0 - sliderPadding, y: 300.0, color: theme.colorScheme.primary),
);
},
);
group('Material 2', () { group('Material 2', () {
// These tests are only relevant for Material 2. Once Material 2 // These tests are only relevant for Material 2. Once Material 2
// support is deprecated and the APIs are removed, these tests // support is deprecated and the APIs are removed, these tests