Unverified Commit b145a533 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Remove Scrollbar.isAlwaysShown assert based on Scrollbar.controller (#72316)

parent 8db2d853
......@@ -561,10 +561,11 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
/// visible.
///
/// By default, the thumb will fade in and out as the child scroll view
/// scrolls. When [isAlwaysShown] is true, and a [controller] is specified, the
/// scrollbar thumb will remain visible without the fade animation.
/// scrolls. When [isAlwaysShown] is true, the scrollbar thumb will remain
/// visible without the fade animation. This requires that a [ScrollController]
/// is provided to [controller], or that the [PrimaryScrollController] is available.
///
/// Scrollbars are interactive and will use the [PrimaryScrollController] if
/// Scrollbars are interactive and will also use the [PrimaryScrollController] if
/// a [controller] is not set. Scrollbar thumbs can be dragged along the main axis
/// of the [ScrollView] to change the [ScrollPosition]. Tapping along the track
/// exclusive of the thumb will trigger a [ScrollIncrementType.page] based on
......@@ -606,10 +607,7 @@ class RawScrollbar extends StatefulWidget {
this.fadeDuration = _kScrollbarFadeDuration,
this.timeToFade = _kScrollbarTimeToFade,
this.pressDuration = Duration.zero,
}) : assert(
!isAlwaysShown || controller != null,
'When isAlwaysShown is true, a ScrollController must be provided.',
),
}) : assert(isAlwaysShown != null),
assert(child != null),
assert(fadeDuration != null),
assert(timeToFade != null),
......@@ -681,8 +679,9 @@ class RawScrollbar extends StatefulWidget {
/// When false, the scrollbar will be shown during scrolling
/// and will fade out otherwise.
///
/// When true, the scrollbar will always be visible and never fade out. The
/// [controller] property must be set in this case.
/// When true, the scrollbar will always be visible and never fade out. If the
/// [controller] property has not been set, the [PrimaryScrollController] will
/// be used.
///
/// Defaults to false.
///
......@@ -826,7 +825,13 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
// Wait one frame and cause an empty scroll event. This allows the
// thumb to show immediately when isAlwaysShown is true. A scroll
// event is required in order to paint the thumb.
widget.controller!.position.didUpdateScrollPositionBy(0);
final ScrollController? scrollController = widget.controller ?? PrimaryScrollController.of(context);
assert(
scrollController != null,
'A ScrollController is required when Scrollbar.isAlwaysShown is true. '
'Either Scrollbar.controller was not provided, or a PrimaryScrollController could not be found.',
);
scrollController!.position.didUpdateScrollPositionBy(0);
}
});
}
......
......@@ -263,16 +263,16 @@ void main() {
await tester.pump(_kScrollbarFadeDuration);
});
testWidgets('When isAlwaysShown is true, must pass a controller',
testWidgets('When isAlwaysShown is true, must pass a controller or find PrimaryScrollController',
(WidgetTester tester) async {
Widget viewWithScroll() {
return Directionality(
return const Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: const MediaQueryData(),
data: MediaQueryData(),
child: CupertinoScrollbar(
isAlwaysShown: true,
child: const SingleChildScrollView(
child: SingleChildScrollView(
child: SizedBox(
width: 4000.0,
height: 4000.0,
......@@ -283,12 +283,12 @@ void main() {
);
}
expect(() async {
await tester.pumpWidget(viewWithScroll());
}, throwsAssertionError);
await tester.pumpWidget(viewWithScroll());
final dynamic exception = tester.takeException();
expect(exception, isAssertionError);
});
testWidgets('When isAlwaysShown is true, must pass a controller that is attached to a scroll view',
testWidgets('When isAlwaysShown is true, must pass a controller or find PrimarySCrollController that is attached to a scroll view',
(WidgetTester tester) async {
final ScrollController controller = ScrollController();
Widget viewWithScroll() {
......@@ -315,6 +315,39 @@ void main() {
expect(exception, isAssertionError);
});
testWidgets('On first render with isAlwaysShown: true, the thumb shows with PrimaryScrollController', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
Widget viewWithScroll() {
return Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: const MediaQueryData(),
child: PrimaryScrollController(
controller: controller,
child: Builder(
builder: (BuildContext context) {
return const CupertinoScrollbar(
isAlwaysShown: true,
child: SingleChildScrollView(
primary: true,
child: SizedBox(
width: 4000.0,
height: 4000.0,
),
),
);
},
),
),
),
);
}
await tester.pumpWidget(viewWithScroll());
await tester.pumpAndSettle();
expect(find.byType(CupertinoScrollbar), paints..rect());
});
testWidgets('On first render with isAlwaysShown: true, the thumb shows',
(WidgetTester tester) async {
final ScrollController controller = ScrollController();
......
......@@ -122,15 +122,15 @@ void main() {
expect(canvas.invocations.isEmpty, isTrue);
});
testWidgets('When isAlwaysShown is true, must pass a controller',
testWidgets('When isAlwaysShown is true, must pass a controller or find PrimaryScrollController',
(WidgetTester tester) async {
Widget viewWithScroll() {
return _buildBoilerplate(
child: Theme(
data: ThemeData(),
child: Scrollbar(
child: const Scrollbar(
isAlwaysShown: true,
child: const SingleChildScrollView(
child: SingleChildScrollView(
child: SizedBox(
width: 4000.0,
height: 4000.0,
......@@ -141,12 +141,12 @@ void main() {
);
}
expect(() async {
await tester.pumpWidget(viewWithScroll());
}, throwsAssertionError);
await tester.pumpWidget(viewWithScroll());
final dynamic exception = tester.takeException();
expect(exception, isAssertionError);
});
testWidgets('When isAlwaysShown is true, must pass a controller that is attached to a scroll view',
testWidgets('When isAlwaysShown is true, must pass a controller that is attached to a scroll view or find PrimaryScrollController',
(WidgetTester tester) async {
final ScrollController controller = ScrollController();
Widget viewWithScroll() {
......@@ -199,6 +199,38 @@ void main() {
expect(find.byType(Scrollbar), paints..rect());
});
testWidgets('On first render with isAlwaysShown: true, the thumb shows with PrimaryScrollController', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
Widget viewWithScroll() {
return _buildBoilerplate(
child: Theme(
data: ThemeData(),
child: PrimaryScrollController(
controller: controller,
child: Builder(
builder: (BuildContext context) {
return const Scrollbar(
isAlwaysShown: true,
child: SingleChildScrollView(
primary: true,
child: SizedBox(
width: 4000.0,
height: 4000.0,
),
),
);
},
),
),
),
);
}
await tester.pumpWidget(viewWithScroll());
await tester.pumpAndSettle();
expect(find.byType(Scrollbar), paints..rect());
});
testWidgets('On first render with isAlwaysShown: false, the thumb is hidden',
(WidgetTester tester) async {
final ScrollController controller = ScrollController();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment