mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This PR removes a single Divider from one test, since it was not adding anything noteworthy to the test. Part of https://github.com/flutter/flutter/issues/177415 Part of https://github.com/flutter/flutter/issues/180501 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
572 lines
20 KiB
Dart
572 lines
20 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// This file contains a wacky demonstration of creating a custom ScrollPosition
|
|
// setup. It's testing that we don't regress the factoring of the
|
|
// ScrollPosition/ScrollActivity logic into a state where you can no longer
|
|
// implement this, e.g. by oversimplifying it or overfitting it to the features
|
|
// built into the framework itself.
|
|
|
|
import 'dart:collection';
|
|
import 'dart:math' as math;
|
|
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
class LinkedScrollController extends ScrollController {
|
|
LinkedScrollController({this.before, this.after});
|
|
|
|
LinkedScrollController? before;
|
|
LinkedScrollController? after;
|
|
|
|
ScrollController? _parent;
|
|
|
|
void setParent(ScrollController? newParent) {
|
|
if (_parent != null) {
|
|
positions.forEach(_parent!.detach);
|
|
}
|
|
_parent = newParent;
|
|
if (_parent != null) {
|
|
positions.forEach(_parent!.attach);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void attach(ScrollPosition position) {
|
|
assert(
|
|
position is LinkedScrollPosition,
|
|
'A LinkedScrollController must only be used with LinkedScrollPositions.',
|
|
);
|
|
final linkedPosition = position as LinkedScrollPosition;
|
|
assert(
|
|
linkedPosition.owner == this,
|
|
'A LinkedScrollPosition cannot change controllers once created.',
|
|
);
|
|
super.attach(position);
|
|
_parent?.attach(position);
|
|
}
|
|
|
|
@override
|
|
void detach(ScrollPosition position) {
|
|
super.detach(position);
|
|
_parent?.detach(position);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
if (_parent != null) {
|
|
positions.forEach(_parent!.detach);
|
|
}
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
LinkedScrollPosition createScrollPosition(
|
|
ScrollPhysics physics,
|
|
ScrollContext context,
|
|
ScrollPosition? oldPosition,
|
|
) {
|
|
return LinkedScrollPosition(
|
|
this,
|
|
physics: physics,
|
|
context: context,
|
|
initialPixels: initialScrollOffset,
|
|
oldPosition: oldPosition,
|
|
);
|
|
}
|
|
|
|
bool get canLinkWithBefore => before != null && before!.hasClients;
|
|
|
|
bool get canLinkWithAfter => after != null && after!.hasClients;
|
|
|
|
Iterable<LinkedScrollActivity> linkWithBefore(LinkedScrollPosition driver) {
|
|
assert(canLinkWithBefore);
|
|
return before!.link(driver);
|
|
}
|
|
|
|
Iterable<LinkedScrollActivity> linkWithAfter(LinkedScrollPosition driver) {
|
|
assert(canLinkWithAfter);
|
|
return after!.link(driver);
|
|
}
|
|
|
|
Iterable<LinkedScrollActivity> link(LinkedScrollPosition driver) sync* {
|
|
assert(hasClients);
|
|
for (final LinkedScrollPosition position in positions.cast<LinkedScrollPosition>()) {
|
|
yield position.link(driver);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void debugFillDescription(List<String> description) {
|
|
super.debugFillDescription(description);
|
|
final String linkSymbol = switch ((before, after)) {
|
|
(null, null) => 'none',
|
|
(null, _) => '➡',
|
|
(_, null) => '⬅',
|
|
(_, _) => '⬌',
|
|
};
|
|
description.add('links: $linkSymbol');
|
|
}
|
|
}
|
|
|
|
class LinkedScrollPosition extends ScrollPositionWithSingleContext {
|
|
LinkedScrollPosition(
|
|
this.owner, {
|
|
required super.physics,
|
|
required super.context,
|
|
required double super.initialPixels,
|
|
super.oldPosition,
|
|
});
|
|
|
|
final LinkedScrollController owner;
|
|
|
|
Set<LinkedScrollActivity>? _beforeActivities;
|
|
Set<LinkedScrollActivity>? _afterActivities;
|
|
|
|
@override
|
|
void beginActivity(ScrollActivity? newActivity) {
|
|
if (newActivity == null) {
|
|
return;
|
|
}
|
|
if (_beforeActivities != null) {
|
|
for (final LinkedScrollActivity activity in _beforeActivities!) {
|
|
activity.unlink(this);
|
|
}
|
|
_beforeActivities!.clear();
|
|
}
|
|
if (_afterActivities != null) {
|
|
for (final LinkedScrollActivity activity in _afterActivities!) {
|
|
activity.unlink(this);
|
|
}
|
|
_afterActivities!.clear();
|
|
}
|
|
super.beginActivity(newActivity);
|
|
}
|
|
|
|
@override
|
|
void applyUserOffset(double delta) {
|
|
updateUserScrollDirection(delta > 0.0 ? ScrollDirection.forward : ScrollDirection.reverse);
|
|
final double value = pixels - physics.applyPhysicsToUserOffset(this, delta);
|
|
|
|
if (value == pixels) {
|
|
return;
|
|
}
|
|
|
|
var beforeOverscroll = 0.0;
|
|
if (owner.canLinkWithBefore && (value < minScrollExtent)) {
|
|
final double delta = value - minScrollExtent;
|
|
_beforeActivities ??= HashSet<LinkedScrollActivity>();
|
|
_beforeActivities!.addAll(owner.linkWithBefore(this));
|
|
for (final LinkedScrollActivity activity in _beforeActivities!) {
|
|
beforeOverscroll = math.min(activity.moveBy(delta), beforeOverscroll);
|
|
}
|
|
assert(beforeOverscroll <= 0.0);
|
|
}
|
|
|
|
var afterOverscroll = 0.0;
|
|
if (owner.canLinkWithAfter && (value > maxScrollExtent)) {
|
|
final double delta = value - maxScrollExtent;
|
|
_afterActivities ??= HashSet<LinkedScrollActivity>();
|
|
_afterActivities!.addAll(owner.linkWithAfter(this));
|
|
for (final LinkedScrollActivity activity in _afterActivities!) {
|
|
afterOverscroll = math.max(activity.moveBy(delta), afterOverscroll);
|
|
}
|
|
assert(afterOverscroll >= 0.0);
|
|
}
|
|
|
|
assert(beforeOverscroll == 0.0 || afterOverscroll == 0.0);
|
|
|
|
final double localOverscroll = setPixels(
|
|
value.clamp(
|
|
owner.canLinkWithBefore ? minScrollExtent : -double.infinity,
|
|
owner.canLinkWithAfter ? maxScrollExtent : double.infinity,
|
|
),
|
|
);
|
|
|
|
assert(localOverscroll == 0.0 || (beforeOverscroll == 0.0 && afterOverscroll == 0.0));
|
|
}
|
|
|
|
void _userMoved(ScrollDirection direction) {
|
|
updateUserScrollDirection(direction);
|
|
}
|
|
|
|
LinkedScrollActivity link(LinkedScrollPosition driver) {
|
|
if (this.activity is! LinkedScrollActivity) {
|
|
beginActivity(LinkedScrollActivity(this));
|
|
}
|
|
final activity = this.activity as LinkedScrollActivity?;
|
|
activity!.link(driver);
|
|
return activity;
|
|
}
|
|
|
|
void unlink(LinkedScrollActivity activity) {
|
|
_beforeActivities?.remove(activity);
|
|
_afterActivities?.remove(activity);
|
|
}
|
|
|
|
@override
|
|
void debugFillDescription(List<String> description) {
|
|
super.debugFillDescription(description);
|
|
description.add('owner: $owner');
|
|
}
|
|
}
|
|
|
|
class LinkedScrollActivity extends ScrollActivity {
|
|
LinkedScrollActivity(LinkedScrollPosition super.delegate);
|
|
|
|
@override
|
|
LinkedScrollPosition get delegate => super.delegate as LinkedScrollPosition;
|
|
|
|
final Set<LinkedScrollPosition> drivers = HashSet<LinkedScrollPosition>();
|
|
|
|
void link(LinkedScrollPosition driver) {
|
|
drivers.add(driver);
|
|
}
|
|
|
|
void unlink(LinkedScrollPosition driver) {
|
|
drivers.remove(driver);
|
|
if (drivers.isEmpty) {
|
|
delegate.goIdle();
|
|
}
|
|
}
|
|
|
|
@override
|
|
bool get shouldIgnorePointer => true;
|
|
|
|
@override
|
|
bool get isScrolling => true;
|
|
|
|
// LinkedScrollActivity is not self-driven but moved by calls to the [moveBy]
|
|
// method.
|
|
@override
|
|
double get velocity => 0.0;
|
|
|
|
double moveBy(double delta) {
|
|
assert(drivers.isNotEmpty);
|
|
ScrollDirection? commonDirection;
|
|
for (final LinkedScrollPosition driver in drivers) {
|
|
commonDirection ??= driver.userScrollDirection;
|
|
if (driver.userScrollDirection != commonDirection) {
|
|
commonDirection = ScrollDirection.idle;
|
|
}
|
|
}
|
|
|
|
if (commonDirection != null) {
|
|
delegate._userMoved(commonDirection);
|
|
}
|
|
return delegate.setPixels(delegate.pixels + delta);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
for (final LinkedScrollPosition driver in drivers) {
|
|
driver.unlink(this);
|
|
}
|
|
super.dispose();
|
|
}
|
|
}
|
|
|
|
class Test extends StatefulWidget {
|
|
const Test({super.key});
|
|
@override
|
|
State<Test> createState() => _TestState();
|
|
}
|
|
|
|
class _TestState extends State<Test> {
|
|
late LinkedScrollController _beforeController;
|
|
late LinkedScrollController _afterController;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_beforeController = LinkedScrollController();
|
|
_afterController = LinkedScrollController(before: _beforeController);
|
|
_beforeController.after = _afterController;
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
_beforeController.setParent(PrimaryScrollController.maybeOf(context));
|
|
_afterController.setParent(PrimaryScrollController.maybeOf(context));
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_beforeController.dispose();
|
|
_afterController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Column(
|
|
children: <Widget>[
|
|
Expanded(
|
|
child: ListView(
|
|
controller: _beforeController,
|
|
children: <Widget>[
|
|
Container(
|
|
margin: const EdgeInsets.all(8.0),
|
|
padding: const EdgeInsets.all(8.0),
|
|
height: 250.0,
|
|
color: const Color(0xFF90F090),
|
|
child: const Center(child: Text('Hello A')),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.all(8.0),
|
|
padding: const EdgeInsets.all(8.0),
|
|
height: 250.0,
|
|
color: const Color(0xFF90F090),
|
|
child: const Center(child: Text('Hello B')),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.all(8.0),
|
|
padding: const EdgeInsets.all(8.0),
|
|
height: 250.0,
|
|
color: const Color(0xFF90F090),
|
|
child: const Center(child: Text('Hello C')),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.all(8.0),
|
|
padding: const EdgeInsets.all(8.0),
|
|
height: 250.0,
|
|
color: const Color(0xFF90F090),
|
|
child: const Center(child: Text('Hello D')),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Expanded(
|
|
child: ListView(
|
|
controller: _afterController,
|
|
children: <Widget>[
|
|
Container(
|
|
margin: const EdgeInsets.all(8.0),
|
|
padding: const EdgeInsets.all(8.0),
|
|
height: 250.0,
|
|
color: const Color(0xFF9090F0),
|
|
child: const Center(child: Text('Hello 1')),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.all(8.0),
|
|
padding: const EdgeInsets.all(8.0),
|
|
height: 250.0,
|
|
color: const Color(0xFF9090F0),
|
|
child: const Center(child: Text('Hello 2')),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.all(8.0),
|
|
padding: const EdgeInsets.all(8.0),
|
|
height: 250.0,
|
|
color: const Color(0xFF9090F0),
|
|
child: const Center(child: Text('Hello 3')),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.all(8.0),
|
|
padding: const EdgeInsets.all(8.0),
|
|
height: 250.0,
|
|
color: const Color(0xFF9090F0),
|
|
child: const Center(child: Text('Hello 4')),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
testWidgets('LinkedScrollController - 1', (WidgetTester tester) async {
|
|
await tester.pumpWidget(const Test());
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.fling(find.text('Hello A'), const Offset(0.0, -50.0), 10000.0);
|
|
await tester.pumpAndSettle();
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello D'), findsOneWidget);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.drag(find.text('Hello D'), const Offset(0.0, -10000.0));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello D'), findsOneWidget);
|
|
expect(find.text('Hello 4'), findsOneWidget);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.drag(find.text('Hello D'), const Offset(0.0, -10000.0));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello D'), findsOneWidget);
|
|
expect(find.text('Hello 4'), findsOneWidget);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.drag(find.text('Hello 4'), const Offset(0.0, -10000.0));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello D'), findsOneWidget);
|
|
expect(find.text('Hello 4'), findsOneWidget);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.drag(find.text('Hello D'), const Offset(0.0, 10000.0));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 4'), findsOneWidget);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.drag(find.text('Hello A'), const Offset(0.0, 10000.0));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 4'), findsOneWidget);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.drag(find.text('Hello A'), const Offset(0.0, -10000.0));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello D'), findsOneWidget);
|
|
expect(find.text('Hello 4'), findsOneWidget);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.drag(find.text('Hello 4'), const Offset(0.0, 10000.0));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.drag(find.text('Hello 1'), const Offset(0.0, 10000.0));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.drag(find.text('Hello 1'), const Offset(0.0, -10000.0));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 4'), findsOneWidget);
|
|
});
|
|
testWidgets('LinkedScrollController - 2', (WidgetTester tester) async {
|
|
await tester.pumpWidget(const Test());
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello B'), findsOneWidget);
|
|
expect(find.text('Hello C'), findsNothing);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello 2'), findsOneWidget);
|
|
expect(find.text('Hello 3'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
final TestGesture gestureTop = await tester.startGesture(const Offset(200.0, 150.0));
|
|
final TestGesture gestureBottom = await tester.startGesture(const Offset(600.0, 450.0));
|
|
await tester.pump(const Duration(seconds: 1));
|
|
await gestureTop.moveBy(const Offset(0.0, -270.0));
|
|
await tester.pump(const Duration(seconds: 1));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello B'), findsOneWidget);
|
|
expect(find.text('Hello C'), findsOneWidget);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello 2'), findsOneWidget);
|
|
expect(find.text('Hello 3'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await gestureBottom.moveBy(const Offset(0.0, -270.0));
|
|
await tester.pump(const Duration(seconds: 1));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello B'), findsOneWidget);
|
|
expect(find.text('Hello C'), findsOneWidget);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello 2'), findsOneWidget);
|
|
expect(find.text('Hello 3'), findsOneWidget);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await gestureTop.moveBy(const Offset(0.0, -270.0));
|
|
await gestureBottom.moveBy(const Offset(0.0, -270.0));
|
|
await tester.pump(const Duration(seconds: 1));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello B'), findsNothing);
|
|
expect(find.text('Hello C'), findsOneWidget);
|
|
expect(find.text('Hello D'), findsOneWidget);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello 2'), findsNothing);
|
|
expect(find.text('Hello 3'), findsOneWidget);
|
|
expect(find.text('Hello 4'), findsOneWidget);
|
|
await gestureTop.moveBy(const Offset(0.0, 270.0));
|
|
await gestureBottom.moveBy(const Offset(0.0, 270.0));
|
|
await tester.pump(const Duration(seconds: 1));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello B'), findsOneWidget);
|
|
expect(find.text('Hello C'), findsOneWidget);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 1'), findsNothing);
|
|
expect(find.text('Hello 2'), findsOneWidget);
|
|
expect(find.text('Hello 3'), findsOneWidget);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await gestureBottom.moveBy(const Offset(0.0, 270.0));
|
|
await tester.pump(const Duration(seconds: 1));
|
|
expect(find.text('Hello A'), findsNothing);
|
|
expect(find.text('Hello B'), findsOneWidget);
|
|
expect(find.text('Hello C'), findsOneWidget);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello 2'), findsOneWidget);
|
|
expect(find.text('Hello 3'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await gestureBottom.moveBy(const Offset(0.0, 50.0));
|
|
await tester.pump(const Duration(seconds: 1));
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello B'), findsOneWidget);
|
|
expect(find.text('Hello C'), findsNothing);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello 2'), findsOneWidget);
|
|
expect(find.text('Hello 3'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await gestureBottom.moveBy(const Offset(0.0, 50.0));
|
|
await tester.pump(const Duration(seconds: 1));
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello B'), findsOneWidget);
|
|
expect(find.text('Hello C'), findsNothing);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello 2'), findsOneWidget);
|
|
expect(find.text('Hello 3'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await gestureBottom.moveBy(const Offset(0.0, 50.0));
|
|
await tester.pump(const Duration(seconds: 1));
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello B'), findsOneWidget);
|
|
expect(find.text('Hello C'), findsNothing);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello 2'), findsOneWidget);
|
|
expect(find.text('Hello 3'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await gestureTop.moveBy(const Offset(0.0, -270.0));
|
|
expect(find.text('Hello A'), findsOneWidget);
|
|
expect(find.text('Hello B'), findsOneWidget);
|
|
expect(find.text('Hello C'), findsNothing);
|
|
expect(find.text('Hello D'), findsNothing);
|
|
expect(find.text('Hello 1'), findsOneWidget);
|
|
expect(find.text('Hello 2'), findsOneWidget);
|
|
expect(find.text('Hello 3'), findsNothing);
|
|
expect(find.text('Hello 4'), findsNothing);
|
|
await tester.pump(const Duration(seconds: 1));
|
|
await tester.pump(const Duration(seconds: 60));
|
|
});
|
|
}
|