Fix a scrollbar crash bug (#92657)
This commit is contained in:
parent
f51b9090dc
commit
765fbe66a7
@ -607,6 +607,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
|
|||||||
return _paintScrollbar(canvas, size, thumbExtent, _lastAxisDirection!);
|
return _paintScrollbar(canvas, size, thumbExtent, _lastAxisDirection!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get _lastMetricsAreScrollable => _lastMetrics!.minScrollExtent != _lastMetrics!.maxScrollExtent;
|
||||||
|
|
||||||
/// Same as hitTest, but includes some padding when the [PointerEvent] is
|
/// Same as hitTest, but includes some padding when the [PointerEvent] is
|
||||||
/// caused by [PointerDeviceKind.touch] to make sure that the region
|
/// caused by [PointerDeviceKind.touch] to make sure that the region
|
||||||
/// isn't too small to be interacted with by the user.
|
/// isn't too small to be interacted with by the user.
|
||||||
@ -617,12 +619,16 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
|
|||||||
/// based on proximity. When `forHover` is true, the larger hit test area will
|
/// based on proximity. When `forHover` is true, the larger hit test area will
|
||||||
/// be used.
|
/// be used.
|
||||||
bool hitTestInteractive(Offset position, PointerDeviceKind kind, { bool forHover = false }) {
|
bool hitTestInteractive(Offset position, PointerDeviceKind kind, { bool forHover = false }) {
|
||||||
if (_thumbRect == null) {
|
if (_trackRect == null) {
|
||||||
// We have not computed the scrollbar position yet.
|
// We have not computed the scrollbar position yet.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Rect interactiveRect = _trackRect ?? _thumbRect!;
|
if (!_lastMetricsAreScrollable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Rect interactiveRect = _trackRect!;
|
||||||
final Rect paddedRect = interactiveRect.expandToInclude(
|
final Rect paddedRect = interactiveRect.expandToInclude(
|
||||||
Rect.fromCircle(center: _thumbRect!.center, radius: _kMinInteractiveSize / 2),
|
Rect.fromCircle(center: _thumbRect!.center, radius: _kMinInteractiveSize / 2),
|
||||||
);
|
);
|
||||||
@ -658,6 +664,10 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_lastMetricsAreScrollable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case PointerDeviceKind.touch:
|
case PointerDeviceKind.touch:
|
||||||
final Rect touchThumbRect = _thumbRect!.expandToInclude(
|
final Rect touchThumbRect = _thumbRect!.expandToInclude(
|
||||||
@ -682,6 +692,11 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
|
|||||||
if (fadeoutOpacityAnimation.value == 0.0) {
|
if (fadeoutOpacityAnimation.value == 0.0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_lastMetricsAreScrollable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return _thumbRect!.contains(position!);
|
return _thumbRect!.contains(position!);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1347,6 +1362,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
|||||||
void _updateScrollPosition(Offset updatedOffset) {
|
void _updateScrollPosition(Offset updatedOffset) {
|
||||||
assert(_currentController != null);
|
assert(_currentController != null);
|
||||||
assert(_dragScrollbarAxisOffset != null);
|
assert(_dragScrollbarAxisOffset != null);
|
||||||
|
|
||||||
final ScrollPosition position = _currentController!.position;
|
final ScrollPosition position = _currentController!.position;
|
||||||
late double primaryDelta;
|
late double primaryDelta;
|
||||||
switch (position.axisDirection) {
|
switch (position.axisDirection) {
|
||||||
|
@ -2038,6 +2038,43 @@ void main() {
|
|||||||
expect(depths[1], 0);
|
expect(depths[1], 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/92262
|
||||||
|
testWidgets('Do not crash when resize from scrollable to non-scrollable.', (WidgetTester tester) async {
|
||||||
|
final ScrollController scrollController = ScrollController();
|
||||||
|
Widget buildFrame(double height) {
|
||||||
|
return Directionality(
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
child: MediaQuery(
|
||||||
|
data: const MediaQueryData(),
|
||||||
|
child: RawScrollbar(
|
||||||
|
controller: scrollController,
|
||||||
|
interactive: true,
|
||||||
|
isAlwaysShown: true,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
controller: scrollController,
|
||||||
|
child: Container(
|
||||||
|
width: 100.0,
|
||||||
|
height: height,
|
||||||
|
color: const Color(0xFF000000),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await tester.pumpWidget(buildFrame(700.0));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(600.0));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Try to drag the thumb.
|
||||||
|
final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(798.0, 5.0));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await dragScrollbarGesture.moveBy(const Offset(0.0, 5.0));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
});
|
||||||
|
|
||||||
test('ScrollbarPainter.shouldRepaint returns true when any of the properties changes', () {
|
test('ScrollbarPainter.shouldRepaint returns true when any of the properties changes', () {
|
||||||
ScrollbarPainter createPainter({
|
ScrollbarPainter createPainter({
|
||||||
Color color = const Color(0xFF000000),
|
Color color = const Color(0xFF000000),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user