| // 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 'dart:ui' as ui; |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/material.dart'; |
| import 'package:flutter/rendering.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| import '../rendering/mock_canvas.dart'; |
| |
| // The const represents the starting position of the scrollbar thumb for |
| // the below tests. The thumb is 90 pixels long, and 8 pixels wide, with a 2 |
| // pixel margin to the right edge of the viewport. |
| const Rect _kMaterialDesignInitialThumbRect = Rect.fromLTRB(790.0, 0.0, 798.0, 90.0); |
| const Radius _kDefaultThumbRadius = Radius.circular(8.0); |
| const Color _kDefaultIdleThumbColor = Color(0x1a000000); |
| const Color _kDefaultDragThumbColor = Color(0x99000000); |
| |
| void main() { |
| test('ScrollbarThemeData copyWith, ==, hashCode basics', () { |
| expect(const ScrollbarThemeData(), const ScrollbarThemeData().copyWith()); |
| expect(const ScrollbarThemeData().hashCode, const ScrollbarThemeData().copyWith().hashCode); |
| }); |
| |
| testWidgets('Passing no ScrollbarTheme returns defaults', (WidgetTester tester) async { |
| final ScrollController scrollController = ScrollController(); |
| await tester.pumpWidget( |
| MaterialApp( |
| home: ScrollConfiguration( |
| behavior: const NoScrollbarBehavior(), |
| child: Scrollbar( |
| isAlwaysShown: true, |
| showTrackOnHover: true, |
| controller: scrollController, |
| child: SingleChildScrollView( |
| controller: scrollController, |
| child: const SizedBox(width: 4000.0, height: 4000.0), |
| ), |
| ), |
| ), |
| ), |
| ); |
| await tester.pumpAndSettle(); |
| // Idle scrollbar behavior |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| _kMaterialDesignInitialThumbRect, |
| _kDefaultThumbRadius, |
| ), |
| color: _kDefaultIdleThumbColor, |
| ), |
| ); |
| |
| // Drag scrollbar behavior |
| const double scrollAmount = 10.0; |
| final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| _kMaterialDesignInitialThumbRect, |
| _kDefaultThumbRadius, |
| ), |
| // Drag color |
| color: _kDefaultDragThumbColor, |
| ), |
| ); |
| |
| await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount)); |
| await tester.pumpAndSettle(); |
| await dragScrollbarGesture.up(); |
| await tester.pumpAndSettle(); |
| |
| // Hover scrollbar behavior |
| final TestGesture gesture = await tester.createGesture(kind: ui.PointerDeviceKind.mouse); |
| await gesture.addPointer(); |
| await gesture.moveTo(const Offset(794.0, 5.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints |
| ..rect( |
| rect: const Rect.fromLTRB(784.0, 0.0, 800.0, 600.0), |
| color: const Color(0x08000000), |
| ) |
| ..line( |
| p1: const Offset(784.0, 0.0), |
| p2: const Offset(784.0, 600.0), |
| strokeWidth: 1.0, |
| color: const Color(0x1a000000), |
| ) |
| ..rrect( |
| rrect: RRect.fromRectAndRadius( |
| // Scrollbar thumb is larger |
| const Rect.fromLTRB(786.0, 10.0, 798.0, 100.0), |
| _kDefaultThumbRadius, |
| ), |
| // Hover color |
| color: const Color(0x80000000), |
| ), |
| ); |
| }, variant: const TargetPlatformVariant(<TargetPlatform>{ |
| TargetPlatform.linux, |
| TargetPlatform.macOS, |
| TargetPlatform.windows, |
| TargetPlatform.fuchsia, |
| }), |
| ); |
| |
| testWidgets('Scrollbar uses values from ScrollbarTheme', (WidgetTester tester) async { |
| final ScrollbarThemeData scrollbarTheme = _scrollbarTheme(); |
| final ScrollController scrollController = ScrollController(); |
| await tester.pumpWidget(MaterialApp( |
| theme: ThemeData( |
| scrollbarTheme: scrollbarTheme, |
| ), |
| home: ScrollConfiguration( |
| behavior: const NoScrollbarBehavior(), |
| child: Scrollbar( |
| isAlwaysShown: true, |
| controller: scrollController, |
| child: SingleChildScrollView( |
| controller: scrollController, |
| child: const SizedBox(width: 4000.0, height: 4000.0), |
| ), |
| ), |
| ), |
| )); |
| await tester.pumpAndSettle(); |
| // Idle scrollbar behavior |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| const Rect.fromLTRB(785.0, 10.0, 795.0, 97.0), |
| const Radius.circular(6.0), |
| ), |
| color: const Color(0xff4caf50), |
| ), |
| ); |
| |
| // Drag scrollbar behavior |
| const double scrollAmount = 10.0; |
| final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| const Rect.fromLTRB(785.0, 10.0, 795.0, 97.0), |
| const Radius.circular(6.0), |
| ), |
| // Drag color |
| color: const Color(0xfff44336), |
| ), |
| ); |
| |
| await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount)); |
| await tester.pumpAndSettle(); |
| await dragScrollbarGesture.up(); |
| await tester.pumpAndSettle(); |
| |
| // Hover scrollbar behavior |
| final TestGesture gesture = await tester.createGesture(kind: ui.PointerDeviceKind.mouse); |
| await gesture.addPointer(); |
| await gesture.moveTo(const Offset(794.0, 15.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints |
| ..rect( |
| rect: const Rect.fromLTRB(770.0, 0.0, 800.0, 600.0), |
| color: const Color(0xff000000), |
| ) |
| ..line( |
| p1: const Offset(770.0, 00.0), |
| p2: const Offset(770.0, 600.0), |
| strokeWidth: 1.0, |
| color: const Color(0xffffeb3b), |
| ) |
| ..rrect( |
| rrect: RRect.fromRectAndRadius( |
| // Scrollbar thumb is larger |
| const Rect.fromLTRB(775.0, 20.0, 795.0, 107.0), |
| const Radius.circular(6.0), |
| ), |
| // Hover color |
| color: const Color(0xff2196f3), |
| ), |
| ); |
| }, variant: const TargetPlatformVariant(<TargetPlatform>{ |
| TargetPlatform.linux, |
| TargetPlatform.macOS, |
| TargetPlatform.windows, |
| TargetPlatform.fuchsia, |
| }), |
| ); |
| |
| testWidgets( |
| 'Scrollbar uses values from ScrollbarTheme if exists instead of values from Theme', |
| (WidgetTester tester) async { |
| final ScrollbarThemeData scrollbarTheme = _scrollbarTheme(); |
| final ScrollController scrollController = ScrollController(); |
| await tester.pumpWidget( |
| MaterialApp( |
| theme: ThemeData( |
| scrollbarTheme: scrollbarTheme, |
| ), |
| home: ScrollConfiguration( |
| behavior: const NoScrollbarBehavior(), |
| child: ScrollbarTheme( |
| data: _scrollbarTheme().copyWith( |
| thumbColor: MaterialStateProperty.all(const Color(0xFF000000)), |
| ), |
| child: Scrollbar( |
| thumbVisibility: true, |
| controller: scrollController, |
| child: SingleChildScrollView( |
| controller: scrollController, |
| child: const SizedBox(width: 4000.0, height: 4000.0), |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| await tester.pumpAndSettle(); |
| // Idle scrollbar behavior |
| expect( |
| find.byType(Scrollbar), |
| paints |
| ..rrect( |
| rrect: RRect.fromRectAndRadius( |
| const Rect.fromLTRB(785.0, 10.0, 795.0, 97.0), |
| const Radius.circular(6.0), |
| ), |
| color: const Color(0xFF000000), |
| ), |
| ); |
| }, |
| ); |
| |
| testWidgets('ScrollbarTheme can disable gestures', (WidgetTester tester) async { |
| final ScrollController scrollController = ScrollController(); |
| await tester.pumpWidget(MaterialApp( |
| theme: ThemeData(scrollbarTheme: const ScrollbarThemeData(interactive: false)), |
| home: Scrollbar( |
| isAlwaysShown: true, |
| controller: scrollController, |
| child: SingleChildScrollView( |
| controller: scrollController, |
| child: const SizedBox(width: 4000.0, height: 4000.0), |
| ), |
| ), |
| )); |
| await tester.pumpAndSettle(); |
| // Idle scrollbar behavior |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| _kMaterialDesignInitialThumbRect, |
| _kDefaultThumbRadius, |
| ), |
| color: _kDefaultIdleThumbColor, |
| ), |
| ); |
| |
| // Try to drag scrollbar. |
| const double scrollAmount = 10.0; |
| final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0)); |
| await tester.pumpAndSettle(); |
| await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount)); |
| await tester.pumpAndSettle(); |
| await dragScrollbarGesture.up(); |
| await tester.pumpAndSettle(); |
| // Expect no change |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| _kMaterialDesignInitialThumbRect, |
| _kDefaultThumbRadius, |
| ), |
| color: _kDefaultIdleThumbColor, |
| ), |
| ); |
| }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.fuchsia })); |
| |
| testWidgets('Scrollbar.interactive takes priority over ScrollbarTheme', (WidgetTester tester) async { |
| final ScrollController scrollController = ScrollController(); |
| await tester.pumpWidget(MaterialApp( |
| theme: ThemeData(scrollbarTheme: const ScrollbarThemeData(interactive: false)), |
| home: Scrollbar( |
| interactive: true, |
| isAlwaysShown: true, |
| controller: scrollController, |
| child: SingleChildScrollView( |
| controller: scrollController, |
| child: const SizedBox(width: 4000.0, height: 4000.0), |
| ), |
| ), |
| )); |
| await tester.pumpAndSettle(); |
| // Idle scrollbar behavior |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| _kMaterialDesignInitialThumbRect, |
| _kDefaultThumbRadius, |
| ), |
| color: _kDefaultIdleThumbColor, |
| ), |
| ); |
| |
| // Drag scrollbar. |
| const double scrollAmount = 10.0; |
| final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0)); |
| await tester.pumpAndSettle(); |
| await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount)); |
| await tester.pumpAndSettle(); |
| await dragScrollbarGesture.up(); |
| await tester.pumpAndSettle(); |
| // Gestures handled by Scrollbar. |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| const Rect.fromLTRB(790.0, 10.0, 798.0, 100.0), |
| _kDefaultThumbRadius, |
| ), |
| color: _kDefaultIdleThumbColor, |
| ), |
| ); |
| }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.fuchsia })); |
| |
| testWidgets('Scrollbar widget properties take priority over theme', (WidgetTester tester) async { |
| const double thickness = 4.0; |
| const double hoverThickness = 4.0; |
| const bool showTrackOnHover = true; |
| const Radius radius = Radius.circular(3.0); |
| final ScrollController scrollController = ScrollController(); |
| |
| await tester.pumpWidget( |
| MaterialApp( |
| theme: ThemeData( |
| colorScheme: const ColorScheme.light(), |
| ), |
| home: ScrollConfiguration( |
| behavior: const NoScrollbarBehavior(), |
| child: Scrollbar( |
| thickness: thickness, |
| hoverThickness: hoverThickness, |
| thumbVisibility: true, |
| showTrackOnHover: showTrackOnHover, |
| radius: radius, |
| controller: scrollController, |
| child: SingleChildScrollView( |
| controller: scrollController, |
| child: const SizedBox(width: 4000.0, height: 4000.0), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pumpAndSettle(); |
| // Idle scrollbar behavior |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| const Rect.fromLTRB(794.0, 0.0, 798.0, 90.0), |
| const Radius.circular(3.0), |
| ), |
| color: _kDefaultIdleThumbColor, |
| ), |
| ); |
| |
| // Drag scrollbar behavior |
| const double scrollAmount = 10.0; |
| final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| const Rect.fromLTRB(794.0, 0.0, 798.0, 90.0), |
| const Radius.circular(3.0), |
| ), |
| // Drag color |
| color: _kDefaultDragThumbColor, |
| ), |
| ); |
| |
| await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount)); |
| await tester.pumpAndSettle(); |
| await dragScrollbarGesture.up(); |
| await tester.pumpAndSettle(); |
| |
| // Hover scrollbar behavior |
| final TestGesture gesture = await tester.createGesture(kind: ui.PointerDeviceKind.mouse); |
| await gesture.addPointer(); |
| await gesture.moveTo(const Offset(794.0, 5.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints |
| ..rect( |
| rect: const Rect.fromLTRB(792.0, 0.0, 800.0, 600.0), |
| color: const Color(0x08000000), |
| ) |
| ..line( |
| p1: const Offset(792.0, 0.0), |
| p2: const Offset(792.0, 600.0), |
| strokeWidth: 1.0, |
| color: const Color(0x1a000000), |
| ) |
| ..rrect( |
| rrect: RRect.fromRectAndRadius( |
| // Scrollbar thumb is larger |
| const Rect.fromLTRB(794.0, 10.0, 798.0, 100.0), |
| const Radius.circular(3.0), |
| ), |
| // Hover color |
| color: const Color(0x80000000), |
| ), |
| ); |
| }, variant: const TargetPlatformVariant(<TargetPlatform>{ |
| TargetPlatform.linux, |
| TargetPlatform.macOS, |
| TargetPlatform.windows, |
| TargetPlatform.fuchsia, |
| }), |
| ); |
| |
| testWidgets('ThemeData colorScheme is used when no ScrollbarTheme is set', (WidgetTester tester) async { |
| Widget buildFrame(ThemeData appTheme) { |
| final ScrollController scrollController = ScrollController(); |
| return MaterialApp( |
| theme: appTheme, |
| home: ScrollConfiguration( |
| behavior: const NoScrollbarBehavior(), |
| child: Scrollbar( |
| isAlwaysShown: true, |
| showTrackOnHover: true, |
| controller: scrollController, |
| child: SingleChildScrollView( |
| controller: scrollController, |
| child: const SizedBox(width: 4000.0, height: 4000.0), |
| ), |
| ), |
| ), |
| ); |
| } |
| |
| // Scrollbar defaults for light themes: |
| // - coloring based on ColorScheme.onSurface |
| await tester.pumpWidget(buildFrame(ThemeData( |
| colorScheme: const ColorScheme.light(), |
| ))); |
| await tester.pumpAndSettle(); |
| // Idle scrollbar behavior |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| _kMaterialDesignInitialThumbRect, |
| _kDefaultThumbRadius, |
| ), |
| color: _kDefaultIdleThumbColor, |
| ), |
| ); |
| |
| // Drag scrollbar behavior |
| const double scrollAmount = 10.0; |
| TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| _kMaterialDesignInitialThumbRect, |
| _kDefaultThumbRadius, |
| ), |
| // Drag color |
| color: _kDefaultDragThumbColor, |
| ), |
| ); |
| |
| await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount)); |
| await tester.pumpAndSettle(); |
| await dragScrollbarGesture.up(); |
| await tester.pumpAndSettle(); |
| |
| // Hover scrollbar behavior |
| final TestGesture hoverGesture = await tester.createGesture(kind: ui.PointerDeviceKind.mouse); |
| await hoverGesture.addPointer(); |
| addTearDown(hoverGesture.removePointer); |
| await hoverGesture.moveTo(const Offset(794.0, 5.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints |
| ..rect( |
| rect: const Rect.fromLTRB(784.0, 0.0, 800.0, 600.0), |
| color: const Color(0x08000000), |
| ) |
| ..line( |
| p1: const Offset(784.0, 0.0), |
| p2: const Offset(784.0, 600.0), |
| strokeWidth: 1.0, |
| color: const Color(0x1a000000), |
| ) |
| ..rrect( |
| rrect: RRect.fromRectAndRadius( |
| // Scrollbar thumb is larger |
| const Rect.fromLTRB(786.0, 10.0, 798.0, 100.0), |
| _kDefaultThumbRadius, |
| ), |
| // Hover color |
| color: const Color(0x80000000), |
| ), |
| ); |
| |
| await hoverGesture.moveTo(Offset.zero); |
| |
| // Scrollbar defaults for dark themes: |
| // - coloring slightly different based on ColorScheme.onSurface |
| await tester.pumpWidget(buildFrame(ThemeData( |
| colorScheme: const ColorScheme.dark(), |
| ))); |
| await tester.pumpAndSettle(); // Theme change animation |
| |
| // Idle scrollbar behavior |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| const Rect.fromLTRB(790.0, 10.0, 798.0, 100.0), |
| _kDefaultThumbRadius, |
| ), |
| color: const Color(0x4dffffff), |
| ), |
| ); |
| |
| // Drag scrollbar behavior |
| dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints..rrect( |
| rrect: RRect.fromRectAndRadius( |
| const Rect.fromLTRB(790.0, 10.0, 798.0, 100.0), |
| _kDefaultThumbRadius, |
| ), |
| // Drag color |
| color: const Color(0xbfffffff), |
| ), |
| ); |
| |
| await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount)); |
| await tester.pumpAndSettle(); |
| await dragScrollbarGesture.up(); |
| await tester.pumpAndSettle(); |
| |
| // Hover scrollbar behavior |
| await hoverGesture.moveTo(const Offset(794.0, 5.0)); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints |
| ..rect( |
| rect: const Rect.fromLTRB(784.0, 0.0, 800.0, 600.0), |
| color: const Color(0x0dffffff), |
| ) |
| ..line( |
| p1: const Offset(784.0, 0.0), |
| p2: const Offset(784.0, 600.0), |
| strokeWidth: 1.0, |
| color: const Color(0x40ffffff), |
| ) |
| ..rrect( |
| rrect: RRect.fromRectAndRadius( |
| // Scrollbar thumb is larger |
| const Rect.fromLTRB(786.0, 20.0, 798.0, 110.0), |
| _kDefaultThumbRadius, |
| ), |
| // Hover color |
| color: const Color(0xa6ffffff), |
| ), |
| ); |
| }, variant: const TargetPlatformVariant(<TargetPlatform>{ |
| TargetPlatform.linux, |
| TargetPlatform.macOS, |
| TargetPlatform.windows, |
| TargetPlatform.fuchsia, |
| }), |
| ); |
| |
| testWidgets('ScrollbarThemeData.trackVisibility test', (WidgetTester tester) async { |
| final ScrollController scrollController = ScrollController(); |
| bool? getTrackVisibility(Set<MaterialState> states) { |
| return true; |
| } |
| await tester.pumpWidget( |
| MaterialApp( |
| theme: ThemeData().copyWith( |
| scrollbarTheme: _scrollbarTheme( |
| trackVisibility: MaterialStateProperty.resolveWith(getTrackVisibility), |
| ), |
| ), |
| home: ScrollConfiguration( |
| behavior: const NoScrollbarBehavior(), |
| child: Scrollbar( |
| isAlwaysShown: true, |
| showTrackOnHover: true, |
| controller: scrollController, |
| child: SingleChildScrollView( |
| controller: scrollController, |
| child: const SizedBox(width: 4000.0, height: 4000.0), |
| ), |
| ), |
| ), |
| ), |
| ); |
| await tester.pumpAndSettle(); |
| |
| expect( |
| find.byType(Scrollbar), |
| paints |
| ..rect(color: const Color(0x08000000)) |
| ..line( |
| strokeWidth: 1.0, |
| color: const Color(0x1a000000), |
| ) |
| ..rrect(color: const Color(0xff4caf50)), |
| ); |
| }, variant: const TargetPlatformVariant(<TargetPlatform>{ |
| TargetPlatform.linux, |
| TargetPlatform.macOS, |
| TargetPlatform.windows, |
| TargetPlatform.fuchsia, |
| }), |
| ); |
| |
| testWidgets('Default ScrollbarTheme debugFillProperties', (WidgetTester tester) async { |
| final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); |
| const ScrollbarThemeData().debugFillProperties(builder); |
| |
| final List<String> description = builder.properties |
| .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) |
| .map((DiagnosticsNode node) => node.toString()) |
| .toList(); |
| |
| expect(description, <String>[]); |
| }); |
| |
| testWidgets('ScrollbarTheme implements debugFillProperties', (WidgetTester tester) async { |
| final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); |
| ScrollbarThemeData( |
| thickness: MaterialStateProperty.resolveWith(_getThickness), |
| showTrackOnHover: true, |
| thumbVisibility: MaterialStateProperty.resolveWith(_getThumbVisibility), |
| radius: const Radius.circular(3.0), |
| thumbColor: MaterialStateProperty.resolveWith(_getThumbColor), |
| trackColor: MaterialStateProperty.resolveWith(_getTrackColor), |
| trackBorderColor: MaterialStateProperty.resolveWith(_getTrackBorderColor), |
| crossAxisMargin: 3.0, |
| mainAxisMargin: 6.0, |
| minThumbLength: 120.0, |
| ).debugFillProperties(builder); |
| |
| final List<String> description = builder.properties |
| .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) |
| .map((DiagnosticsNode node) => node.toString()) |
| .toList(); |
| |
| expect(description, <String>[ |
| "thumbVisibility: Instance of '_MaterialStatePropertyWith<bool?>'", |
| "thickness: Instance of '_MaterialStatePropertyWith<double?>'", |
| 'showTrackOnHover: true', |
| 'radius: Radius.circular(3.0)', |
| "thumbColor: Instance of '_MaterialStatePropertyWith<Color?>'", |
| "trackColor: Instance of '_MaterialStatePropertyWith<Color?>'", |
| "trackBorderColor: Instance of '_MaterialStatePropertyWith<Color?>'", |
| 'crossAxisMargin: 3.0', |
| 'mainAxisMargin: 6.0', |
| 'minThumbLength: 120.0', |
| ]); |
| |
| // On the web, Dart doubles and ints are backed by the same kind of object because |
| // JavaScript does not support integers. So, the Dart double "4.0" is identical |
| // to "4", which results in the web evaluating to the value "4" regardless of which |
| // one is used. This results in a difference for doubles in debugFillProperties between |
| // the web and the rest of Flutter's target platforms. |
| }, skip: kIsWeb); // [intended] |
| } |
| |
| class NoScrollbarBehavior extends ScrollBehavior { |
| const NoScrollbarBehavior(); |
| |
| @override |
| Widget buildScrollbar(BuildContext context, Widget child, ScrollableDetails details) => child; |
| } |
| |
| ScrollbarThemeData _scrollbarTheme({ |
| MaterialStateProperty<double?>? thickness, |
| MaterialStateProperty<bool?>? trackVisibility, |
| bool showTrackOnHover = true, |
| MaterialStateProperty<bool?>? thumbVisibility, |
| Radius radius = const Radius.circular(6.0), |
| MaterialStateProperty<Color?>? thumbColor, |
| MaterialStateProperty<Color?>? trackColor, |
| MaterialStateProperty<Color?>? trackBorderColor, |
| double crossAxisMargin = 5.0, |
| double mainAxisMargin = 10.0, |
| double minThumbLength = 50.0, |
| }) { |
| return ScrollbarThemeData( |
| thickness: thickness ?? MaterialStateProperty.resolveWith(_getThickness), |
| trackVisibility: trackVisibility, |
| showTrackOnHover: showTrackOnHover, |
| thumbVisibility: thumbVisibility, |
| radius: radius, |
| thumbColor: thumbColor ?? MaterialStateProperty.resolveWith(_getThumbColor), |
| trackColor: trackColor ?? MaterialStateProperty.resolveWith(_getTrackColor), |
| trackBorderColor: trackBorderColor ?? MaterialStateProperty.resolveWith(_getTrackBorderColor), |
| crossAxisMargin: crossAxisMargin, |
| mainAxisMargin: mainAxisMargin, |
| minThumbLength: minThumbLength, |
| ); |
| } |
| |
| double? _getThickness(Set<MaterialState> states) { |
| if (states.contains(MaterialState.hovered)) { |
| return 20.0; |
| } |
| return 10.0; |
| } |
| |
| bool? _getThumbVisibility(Set<MaterialState> states) => true; |
| |
| Color? _getThumbColor(Set<MaterialState> states) { |
| if (states.contains(MaterialState.dragged)) { |
| return Colors.red; |
| } |
| if (states.contains(MaterialState.hovered)) { |
| return Colors.blue; |
| } |
| return Colors.green; |
| } |
| |
| Color? _getTrackColor(Set<MaterialState> states) { |
| if (states.contains(MaterialState.hovered)) { |
| return Colors.black; |
| } |
| return null; |
| } |
| |
| Color? _getTrackBorderColor(Set<MaterialState> states) { |
| if (states.contains(MaterialState.hovered)) { |
| return Colors.yellow; |
| } |
| return null; |
| } |