Unverified Commit 0190e404 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Keyboard scrolling of Scrollable (#45019)

This adds the ability to scroll and page up/down in a Scrollable using the keyboard. Currently, the macOS bindings use Platform.isMacOS as a check, but we'll switch that to be defaultTargetPlatform == TargetPlatform.macOS once that exists.
parent 459c7fb8
......@@ -4,6 +4,7 @@
import 'dart:async';
import 'dart:collection' show HashMap;
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
......@@ -20,6 +21,7 @@ import 'media_query.dart';
import 'navigator.dart';
import 'pages.dart';
import 'performance_overlay.dart';
import 'scrollable.dart';
import 'semantics_debugger.dart';
import 'shortcuts.dart';
import 'text.dart';
......@@ -1041,12 +1043,46 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
}
final Map<LogicalKeySet, Intent> _keyMap = <LogicalKeySet, Intent>{
// Next/previous keyboard traversal.
LogicalKeySet(LogicalKeyboardKey.tab): const Intent(NextFocusAction.key),
LogicalKeySet(LogicalKeyboardKey.shift, LogicalKeyboardKey.tab): const Intent(PreviousFocusAction.key),
LogicalKeySet(LogicalKeyboardKey.arrowLeft): const DirectionalFocusIntent(TraversalDirection.left),
LogicalKeySet(LogicalKeyboardKey.arrowRight): const DirectionalFocusIntent(TraversalDirection.right),
LogicalKeySet(LogicalKeyboardKey.arrowDown): const DirectionalFocusIntent(TraversalDirection.down),
LogicalKeySet(LogicalKeyboardKey.arrowUp): const DirectionalFocusIntent(TraversalDirection.up),
// Directional keyboard traversal. Not available on web.
if (!kIsWeb) ...<LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.arrowLeft): const DirectionalFocusIntent(TraversalDirection.left),
LogicalKeySet(LogicalKeyboardKey.arrowRight): const DirectionalFocusIntent(TraversalDirection.right),
LogicalKeySet(LogicalKeyboardKey.arrowDown): const DirectionalFocusIntent(TraversalDirection.down),
LogicalKeySet(LogicalKeyboardKey.arrowUp): const DirectionalFocusIntent(TraversalDirection.up)
},
// Keyboard scrolling.
// TODO(gspencergoog): Convert all of the Platform.isMacOS checks to be
// defaultTargetPlatform == TargetPlatform.macOS, once that exists.
// https://github.com/flutter/flutter/issues/31366
if (!kIsWeb && !Platform.isMacOS) ...<LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.arrowUp): const ScrollIntent(direction: AxisDirection.up),
LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.arrowDown): const ScrollIntent(direction: AxisDirection.down),
LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.arrowLeft): const ScrollIntent(direction: AxisDirection.left),
LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.arrowRight): const ScrollIntent(direction: AxisDirection.right),
},
if (!kIsWeb && Platform.isMacOS) ...<LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.arrowUp): const ScrollIntent(direction: AxisDirection.up),
LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.arrowDown): const ScrollIntent(direction: AxisDirection.down),
LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.arrowLeft): const ScrollIntent(direction: AxisDirection.left),
LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.arrowRight): const ScrollIntent(direction: AxisDirection.right),
},
// Web scrolling.
if (kIsWeb) ...<LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.arrowUp): const ScrollIntent(direction: AxisDirection.up),
LogicalKeySet(LogicalKeyboardKey.arrowDown): const ScrollIntent(direction: AxisDirection.down),
LogicalKeySet(LogicalKeyboardKey.arrowLeft): const ScrollIntent(direction: AxisDirection.left),
LogicalKeySet(LogicalKeyboardKey.arrowRight): const ScrollIntent(direction: AxisDirection.right),
},
LogicalKeySet(LogicalKeyboardKey.pageUp): const ScrollIntent(direction: AxisDirection.up, type: ScrollIncrementType.page),
LogicalKeySet(LogicalKeyboardKey.pageDown): const ScrollIntent(direction: AxisDirection.down, type: ScrollIncrementType.page),
LogicalKeySet(LogicalKeyboardKey.enter): const Intent(ActivateAction.key),
LogicalKeySet(LogicalKeyboardKey.space): const Intent(SelectAction.key),
};
......@@ -1057,6 +1093,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
NextFocusAction.key: () => NextFocusAction(),
PreviousFocusAction.key: () => PreviousFocusAction(),
DirectionalFocusAction.key: () => DirectionalFocusAction(),
ScrollAction.key: () => ScrollAction(),
};
@override
......@@ -1169,7 +1206,6 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
: _locale;
assert(_debugCheckLocalizations(appLocale));
return Shortcuts(
shortcuts: _keyMap,
child: Actions(
......
......@@ -1002,8 +1002,8 @@ class DirectionalFocusIntent extends Intent {
final bool ignoreTextFields;
}
/// An [Action] that moves the focus to the focusable node in the given
/// [direction] configured by the associated [DirectionalFocusIntent].
/// An [Action] that moves the focus to the focusable node in the direction
/// configured by the associated [DirectionalFocusIntent.direction].
///
/// This is the [Action] associated with the [key] and bound by default to the
/// [LogicalKeyboardKey.arrowUp], [LogicalKeyboardKey.arrowDown],
......@@ -1016,9 +1016,6 @@ class DirectionalFocusAction extends _RequestFocusActionBase {
/// The [LocalKey] that uniquely identifies this action to [DirectionalFocusIntent].
static const LocalKey key = ValueKey<Type>(DirectionalFocusAction);
/// The direction in which to look for the next focusable node when invoked.
TraversalDirection direction;
@override
void invoke(FocusNode node, DirectionalFocusIntent intent) {
if (!intent.ignoreTextFields || node.context.widget is! EditableText) {
......
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