update ScrollMetricsNotification (#87421)
This commit is contained in:
@@ -558,7 +558,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
|
||||
// It isn't safe to trigger the ScrollMetricsNotification if we are in
|
||||
// the middle of rendering the frame, the developer is likely to schedule
|
||||
// a new frame(build scheduled during frame is illegal).
|
||||
if (_lastMetrics != null && !_haveScheduledUpdateNotification) {
|
||||
if (!_haveScheduledUpdateNotification) {
|
||||
scheduleMicrotask(didUpdateScrollMetrics);
|
||||
_haveScheduledUpdateNotification = true;
|
||||
}
|
||||
|
||||
@@ -1224,25 +1224,16 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_maybeTriggerScrollbar();
|
||||
assert(_debugScheduleCheckHasValidScrollPosition());
|
||||
}
|
||||
|
||||
// Waits one frame and cause an empty scroll event (zero delta pixels).
|
||||
//
|
||||
// This allows the thumb to show immediately when isAlwaysShown is true.
|
||||
// A scroll event is required in order to paint the thumb.
|
||||
void _maybeTriggerScrollbar() {
|
||||
bool _debugScheduleCheckHasValidScrollPosition() {
|
||||
if (!showScrollbar)
|
||||
return true;
|
||||
WidgetsBinding.instance!.addPostFrameCallback((Duration duration) {
|
||||
final ScrollController? scrollController = widget.controller ?? PrimaryScrollController.of(context);
|
||||
if (showScrollbar) {
|
||||
_fadeoutTimer?.cancel();
|
||||
// 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.
|
||||
assert(_debugCheckHasValidScrollPosition());
|
||||
scrollController!.position.didUpdateScrollPositionBy(0);
|
||||
}
|
||||
assert(_debugCheckHasValidScrollPosition());
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
void _validateInteractions(AnimationStatus status) {
|
||||
@@ -1365,7 +1356,8 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.isAlwaysShown != oldWidget.isAlwaysShown) {
|
||||
if (widget.isAlwaysShown == true) {
|
||||
_maybeTriggerScrollbar();
|
||||
assert(_debugScheduleCheckHasValidScrollPosition());
|
||||
_fadeoutTimer?.cancel();
|
||||
_fadeoutAnimationController.animateTo(1.0);
|
||||
} else {
|
||||
_fadeoutAnimationController.reverse();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
@@ -389,9 +390,16 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
final FlutterExceptionHandler? handler = FlutterError.onError;
|
||||
FlutterErrorDetails? error;
|
||||
FlutterError.onError = (FlutterErrorDetails details) {
|
||||
error = details;
|
||||
};
|
||||
|
||||
await tester.pumpWidget(viewWithScroll());
|
||||
final AssertionError exception = tester.takeException() as AssertionError;
|
||||
expect(exception, isAssertionError);
|
||||
expect(error, isNotNull);
|
||||
|
||||
FlutterError.onError = handler;
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -21,8 +21,9 @@ void main() {
|
||||
);
|
||||
}
|
||||
await tester.pumpWidget(buildFrame(1200.0));
|
||||
expect(events.length, 0);
|
||||
expect(events.length, 1);
|
||||
|
||||
events.clear();
|
||||
await tester.pumpWidget(buildFrame(1000.0));
|
||||
// Change the content dimensions will trigger a new event.
|
||||
expect(events.length, 1);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/src/physics/utils.dart' show nearEqual;
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@@ -1143,6 +1144,12 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('RawScrollbar.isAlwaysShown asserts that a ScrollPosition is attached', (WidgetTester tester) async {
|
||||
final FlutterExceptionHandler? handler = FlutterError.onError;
|
||||
FlutterErrorDetails? error;
|
||||
FlutterError.onError = (FlutterErrorDetails details) {
|
||||
error = details;
|
||||
};
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
@@ -1163,12 +1170,15 @@ void main() {
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
final AssertionError exception = tester.takeException() as AssertionError;
|
||||
expect(exception, isAssertionError);
|
||||
|
||||
expect(error, isNotNull);
|
||||
final AssertionError exception = error!.exception as AssertionError;
|
||||
expect(
|
||||
exception.message,
|
||||
contains("The Scrollbar's ScrollController has no ScrollPosition attached."),
|
||||
);
|
||||
|
||||
FlutterError.onError = handler;
|
||||
});
|
||||
|
||||
testWidgets('Interactive scrollbars should have a valid scroll controller', (WidgetTester tester) async {
|
||||
|
||||
Reference in New Issue
Block a user