mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
This reverts commit 9b56241eef
.
This commit is contained in:
parent
22e576fa26
commit
e803b13f01
|
@ -12,12 +12,6 @@ import 'theme.dart';
|
||||||
/// The scaffold lays out the navigation bar on top and the content between or
|
/// The scaffold lays out the navigation bar on top and the content between or
|
||||||
/// behind the navigation bar.
|
/// behind the navigation bar.
|
||||||
///
|
///
|
||||||
/// When tapping a status bar at the top of the CupertinoPageScaffold, an
|
|
||||||
/// animation will complete for the current primary [ScrollView], scrolling to
|
|
||||||
/// the beginning. This is done using the [PrimaryScrollController] that
|
|
||||||
/// encloses the [ScrollView]. The [ScrollView.primary] flag is used to connect
|
|
||||||
/// a [ScrollView] to the enclosing [PrimaryScrollController].
|
|
||||||
///
|
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [CupertinoTabScaffold], a similar widget for tabbed applications.
|
/// * [CupertinoTabScaffold], a similar widget for tabbed applications.
|
||||||
|
@ -81,11 +75,11 @@ class CupertinoPageScaffold extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
|
class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
|
||||||
|
final ScrollController _primaryScrollController = ScrollController();
|
||||||
|
|
||||||
void _handleStatusBarTap() {
|
void _handleStatusBarTap() {
|
||||||
final ScrollController? _primaryScrollController = PrimaryScrollController.of(context);
|
|
||||||
// Only act on the scroll controller if it has any attached scroll positions.
|
// Only act on the scroll controller if it has any attached scroll positions.
|
||||||
if (_primaryScrollController != null && _primaryScrollController.hasClients) {
|
if (_primaryScrollController.hasClients) {
|
||||||
_primaryScrollController.animateTo(
|
_primaryScrollController.animateTo(
|
||||||
0.0,
|
0.0,
|
||||||
// Eyeballed from iOS.
|
// Eyeballed from iOS.
|
||||||
|
@ -169,7 +163,10 @@ class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
// The main content being at the bottom is added to the stack first.
|
// The main content being at the bottom is added to the stack first.
|
||||||
paddedContent,
|
PrimaryScrollController(
|
||||||
|
controller: _primaryScrollController,
|
||||||
|
child: paddedContent,
|
||||||
|
),
|
||||||
if (widget.navigationBar != null)
|
if (widget.navigationBar != null)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 0.0,
|
top: 0.0,
|
||||||
|
|
|
@ -2670,11 +2670,13 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
|
||||||
// iOS FEATURES - status bar tap, back gesture
|
// iOS FEATURES - status bar tap, back gesture
|
||||||
|
|
||||||
// On iOS, tapping the status bar scrolls the app's primary scrollable to the
|
// On iOS, tapping the status bar scrolls the app's primary scrollable to the
|
||||||
// top. We implement this by looking up the primary scroll controller and
|
// top. We implement this by providing a primary scroll controller and
|
||||||
// scrolling it to the top when tapped.
|
// scrolling it to the top when tapped.
|
||||||
|
|
||||||
|
final ScrollController _primaryScrollController = ScrollController();
|
||||||
|
|
||||||
void _handleStatusBarTap() {
|
void _handleStatusBarTap() {
|
||||||
final ScrollController? _primaryScrollController = PrimaryScrollController.of(context);
|
if (_primaryScrollController.hasClients) {
|
||||||
if (_primaryScrollController != null && _primaryScrollController.hasClients) {
|
|
||||||
_primaryScrollController.animateTo(
|
_primaryScrollController.animateTo(
|
||||||
0.0,
|
0.0,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
|
@ -3158,6 +3160,8 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
|
||||||
return _ScaffoldScope(
|
return _ScaffoldScope(
|
||||||
hasDrawer: hasDrawer,
|
hasDrawer: hasDrawer,
|
||||||
geometryNotifier: _geometryNotifier,
|
geometryNotifier: _geometryNotifier,
|
||||||
|
child: PrimaryScrollController(
|
||||||
|
controller: _primaryScrollController,
|
||||||
child: Material(
|
child: Material(
|
||||||
color: widget.backgroundColor ?? themeData.scaffoldBackgroundColor,
|
color: widget.backgroundColor ?? themeData.scaffoldBackgroundColor,
|
||||||
child: AnimatedBuilder(animation: _floatingActionButtonMoveController, builder: (BuildContext context, Widget? child) {
|
child: AnimatedBuilder(animation: _floatingActionButtonMoveController, builder: (BuildContext context, Widget? child) {
|
||||||
|
@ -3180,6 +3184,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,19 +16,6 @@ import 'scroll_controller.dart';
|
||||||
/// This mechanism can be used to provide default behavior for scroll views in a
|
/// This mechanism can be used to provide default behavior for scroll views in a
|
||||||
/// subtree. For example, the [Scaffold] uses this mechanism to implement the
|
/// subtree. For example, the [Scaffold] uses this mechanism to implement the
|
||||||
/// scroll-to-top gesture on iOS.
|
/// scroll-to-top gesture on iOS.
|
||||||
///
|
|
||||||
/// Another default behavior handled by the PrimaryScrollController is default
|
|
||||||
/// [ScrollAction]s. If a ScrollAction is not handled by an otherwise focused
|
|
||||||
/// part of the application, the ScrollAction will be evaluated using the scroll
|
|
||||||
/// view associated with a PrimaryScrollController, for example, when executing
|
|
||||||
/// [Shortcuts] key events like page up and down.
|
|
||||||
///
|
|
||||||
/// See also:
|
|
||||||
/// * [ScrollAction], an [Action] that scrolls the [Scrollable] that encloses
|
|
||||||
/// the current [primaryFocus] or is attached to the PrimaryScrollController.
|
|
||||||
/// * [Shortcuts], a widget that establishes a [ShortcutManager] to be used
|
|
||||||
/// by its descendants when invoking an [Action] via a keyboard key
|
|
||||||
/// combination that maps to an [Intent].
|
|
||||||
class PrimaryScrollController extends InheritedWidget {
|
class PrimaryScrollController extends InheritedWidget {
|
||||||
/// Creates a widget that associates a [ScrollController] with a subtree.
|
/// Creates a widget that associates a [ScrollController] with a subtree.
|
||||||
const PrimaryScrollController({
|
const PrimaryScrollController({
|
||||||
|
|
|
@ -18,9 +18,7 @@ import 'modal_barrier.dart';
|
||||||
import 'navigator.dart';
|
import 'navigator.dart';
|
||||||
import 'overlay.dart';
|
import 'overlay.dart';
|
||||||
import 'page_storage.dart';
|
import 'page_storage.dart';
|
||||||
import 'primary_scroll_controller.dart';
|
|
||||||
import 'restoration.dart';
|
import 'restoration.dart';
|
||||||
import 'scroll_controller.dart';
|
|
||||||
import 'transitions.dart';
|
import 'transitions.dart';
|
||||||
|
|
||||||
// Examples can assume:
|
// Examples can assume:
|
||||||
|
@ -724,7 +722,6 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
|
||||||
|
|
||||||
/// The node this scope will use for its root [FocusScope] widget.
|
/// The node this scope will use for its root [FocusScope] widget.
|
||||||
final FocusScopeNode focusScopeNode = FocusScopeNode(debugLabel: '$_ModalScopeState Focus Scope');
|
final FocusScopeNode focusScopeNode = FocusScopeNode(debugLabel: '$_ModalScopeState Focus Scope');
|
||||||
final ScrollController primaryScrollController = ScrollController();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -805,8 +802,6 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
|
||||||
actions: <Type, Action<Intent>>{
|
actions: <Type, Action<Intent>>{
|
||||||
DismissIntent: _DismissModalAction(context),
|
DismissIntent: _DismissModalAction(context),
|
||||||
},
|
},
|
||||||
child: PrimaryScrollController(
|
|
||||||
controller: primaryScrollController,
|
|
||||||
child: FocusScope(
|
child: FocusScope(
|
||||||
node: focusScopeNode, // immutable
|
node: focusScopeNode, // immutable
|
||||||
child: RepaintBoundary(
|
child: RepaintBoundary(
|
||||||
|
@ -850,7 +845,6 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -149,11 +149,6 @@ abstract class ScrollView extends StatelessWidget {
|
||||||
/// sufficient content to actually scroll. Otherwise, by default the user can
|
/// sufficient content to actually scroll. Otherwise, by default the user can
|
||||||
/// only scroll the view if it has sufficient content. See [physics].
|
/// only scroll the view if it has sufficient content. See [physics].
|
||||||
///
|
///
|
||||||
/// Also when true, the scroll view is used for default [ScrollAction]s. If a
|
|
||||||
/// ScrollAction is not handled by an otherwise focused part of the application,
|
|
||||||
/// the ScrollAction will be evaluated using this scroll view, for example,
|
|
||||||
/// when executing [Shortcuts] key events like page up and down.
|
|
||||||
///
|
|
||||||
/// On iOS, this also identifies the scroll view that will scroll to top in
|
/// On iOS, this also identifies the scroll view that will scroll to top in
|
||||||
/// response to a tap in the status bar.
|
/// response to a tap in the status bar.
|
||||||
///
|
///
|
||||||
|
|
|
@ -17,7 +17,6 @@ import 'focus_manager.dart';
|
||||||
import 'framework.dart';
|
import 'framework.dart';
|
||||||
import 'gesture_detector.dart';
|
import 'gesture_detector.dart';
|
||||||
import 'notification_listener.dart';
|
import 'notification_listener.dart';
|
||||||
import 'primary_scroll_controller.dart';
|
|
||||||
import 'restoration.dart';
|
import 'restoration.dart';
|
||||||
import 'restoration_properties.dart';
|
import 'restoration_properties.dart';
|
||||||
import 'scroll_configuration.dart';
|
import 'scroll_configuration.dart';
|
||||||
|
@ -960,10 +959,6 @@ class ScrollIntent extends Intent {
|
||||||
/// An [Action] that scrolls the [Scrollable] that encloses the current
|
/// An [Action] that scrolls the [Scrollable] that encloses the current
|
||||||
/// [primaryFocus] by the amount configured in the [ScrollIntent] given to it.
|
/// [primaryFocus] by the amount configured in the [ScrollIntent] given to it.
|
||||||
///
|
///
|
||||||
/// If a Scrollable cannot be found above the current [primaryFocus], the
|
|
||||||
/// [PrimaryScrollController] will be considered for default handling of
|
|
||||||
/// [ScrollAction]s.
|
|
||||||
///
|
|
||||||
/// If [Scrollable.incrementCalculator] is null for the scrollable, the default
|
/// If [Scrollable.incrementCalculator] is null for the scrollable, the default
|
||||||
/// for a [ScrollIntent.type] set to [ScrollIncrementType.page] is 80% of the
|
/// for a [ScrollIntent.type] set to [ScrollIncrementType.page] is 80% of the
|
||||||
/// size of the scroll window, and for [ScrollIncrementType.line], 50 logical
|
/// size of the scroll window, and for [ScrollIncrementType.line], 50 logical
|
||||||
|
@ -972,21 +967,7 @@ class ScrollAction extends Action<ScrollIntent> {
|
||||||
@override
|
@override
|
||||||
bool isEnabled(ScrollIntent intent) {
|
bool isEnabled(ScrollIntent intent) {
|
||||||
final FocusNode? focus = primaryFocus;
|
final FocusNode? focus = primaryFocus;
|
||||||
final bool contextIsValid = focus != null && focus.context != null;
|
return focus != null && focus.context != null && Scrollable.of(focus.context!) != null;
|
||||||
if (contextIsValid) {
|
|
||||||
// Check for primary scrollable within the current context
|
|
||||||
if (Scrollable.of(focus!.context!) != null)
|
|
||||||
return true;
|
|
||||||
// Check for fallback scrollable with context from PrimaryScrollController
|
|
||||||
if (PrimaryScrollController.of(focus.context!) != null) {
|
|
||||||
final ScrollController? primaryScrollController = PrimaryScrollController.of(focus.context!);
|
|
||||||
return primaryScrollController != null
|
|
||||||
&& primaryScrollController.hasClients
|
|
||||||
&& primaryScrollController.position.context.notificationContext != null
|
|
||||||
&& Scrollable.of(primaryScrollController.position.context.notificationContext!) != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the scroll increment for a single scroll request, for use when
|
// Returns the scroll increment for a single scroll request, for use when
|
||||||
|
@ -1070,11 +1051,7 @@ class ScrollAction extends Action<ScrollIntent> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void invoke(ScrollIntent intent) {
|
void invoke(ScrollIntent intent) {
|
||||||
ScrollableState? state = Scrollable.of(primaryFocus!.context!);
|
final ScrollableState? state = Scrollable.of(primaryFocus!.context!);
|
||||||
if (state == null) {
|
|
||||||
final ScrollController? primaryScrollController = PrimaryScrollController.of(primaryFocus!.context!);
|
|
||||||
state = Scrollable.of(primaryScrollController!.position.context.notificationContext!);
|
|
||||||
}
|
|
||||||
assert(state != null, '$ScrollAction was invoked on a context that has no scrollable parent');
|
assert(state != null, '$ScrollAction was invoked on a context that has no scrollable parent');
|
||||||
assert(state!.position.hasPixels, 'Scrollable must be laid out before it can be scrolled via a ScrollAction');
|
assert(state!.position.hasPixels, 'Scrollable must be laid out before it can be scrolled via a ScrollAction');
|
||||||
assert(state!.position.viewportDimension != null);
|
assert(state!.position.viewportDimension != null);
|
||||||
|
|
|
@ -382,7 +382,7 @@ class ShortcutManager extends ChangeNotifier with Diagnosticable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A widget that establishes a [ShortcutManager] to be used by its descendants
|
/// A widget that establishes an [ShortcutManager] to be used by its descendants
|
||||||
/// when invoking an [Action] via a keyboard key combination that maps to an
|
/// when invoking an [Action] via a keyboard key combination that maps to an
|
||||||
/// [Intent].
|
/// [Intent].
|
||||||
///
|
///
|
||||||
|
|
|
@ -270,11 +270,6 @@ class SingleChildScrollView extends StatelessWidget {
|
||||||
/// Whether this is the primary scroll view associated with the parent
|
/// Whether this is the primary scroll view associated with the parent
|
||||||
/// [PrimaryScrollController].
|
/// [PrimaryScrollController].
|
||||||
///
|
///
|
||||||
/// When true, the scroll view is used for default [ScrollAction]s. If a
|
|
||||||
/// ScrollAction is not handled by an otherwise focused part of the application,
|
|
||||||
/// the ScrollAction will be evaluated using this scroll view, for example,
|
|
||||||
/// when executing [Shortcuts] key events like page up and down.
|
|
||||||
///
|
|
||||||
/// On iOS, this identifies the scroll view that will scroll to top in
|
/// On iOS, this identifies the scroll view that will scroll to top in
|
||||||
/// response to a tap in the status bar.
|
/// response to a tap in the status bar.
|
||||||
///
|
///
|
||||||
|
|
|
@ -19,8 +19,17 @@ Widget buildSliverAppBarApp({
|
||||||
bool snap = false,
|
bool snap = false,
|
||||||
double toolbarHeight = kToolbarHeight,
|
double toolbarHeight = kToolbarHeight,
|
||||||
}) {
|
}) {
|
||||||
return MaterialApp(
|
return Localizations(
|
||||||
home: Scaffold(
|
locale: const Locale('en', 'US'),
|
||||||
|
delegates: const <LocalizationsDelegate<dynamic>>[
|
||||||
|
DefaultMaterialLocalizations.delegate,
|
||||||
|
DefaultWidgetsLocalizations.delegate,
|
||||||
|
],
|
||||||
|
child: Directionality(
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
child: MediaQuery(
|
||||||
|
data: const MediaQueryData(),
|
||||||
|
child: Scaffold(
|
||||||
body: DefaultTabController(
|
body: DefaultTabController(
|
||||||
length: 3,
|
length: 3,
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
|
@ -48,6 +57,8 @@ Widget buildSliverAppBarApp({
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,6 @@ void main() {
|
||||||
' _FocusMarker\n'
|
' _FocusMarker\n'
|
||||||
' Semantics\n'
|
' Semantics\n'
|
||||||
' FocusScope\n'
|
' FocusScope\n'
|
||||||
' PrimaryScrollController\n'
|
|
||||||
' _ActionsMarker\n'
|
' _ActionsMarker\n'
|
||||||
' Actions\n'
|
' Actions\n'
|
||||||
' Builder\n'
|
' Builder\n'
|
||||||
|
|
|
@ -2128,11 +2128,12 @@ void main() {
|
||||||
' AnimatedBuilder\n'
|
' AnimatedBuilder\n'
|
||||||
' DefaultTextStyle\n'
|
' DefaultTextStyle\n'
|
||||||
' AnimatedDefaultTextStyle\n'
|
' AnimatedDefaultTextStyle\n'
|
||||||
' _InkFeatures-[GlobalKey#00000 ink renderer]\n'
|
' _InkFeatures-[GlobalKey#342d0 ink renderer]\n'
|
||||||
' NotificationListener<LayoutChangedNotification>\n'
|
' NotificationListener<LayoutChangedNotification>\n'
|
||||||
' PhysicalModel\n'
|
' PhysicalModel\n'
|
||||||
' AnimatedPhysicalModel\n'
|
' AnimatedPhysicalModel\n'
|
||||||
' Material\n'
|
' Material\n'
|
||||||
|
' PrimaryScrollController\n'
|
||||||
' _ScaffoldScope\n'
|
' _ScaffoldScope\n'
|
||||||
' Scaffold\n'
|
' Scaffold\n'
|
||||||
' MediaQuery\n'
|
' MediaQuery\n'
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:flutter/services.dart' show LogicalKeyboardKey;
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter/gestures.dart' show DragStartBehavior;
|
import 'package:flutter/gestures.dart' show DragStartBehavior;
|
||||||
|
@ -1260,48 +1259,4 @@ void main() {
|
||||||
semanticChildCount: 4,
|
semanticChildCount: 4,
|
||||||
), throwsAssertionError);
|
), throwsAssertionError);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('PrimaryScrollController provides fallback ScrollActions', (WidgetTester tester) async {
|
|
||||||
await tester.pumpWidget(
|
|
||||||
MaterialApp(
|
|
||||||
home: CustomScrollView(
|
|
||||||
primary: true,
|
|
||||||
slivers: List<Widget>.generate(
|
|
||||||
20,
|
|
||||||
(int index) {
|
|
||||||
return SliverToBoxAdapter(
|
|
||||||
child: Focus(
|
|
||||||
autofocus: index == 0,
|
|
||||||
child: SizedBox(key: ValueKey<String>('Box $index'), height: 50.0),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
final ScrollController controller = PrimaryScrollController.of(
|
|
||||||
tester.element(find.byType(CustomScrollView))
|
|
||||||
)!;
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(controller.position.pixels, equals(0.0));
|
|
||||||
expect(
|
|
||||||
tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)),
|
|
||||||
equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)),
|
|
||||||
);
|
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.pageDown);
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(controller.position.pixels, equals(400.0));
|
|
||||||
expect(
|
|
||||||
tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)),
|
|
||||||
equals(const Rect.fromLTRB(0.0, -400.0, 800.0, -350.0)),
|
|
||||||
);
|
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.pageUp);
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(controller.position.pixels, equals(0.0));
|
|
||||||
expect(
|
|
||||||
tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)),
|
|
||||||
equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -521,19 +521,13 @@ void main() {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.position.pixels, equals(0.0));
|
expect(controller.position.pixels, equals(0.0));
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)));
|
||||||
// We exclude the modifier keys here for web testing since default web shortcuts
|
|
||||||
// do not use a modifier key with arrow keys for ScrollActions.
|
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, -50.0, 800.0, 0.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, -50.0, 800.0, 0.0)));
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)));
|
||||||
|
@ -543,7 +537,7 @@ void main() {
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.pageUp);
|
await tester.sendKeyEvent(LogicalKeyboardKey.pageUp);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)));
|
||||||
});
|
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694
|
||||||
|
|
||||||
testWidgets('Horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
|
testWidgets('Horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
|
@ -573,23 +567,17 @@ void main() {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.position.pixels, equals(0.0));
|
expect(controller.position.pixels, equals(0.0));
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 50.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 50.0, 600.0)));
|
||||||
// We exclude the modifier keys here for web testing since default web shortcuts
|
|
||||||
// do not use a modifier key with arrow keys for ScrollActions.
|
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(-50.0, 0.0, 0.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(-50.0, 0.0, 0.0, 600.0)));
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 50.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 50.0, 600.0)));
|
||||||
});
|
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694
|
||||||
|
|
||||||
testWidgets('Horizontal scrollables are scrolled the correct direction in RTL locales.', (WidgetTester tester) async {
|
testWidgets('Horizontal scrollables are scrolled the correct direction in RTL locales.', (WidgetTester tester) async {
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
|
@ -622,23 +610,17 @@ void main() {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.position.pixels, equals(0.0));
|
expect(controller.position.pixels, equals(0.0));
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(750.0, 0.0, 800.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(750.0, 0.0, 800.0, 600.0)));
|
||||||
// We exclude the modifier keys here for web testing since default web shortcuts
|
|
||||||
// do not use a modifier key with arrow keys for ScrollActions.
|
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(800.0, 0.0, 850.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(800.0, 0.0, 850.0, 600.0)));
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(750.0, 0.0, 800.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(750.0, 0.0, 800.0, 600.0)));
|
||||||
});
|
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694
|
||||||
|
|
||||||
testWidgets('Reversed vertical scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
|
testWidgets('Reversed vertical scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
|
@ -670,19 +652,13 @@ void main() {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.position.pixels, equals(0.0));
|
expect(controller.position.pixels, equals(0.0));
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 550.0, 800.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 550.0, 800.0, 600.0)));
|
||||||
// We exclude the modifier keys here for web testing since default web shortcuts
|
|
||||||
// do not use a modifier key with arrow keys for ScrollActions.
|
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 600.0, 800.0, 650.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 600.0, 800.0, 650.0)));
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 550.0, 800.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 550.0, 800.0, 600.0)));
|
||||||
|
@ -692,7 +668,7 @@ void main() {
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.pageDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.pageDown);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 550.0, 800.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 550.0, 800.0, 600.0)));
|
||||||
});
|
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694
|
||||||
|
|
||||||
testWidgets('Reversed horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
|
testWidgets('Reversed horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
|
@ -725,22 +701,16 @@ void main() {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.position.pixels, equals(0.0));
|
expect(controller.position.pixels, equals(0.0));
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(750.0, 0.0, 800.0, 600.00)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(750.0, 0.0, 800.0, 600.00)));
|
||||||
// We exclude the modifier keys here for web testing since default web shortcuts
|
|
||||||
// do not use a modifier key with arrow keys for ScrollActions.
|
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(800.0, 0.0, 850.0, 600.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(800.0, 0.0, 850.0, 600.0)));
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
});
|
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694
|
||||||
|
|
||||||
testWidgets('Custom scrollables with a center sliver are scrolled when activated via keyboard.', (WidgetTester tester) async {
|
testWidgets('Custom scrollables with a center sliver are scrolled when activated via keyboard.', (WidgetTester tester) async {
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
|
@ -777,12 +747,8 @@ void main() {
|
||||||
expect(controller.position.pixels, equals(0.0));
|
expect(controller.position.pixels, equals(0.0));
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Item 10'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 100.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Item 10'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 100.0)));
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
// We exclude the modifier keys here for web testing since default web shortcuts
|
|
||||||
// do not use a modifier key with arrow keys for ScrollActions.
|
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
}
|
}
|
||||||
|
@ -790,17 +756,15 @@ void main() {
|
||||||
expect(controller.position.pixels, equals(400.0));
|
expect(controller.position.pixels, equals(400.0));
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Item 10'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, -400.0, 800.0, -300.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Item 10'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, -400.0, 800.0, -300.0)));
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyDownEvent(modifierKey);
|
await tester.sendKeyDownEvent(modifierKey);
|
||||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||||
if (!kIsWeb)
|
|
||||||
await tester.sendKeyUpEvent(modifierKey);
|
await tester.sendKeyUpEvent(modifierKey);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
}
|
}
|
||||||
// Goes up two past "center" where it started, so negative.
|
// Goes up two past "center" where it started, so negative.
|
||||||
expect(controller.position.pixels, equals(-100.0));
|
expect(controller.position.pixels, equals(-100.0));
|
||||||
expect(tester.getRect(find.byKey(const ValueKey<String>('Item 10'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 100.0, 800.0, 200.0)));
|
expect(tester.getRect(find.byKey(const ValueKey<String>('Item 10'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 100.0, 800.0, 200.0)));
|
||||||
});
|
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694
|
||||||
|
|
||||||
testWidgets('Can recommendDeferredLoadingForContext - animation', (WidgetTester tester) async {
|
testWidgets('Can recommendDeferredLoadingForContext - animation', (WidgetTester tester) async {
|
||||||
final List<String> widgetTracker = <String>[];
|
final List<String> widgetTracker = <String>[];
|
||||||
|
|
Loading…
Reference in a new issue