mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
fixes isAlwaysShown material scrollbar.dart (#54128)
This commit is contained in:
parent
8cb6d5edbf
commit
4f0c82b7a3
|
@ -238,15 +238,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
|
|||
..color = CupertinoDynamicColor.resolve(_kScrollbarColor, context)
|
||||
..padding = MediaQuery.of(context).padding;
|
||||
}
|
||||
WidgetsBinding.instance.addPostFrameCallback((Duration duration) {
|
||||
if (widget.isAlwaysShown) {
|
||||
assert(widget.controller != null);
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
_triggerScrollbar();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -254,7 +246,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
|
|||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.isAlwaysShown != oldWidget.isAlwaysShown) {
|
||||
if (widget.isAlwaysShown == true) {
|
||||
assert(widget.controller != null);
|
||||
_triggerScrollbar();
|
||||
_fadeoutAnimationController.animateTo(1.0);
|
||||
} else {
|
||||
_fadeoutAnimationController.reverse();
|
||||
|
@ -278,6 +270,19 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> 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.
|
||||
void _triggerScrollbar() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((Duration duration) {
|
||||
if (widget.isAlwaysShown) {
|
||||
assert(widget.controller != null);
|
||||
_fadeoutTimer?.cancel();
|
||||
widget.controller.position.didUpdateScrollPositionBy(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Handle a gesture that drags the scrollbar by the given amount.
|
||||
void _dragScrollbar(double primaryDelta) {
|
||||
assert(_currentController != null);
|
||||
|
|
|
@ -106,15 +106,7 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin {
|
|||
_textDirection = Directionality.of(context);
|
||||
_materialPainter = _buildMaterialScrollbarPainter();
|
||||
_useCupertinoScrollbar = false;
|
||||
WidgetsBinding.instance.addPostFrameCallback((Duration duration) {
|
||||
if (widget.isAlwaysShown) {
|
||||
assert(widget.controller != null);
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
_triggerScrollbar();
|
||||
break;
|
||||
}
|
||||
assert(_useCupertinoScrollbar != null);
|
||||
|
@ -124,15 +116,28 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin {
|
|||
void didUpdateWidget(Scrollbar oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.isAlwaysShown != oldWidget.isAlwaysShown) {
|
||||
assert(widget.controller != null);
|
||||
if (widget.isAlwaysShown == false) {
|
||||
_fadeoutAnimationController.reverse();
|
||||
} else {
|
||||
_triggerScrollbar();
|
||||
_fadeoutAnimationController.animateTo(1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
void _triggerScrollbar() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((Duration duration) {
|
||||
if (widget.isAlwaysShown) {
|
||||
assert(widget.controller != null);
|
||||
_fadeoutTimer?.cancel();
|
||||
widget.controller.position.didUpdateScrollPositionBy(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ScrollbarPainter _buildMaterialScrollbarPainter() {
|
||||
return ScrollbarPainter(
|
||||
color: _themeColor,
|
||||
|
|
|
@ -286,6 +286,59 @@ void main() {
|
|||
expect(find.byType(CupertinoScrollbar), isNot(paints..rrect()));
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'With isAlwaysShown: false, set isAlwaysShown: true. The thumb should be always shown directly',
|
||||
(WidgetTester tester) async {
|
||||
final ScrollController controller = ScrollController();
|
||||
bool isAlwaysShown = false;
|
||||
Widget viewWithScroll() {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(),
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
CupertinoScrollbar(
|
||||
isAlwaysShown: isAlwaysShown,
|
||||
controller: controller,
|
||||
child: SingleChildScrollView(
|
||||
controller: controller,
|
||||
child: const SizedBox(
|
||||
width: 4000.0,
|
||||
height: 4000.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 10,
|
||||
child: CupertinoButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isAlwaysShown = !isAlwaysShown;
|
||||
});
|
||||
},
|
||||
child: const Text('change isAlwaysShown'),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(viewWithScroll());
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(CupertinoScrollbar), isNot(paints..rrect()));
|
||||
|
||||
await tester.tap(find.byType(CupertinoButton));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(CupertinoScrollbar), paints..rrect());
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'With isAlwaysShown: false, fling a scroll. While it is still scrolling, set isAlwaysShown: true. The thumb should not fade even after the scrolling stops',
|
||||
(WidgetTester tester) async {
|
||||
|
@ -332,6 +385,7 @@ void main() {
|
|||
|
||||
await tester.pumpWidget(viewWithScroll());
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(CupertinoScrollbar), isNot(paints..rrect()));
|
||||
await tester.fling(
|
||||
find.byType(SingleChildScrollView),
|
||||
const Offset(0.0, -10.0),
|
||||
|
@ -340,7 +394,13 @@ void main() {
|
|||
expect(find.byType(CupertinoScrollbar), paints..rrect());
|
||||
|
||||
await tester.tap(find.byType(CupertinoButton));
|
||||
await tester.pump();
|
||||
expect(find.byType(CupertinoScrollbar), paints..rrect());
|
||||
|
||||
// Wait for the timer delay to expire.
|
||||
await tester.pump(const Duration(milliseconds: 600)); // _kScrollbarTimeToFade
|
||||
await tester.pumpAndSettle();
|
||||
// Scrollbar thumb is showing after scroll finishes and timer ends.
|
||||
expect(find.byType(CupertinoScrollbar), paints..rrect());
|
||||
});
|
||||
|
||||
|
|
|
@ -308,6 +308,54 @@ void main() {
|
|||
expect(find.byType(Scrollbar), isNot(paints..rect()));
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'With isAlwaysShown: false, set isAlwaysShown: true. The thumb should be always shown directly',
|
||||
(WidgetTester tester) async {
|
||||
final ScrollController controller = ScrollController();
|
||||
bool isAlwaysShown = false;
|
||||
Widget viewWithScroll() {
|
||||
return _buildBoilerplate(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Theme(
|
||||
data: ThemeData(),
|
||||
child: Scaffold(
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: const Icon(Icons.threed_rotation),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isAlwaysShown = !isAlwaysShown;
|
||||
});
|
||||
},
|
||||
),
|
||||
body: Scrollbar(
|
||||
isAlwaysShown: isAlwaysShown,
|
||||
controller: controller,
|
||||
child: SingleChildScrollView(
|
||||
controller: controller,
|
||||
child: const SizedBox(
|
||||
width: 4000.0,
|
||||
height: 4000.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(viewWithScroll());
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(Scrollbar), isNot(paints..rect()));
|
||||
|
||||
await tester.tap(find.byType(FloatingActionButton));
|
||||
await tester.pumpAndSettle();
|
||||
// Scrollbar is not showing after scroll finishes
|
||||
expect(find.byType(Scrollbar), paints..rect());
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'With isAlwaysShown: false, fling a scroll. While it is still scrolling, set isAlwaysShown: true. The thumb should not fade even after the scrolling stops',
|
||||
(WidgetTester tester) async {
|
||||
|
@ -348,6 +396,7 @@ void main() {
|
|||
|
||||
await tester.pumpWidget(viewWithScroll());
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(Scrollbar), isNot(paints..rect()));
|
||||
await tester.fling(
|
||||
find.byType(SingleChildScrollView),
|
||||
const Offset(0.0, -10.0),
|
||||
|
@ -356,8 +405,13 @@ void main() {
|
|||
expect(find.byType(Scrollbar), paints..rect());
|
||||
|
||||
await tester.tap(find.byType(FloatingActionButton));
|
||||
await tester.pump();
|
||||
expect(find.byType(Scrollbar), paints..rect());
|
||||
|
||||
// Wait for the timer delay to expire.
|
||||
await tester.pump(const Duration(milliseconds: 600)); // _kScrollbarTimeToFade
|
||||
await tester.pumpAndSettle();
|
||||
// Scrollbar is not showing after scroll finishes
|
||||
// Scrollbar thumb is showing after scroll finishes and timer ends.
|
||||
expect(find.byType(Scrollbar), paints..rect());
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue