Unverified Commit 1c3989b8 authored by Angjie Li's avatar Angjie Li Committed by GitHub

Revert "[new feature]introduce `ScrollMetricsNotification` (#85221)" (#85466)

parent 32e6de84
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/physics.dart';
......@@ -12,7 +10,6 @@ import 'package:flutter/scheduler.dart';
import 'basic.dart';
import 'framework.dart';
import 'notification_listener.dart';
import 'page_storage.dart';
import 'scroll_activity.dart';
import 'scroll_context.dart';
......@@ -511,17 +508,6 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
ScrollMetrics? _lastMetrics;
Axis? _lastAxis;
bool _isMetricsChanged() {
assert(haveDimensions);
final ScrollMetrics currentMetrics = copyWith();
return _lastMetrics == null ||
!(currentMetrics.extentBefore == _lastMetrics!.extentBefore
&& currentMetrics.extentInside == _lastMetrics!.extentInside
&& currentMetrics.extentAfter == _lastMetrics!.extentAfter
&& currentMetrics.axisDirection == _lastMetrics!.axisDirection);
}
@override
bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) {
assert(minScrollExtent != null);
......@@ -551,14 +537,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
_pendingDimensions = false;
}
assert(!_didChangeViewportDimensionOrReceiveCorrection, 'Use correctForNewDimensions() (and return true) to change the scroll offset during applyContentDimensions().');
if (_isMetricsChanged()) {
// 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).
scheduleMicrotask(didUpdateScrollMetrics);
_lastMetrics = copyWith();
}
_lastMetrics = copyWith();
return true;
}
......@@ -919,13 +898,6 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
UserScrollNotification(metrics: copyWith(), context: context.notificationContext!, direction: direction).dispatch(context.notificationContext);
}
/// Dispatches a notification that the [ScrollMetrics] has changed.
void didUpdateScrollMetrics() {
assert(SchedulerBinding.instance!.schedulerPhase != SchedulerPhase.persistentCallbacks);
if (context.notificationContext != null)
ScrollMetricsNotification(metrics: copyWith(), context: context.notificationContext!).dispatch(context.notificationContext);
}
/// Provides a heuristic to determine if expensive frame-bound tasks should be
/// deferred.
///
......@@ -970,99 +942,3 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
description.add('viewport: ${_viewportDimension?.toStringAsFixed(1)}');
}
}
/// A notification that a scrollable widget's [ScrollMetrics] have changed.
///
/// For example, when the content of a scrollable is altered, making it larger
/// or smaller, this notification will be dispatched. Similarly, if the size
/// of the window or parent changes, the scrollable can notify of these
/// changes in dimensions.
///
/// The above behaviors usually do not trigger [ScrollNotification] events,
/// so this is useful for listening to [ScrollMetrics] changes that are not
/// caused by the user scrolling.
///
/// {@tool dartpad --template=freeform}
/// This sample shows how a [ScrollMetricsNotification] is dispatched when
/// the `windowSize` is changed. Press the floating action button to increase
/// the scrollable window's size.
///
/// ```dart main
/// import 'package:flutter/material.dart';
///
/// void main() => runApp(const ScrollMetricsDemo());
///
/// class ScrollMetricsDemo extends StatefulWidget {
/// const ScrollMetricsDemo({Key? key}) : super(key: key);
///
/// @override
/// State<ScrollMetricsDemo> createState() => ScrollMetricsDemoState();
/// }
///
/// class ScrollMetricsDemoState extends State<ScrollMetricsDemo> {
/// double windowSize = 200.0;
///
/// @override
/// Widget build(BuildContext context) {
/// return MaterialApp(
/// home: Scaffold(
/// appBar: AppBar(
/// title: const Text('ScrollMetrics Demo'),
/// ),
/// floatingActionButton: FloatingActionButton(
/// child: const Icon(Icons.add),
/// onPressed: () => setState(() {
/// windowSize += 10.0;
/// }),
/// ),
/// body: NotificationListener<ScrollMetricsNotification>(
/// onNotification: (ScrollMetricsNotification notification) {
/// ScaffoldMessenger.of(notification.context).showSnackBar(
/// const SnackBar(
/// content: Text('Scroll metrics changed!'),
/// ),
/// );
/// return false;
/// },
/// child: Scrollbar(
/// isAlwaysShown: true,
/// child: SizedBox(
/// height: windowSize,
/// width: double.infinity,
/// child: const SingleChildScrollView(
/// child: FlutterLogo(
/// size: 300.0,
/// ),
/// ),
/// ),
/// ),
/// ),
/// ),
/// );
/// }
/// }
/// ```
/// {@end-tool}
class ScrollMetricsNotification extends LayoutChangedNotification with ViewportNotificationMixin {
/// Creates a notification that the scrollable widget's [ScrollMetrics] have
/// changed.
ScrollMetricsNotification({
required this.metrics,
required this.context,
});
/// Description of a scrollable widget's [ScrollMetrics].
final ScrollMetrics metrics;
/// The build context of the widget that fired this notification.
///
/// This can be used to find the scrollable widget's render objects to
/// determine the size of the viewport, for instance.
final BuildContext context;
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('$metrics');
}
}
......@@ -7,64 +7,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('ScrollMetricsNotification test', (WidgetTester tester) async {
final List<LayoutChangedNotification> events = <LayoutChangedNotification>[];
Widget buildFrame(double height) {
return NotificationListener<LayoutChangedNotification>(
onNotification: (LayoutChangedNotification value) {
events.add(value);
return false;
},
child: SingleChildScrollView(
child: SizedBox(height: height),
),
);
}
await tester.pumpWidget(buildFrame(1200.0));
// Initial metrics notification.
expect(events.length, 1);
ScrollMetricsNotification event = events[0] as ScrollMetricsNotification;
expect(event.metrics.extentBefore, 0.0);
expect(event.metrics.extentInside, 600.0);
expect(event.metrics.extentAfter, 600.0);
events.clear();
await tester.pumpWidget(buildFrame(1000.0));
// Change the content dimensions will trigger a new event.
expect(events.length, 1);
event = events[0] as ScrollMetricsNotification;
expect(event.metrics.extentBefore, 0.0);
expect(event.metrics.extentInside, 600.0);
expect(event.metrics.extentAfter, 400.0);
events.clear();
final TestGesture gesture = await tester.startGesture(const Offset(100.0, 100.0));
expect(events.length, 1);
// user scroll do not trigger the ScrollContentMetricsNotification.
expect(events[0] is ScrollStartNotification, true);
events.clear();
await gesture.moveBy(const Offset(-10.0, -10.0));
expect(events.length, 2);
// User scroll do not trigger the ScrollContentMetricsNotification.
expect(events[0] is UserScrollNotification, true);
expect(events[1] is ScrollUpdateNotification, true);
events.clear();
// Change the content dimensions again.
await tester.pumpWidget(buildFrame(500.0));
expect(events.length, 1);
event = events[0] as ScrollMetricsNotification;
expect(event.metrics.extentBefore, 10.0);
expect(event.metrics.extentInside, 590.0);
expect(event.metrics.extentAfter, 0.0);
events.clear();
// The content dimensions does not change.
await tester.pumpWidget(buildFrame(500.0));
expect(events.length, 0);
});
testWidgets('Scroll notification basics', (WidgetTester tester) async {
late ScrollNotification notification;
......
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