Skip to content

Commit c3587c6

Browse files
authored
Add InheritedTheme support to ScrollbarTheme (flutter#120970)
1 parent 51712b9 commit c3587c6

File tree

3 files changed

+192
-1
lines changed

3 files changed

+192
-1
lines changed

packages/flutter/lib/src/material/scrollbar_theme.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ bool? _lerpBool(bool? a, bool? b, double t) => t < 0.5 ? a : b;
299299
///
300300
/// * [ScrollbarThemeData], which describes the configuration of a
301301
/// scrollbar theme.
302-
class ScrollbarTheme extends InheritedWidget {
302+
class ScrollbarTheme extends InheritedTheme {
303303
/// Constructs a scrollbar theme that configures all descendant [Scrollbar]
304304
/// widgets.
305305
const ScrollbarTheme({
@@ -324,6 +324,11 @@ class ScrollbarTheme extends InheritedWidget {
324324
return scrollbarTheme?.data ?? Theme.of(context).scrollbarTheme;
325325
}
326326

327+
@override
328+
Widget wrap(BuildContext context, Widget child) {
329+
return ScrollbarTheme(data: data, child: child);
330+
}
331+
327332
@override
328333
bool updateShouldNotify(ScrollbarTheme oldWidget) => data != oldWidget.data;
329334
}

packages/flutter/test/material/menu_anchor_test.dart

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import 'package:flutter/rendering.dart';
99
import 'package:flutter/services.dart';
1010
import 'package:flutter_test/flutter_test.dart';
1111

12+
import '../rendering/mock_canvas.dart';
13+
1214
void main() {
1315
late MenuController controller;
1416
String? focusedMenu;
@@ -298,6 +300,101 @@ void main() {
298300
expect(iconRichText.text.style?.color, themeData.colorScheme.onSurface.withOpacity(0.38));
299301
});
300302

303+
testWidgets('Menu scrollbar inherits ScrollbarTheme', (WidgetTester tester) async {
304+
const ScrollbarThemeData scrollbarTheme = ScrollbarThemeData(
305+
thumbColor: MaterialStatePropertyAll<Color?>(Color(0xffff0000)),
306+
thumbVisibility: MaterialStatePropertyAll<bool?>(true),
307+
);
308+
await tester.pumpWidget(
309+
MaterialApp(
310+
theme: ThemeData(scrollbarTheme: scrollbarTheme),
311+
home: Material(
312+
child: MenuBar(
313+
children: <Widget>[
314+
SubmenuButton(
315+
menuChildren: <Widget>[
316+
MenuItemButton(
317+
style: ButtonStyle(
318+
minimumSize: MaterialStateProperty.all<Size>(
319+
const Size.fromHeight(1000),
320+
),
321+
),
322+
onPressed: () {},
323+
child: const Text(
324+
'Category',
325+
),
326+
),
327+
],
328+
child: const Text(
329+
'Main Menu',
330+
),
331+
),
332+
],
333+
),
334+
),
335+
),
336+
);
337+
338+
await tester.tap(find.text('Main Menu'));
339+
await tester.pumpAndSettle();
340+
341+
expect(find.byType(Scrollbar), findsOneWidget);
342+
// Test Scrollbar thumb color.
343+
expect(
344+
find.byType(Scrollbar),
345+
paints..rrect(color: const Color(0xffff0000)),
346+
);
347+
348+
// Close the menu.
349+
await tester.tapAt(const Offset(10.0, 10.0));
350+
await tester.pumpAndSettle();
351+
352+
await tester.pumpWidget(
353+
MaterialApp(
354+
theme: ThemeData(scrollbarTheme: scrollbarTheme),
355+
home: Material(
356+
child: ScrollbarTheme(
357+
data: scrollbarTheme.copyWith(
358+
thumbColor: const MaterialStatePropertyAll<Color?>(Color(0xff00ff00)),
359+
),
360+
child: MenuBar(
361+
children: <Widget>[
362+
SubmenuButton(
363+
menuChildren: <Widget>[
364+
MenuItemButton(
365+
style: ButtonStyle(
366+
minimumSize: MaterialStateProperty.all<Size>(
367+
const Size.fromHeight(1000),
368+
),
369+
),
370+
onPressed: () {},
371+
child: const Text(
372+
'Category',
373+
),
374+
),
375+
],
376+
child: const Text(
377+
'Main Menu',
378+
),
379+
),
380+
],
381+
),
382+
),
383+
),
384+
),
385+
);
386+
387+
await tester.tap(find.text('Main Menu'));
388+
await tester.pumpAndSettle();
389+
390+
expect(find.byType(Scrollbar), findsOneWidget);
391+
// Scrollbar thumb color should be updated.
392+
expect(
393+
find.byType(Scrollbar),
394+
paints..rrect(color: const Color(0xff00ff00)),
395+
);
396+
}, variant: TargetPlatformVariant.desktop());
397+
301398
group('Menu functions', () {
302399
testWidgets('basic menu structure', (WidgetTester tester) async {
303400
await tester.pumpWidget(

packages/flutter/test/material/popup_menu_test.dart

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
1010
import 'package:flutter/rendering.dart';
1111
import 'package:flutter_test/flutter_test.dart';
1212

13+
import '../rendering/mock_canvas.dart';
1314
import '../widgets/semantics_tester.dart';
1415
import 'feedback_tester.dart';
1516

@@ -3098,6 +3099,94 @@ void main() {
30983099
expect(nodeA().hasFocus, true);
30993100
expect(nodeB().hasFocus, false);
31003101
});
3102+
3103+
testWidgets('Popup menu scrollbar inherits ScrollbarTheme', (WidgetTester tester) async {
3104+
final Key popupButtonKey = UniqueKey();
3105+
const ScrollbarThemeData scrollbarTheme = ScrollbarThemeData(
3106+
thumbColor: MaterialStatePropertyAll<Color?>(Color(0xffff0000)),
3107+
thumbVisibility: MaterialStatePropertyAll<bool?>(true),
3108+
);
3109+
await tester.pumpWidget(
3110+
MaterialApp(
3111+
theme: ThemeData(
3112+
scrollbarTheme: scrollbarTheme,
3113+
useMaterial3: true,
3114+
),
3115+
home: Material(
3116+
child: Column(
3117+
children: <Widget>[
3118+
PopupMenuButton<void>(
3119+
key: popupButtonKey,
3120+
itemBuilder: (BuildContext context) {
3121+
return <PopupMenuEntry<void>>[
3122+
const PopupMenuItem<void>(
3123+
height: 1000,
3124+
child: Text('Example'),
3125+
),
3126+
];
3127+
},
3128+
),
3129+
],
3130+
),
3131+
),
3132+
)
3133+
);
3134+
3135+
await tester.tap(find.byKey(popupButtonKey));
3136+
await tester.pumpAndSettle();
3137+
3138+
expect(find.byType(Scrollbar), findsOneWidget);
3139+
// Test Scrollbar thumb color.
3140+
expect(
3141+
find.byType(Scrollbar),
3142+
paints..rrect(color: const Color(0xffff0000)),
3143+
);
3144+
3145+
// Close the menu.
3146+
await tester.tapAt(const Offset(20.0, 20.0));
3147+
await tester.pumpAndSettle();
3148+
3149+
// Test local ScrollbarTheme overrides global ScrollbarTheme.
3150+
await tester.pumpWidget(
3151+
MaterialApp(
3152+
theme: ThemeData(
3153+
scrollbarTheme: scrollbarTheme,
3154+
useMaterial3: true,
3155+
),
3156+
home: Material(
3157+
child: Column(
3158+
children: <Widget>[
3159+
ScrollbarTheme(
3160+
data: scrollbarTheme.copyWith(
3161+
thumbColor: const MaterialStatePropertyAll<Color?>(Color(0xff0000ff)),
3162+
),
3163+
child: PopupMenuButton<void>(
3164+
key: popupButtonKey,
3165+
itemBuilder: (BuildContext context) {
3166+
return <PopupMenuEntry<void>>[
3167+
const PopupMenuItem<void>(
3168+
height: 1000,
3169+
child: Text('Example'),
3170+
),
3171+
];
3172+
},
3173+
),
3174+
),
3175+
],
3176+
),
3177+
),
3178+
)
3179+
);
3180+
await tester.tap(find.byKey(popupButtonKey));
3181+
await tester.pumpAndSettle();
3182+
3183+
expect(find.byType(Scrollbar), findsOneWidget);
3184+
// Scrollbar thumb color should be updated.
3185+
expect(
3186+
find.byType(Scrollbar),
3187+
paints..rrect(color: const Color(0xff0000ff)),
3188+
);
3189+
}, variant: TargetPlatformVariant.desktop());
31013190
}
31023191

31033192
class TestApp extends StatelessWidget {

0 commit comments

Comments
 (0)