Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
0351c74a
Unverified
Commit
0351c74a
authored
Dec 15, 2020
by
Greg Spencer
Committed by
GitHub
Dec 15, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make web buttons respond to enter key (#72162)
parent
70f5f7a7
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
131 additions
and
12 deletions
+131
-12
dropdown.dart
packages/flutter/lib/src/material/dropdown.dart
+3
-0
ink_well.dart
packages/flutter/lib/src/material/ink_well.dart
+2
-1
actions.dart
packages/flutter/lib/src/widgets/actions.dart
+30
-1
app.dart
packages/flutter/lib/src/widgets/app.dart
+5
-6
dropdown_test.dart
packages/flutter/test/material/dropdown_test.dart
+58
-4
ink_well_test.dart
packages/flutter/test/material/ink_well_test.dart
+33
-0
No files found.
packages/flutter/lib/src/material/dropdown.dart
View file @
0351c74a
...
...
@@ -1113,6 +1113,9 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
ActivateIntent:
CallbackAction
<
ActivateIntent
>(
onInvoke:
(
ActivateIntent
intent
)
=>
_handleTap
(),
),
ButtonActivateIntent:
CallbackAction
<
ButtonActivateIntent
>(
onInvoke:
(
ButtonActivateIntent
intent
)
=>
_handleTap
(),
),
};
focusNode
!.
addListener
(
_handleFocusChanged
);
final
FocusManager
focusManager
=
WidgetsBinding
.
instance
!.
focusManager
;
...
...
packages/flutter/lib/src/material/ink_well.dart
View file @
0351c74a
...
...
@@ -734,6 +734,7 @@ class _InkResponseState extends State<_InkResponseStateWidget>
final
Map
<
_HighlightType
,
InkHighlight
?>
_highlights
=
<
_HighlightType
,
InkHighlight
?>{};
late
final
Map
<
Type
,
Action
<
Intent
>>
_actionMap
=
<
Type
,
Action
<
Intent
>>{
ActivateIntent:
CallbackAction
<
ActivateIntent
>(
onInvoke:
_simulateTap
),
ButtonActivateIntent:
CallbackAction
<
ButtonActivateIntent
>(
onInvoke:
_simulateTap
),
};
bool
get
highlightsExist
=>
_highlights
.
values
.
where
((
InkHighlight
?
highlight
)
=>
highlight
!=
null
).
isNotEmpty
;
...
...
@@ -756,7 +757,7 @@ class _InkResponseState extends State<_InkResponseStateWidget>
}
bool
get
_anyChildInkResponsePressed
=>
_activeChildren
.
isNotEmpty
;
void
_simulateTap
([
Activate
Intent
?
intent
])
{
void
_simulateTap
([
Intent
?
intent
])
{
_startSplash
(
context:
context
);
_handleTap
();
}
...
...
packages/flutter/lib/src/widgets/actions.dart
View file @
0351c74a
...
...
@@ -1248,12 +1248,41 @@ class DoNothingAction extends Action<Intent> {
void
invoke
(
Intent
intent
)
{}
}
/// An intent that activates the currently focused control.
/// An [Intent] that activates the currently focused control.
///
/// This intent is bound by default to the [LogicalKeyboardKey.space] key on all
/// platforms, and also to the [LogicalKeyboardKey.enter] key on all platforms
/// except the web, where ENTER doesn't toggle selection. On the web, ENTER is
/// bound to [ButtonActivateIntent] instead.
///
/// See also:
///
/// * [WidgetsApp.defaultShortcuts], which contains the default shortcuts used
/// in apps.
/// * [WidgetsApp.shortcuts], which defines the shortcuts to use in an
/// application (and defaults to [WidgetsApp.defaultShortcuts]).
class
ActivateIntent
extends
Intent
{
/// Creates a const [ActivateIntent] so subclasses can be const.
const
ActivateIntent
();
}
/// An [Intent] that activates the currently focused button.
///
/// This intent is bound by default to the [LogicalKeyboardKey.enter] key on the
/// web, where ENTER can be used to activate buttons, but not toggle selection.
/// All other platforms bind [LogicalKeyboardKey.enter] to [ActivateIntent].
///
/// See also:
///
/// * [WidgetsApp.defaultShortcuts], which contains the default shortcuts used
/// in apps.
/// * [WidgetsApp.shortcuts], which defines the shortcuts to use in an
/// application (and defaults to [WidgetsApp.defaultShortcuts]).
class
ButtonActivateIntent
extends
Intent
{
/// Creates a const [ButtonActivateIntent] so subclasses can be const.
const
ButtonActivateIntent
();
}
/// An action that activates the currently focused control.
///
/// This is an abstract class that serves as a base class for actions that
...
...
packages/flutter/lib/src/widgets/app.dart
View file @
0351c74a
...
...
@@ -1028,6 +1028,8 @@ class WidgetsApp extends StatefulWidget {
static
final
Map
<
LogicalKeySet
,
Intent
>
_defaultWebShortcuts
=
<
LogicalKeySet
,
Intent
>{
// Activation
LogicalKeySet
(
LogicalKeyboardKey
.
space
):
const
ActivateIntent
(),
// On the web, enter activates buttons, but not other controls.
LogicalKeySet
(
LogicalKeyboardKey
.
enter
):
const
ButtonActivateIntent
(),
// Dismissal
LogicalKeySet
(
LogicalKeyboardKey
.
escape
):
const
DismissIntent
(),
...
...
@@ -1046,7 +1048,7 @@ class WidgetsApp extends StatefulWidget {
};
// Default shortcuts for the macOS platform.
static
final
Map
<
LogicalKeySet
,
Intent
>
_default
Mac
OsShortcuts
=
<
LogicalKeySet
,
Intent
>{
static
final
Map
<
LogicalKeySet
,
Intent
>
_default
Apple
OsShortcuts
=
<
LogicalKeySet
,
Intent
>{
// Activation
LogicalKeySet
(
LogicalKeyboardKey
.
enter
):
const
ActivateIntent
(),
LogicalKeySet
(
LogicalKeyboardKey
.
space
):
const
ActivateIntent
(),
...
...
@@ -1086,13 +1088,10 @@ class WidgetsApp extends StatefulWidget {
case
TargetPlatform
.
linux
:
case
TargetPlatform
.
windows
:
return
_defaultShortcuts
;
case
TargetPlatform
.
macOS
:
return
_defaultMacOsShortcuts
;
case
TargetPlatform
.
iOS
:
// No keyboard support on iOS yet.
break
;
case
TargetPlatform
.
macOS
:
return
_defaultAppleOsShortcuts
;
}
return
<
LogicalKeySet
,
Intent
>{};
}
/// The default value of [WidgetsApp.actions].
...
...
packages/flutter/test/material/dropdown_test.dart
View file @
0351c74a
...
...
@@ -2358,7 +2358,7 @@ void main() {
expect
(
find
.
byKey
(
buttonKey
),
isNot
(
paints
..
rrect
(
rrect:
const
RRect
.
fromLTRBXY
(
0.0
,
0.0
,
104.0
,
48.0
,
4.0
,
4.0
),
color:
const
Color
(
0xff00ff00
))));
});
testWidgets
(
'DropdownButton is activated with the enter
/space
key'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'DropdownButton is activated with the enter key'
,
(
WidgetTester
tester
)
async
{
final
FocusNode
focusNode
=
FocusNode
(
debugLabel:
'DropdownButton'
);
String
?
value
=
'one'
;
...
...
@@ -2397,15 +2397,69 @@ void main() {
await
tester
.
pump
();
// Pump a frame for autofocus to take effect.
expect
(
focusNode
.
hasPrimaryFocus
,
isTrue
);
// Web doesn't respond to enter, only space.
await
tester
.
sendKeyEvent
(
kIsWeb
?
LogicalKeyboardKey
.
space
:
LogicalKeyboardKey
.
enter
);
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
enter
);
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
seconds:
1
));
// finish the menu animation
expect
(
value
,
equals
(
'one'
));
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
tab
);
// Focus 'two'
await
tester
.
pump
();
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
enter
);
// Select 'two'.
await
tester
.
pump
();
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
seconds:
1
));
// finish the menu animation
expect
(
value
,
equals
(
'two'
));
});
testWidgets
(
'DropdownButton is activated with the space key'
,
(
WidgetTester
tester
)
async
{
final
FocusNode
focusNode
=
FocusNode
(
debugLabel:
'DropdownButton'
);
String
?
value
=
'one'
;
Widget
buildFrame
()
{
return
MaterialApp
(
home:
Scaffold
(
body:
Center
(
child:
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
DropdownButton
<
String
>(
focusNode:
focusNode
,
autofocus:
true
,
onChanged:
(
String
?
newValue
)
{
setState
(()
{
value
=
newValue
;
});
},
value:
value
,
itemHeight:
null
,
items:
menuItems
.
map
<
DropdownMenuItem
<
String
>>((
String
item
)
{
return
DropdownMenuItem
<
String
>(
key:
ValueKey
<
String
>(
item
),
value:
item
,
child:
Text
(
item
,
key:
ValueKey
<
String
>(
item
+
'Text'
)),
);
}).
toList
(),
);
},
),
),
),
);
}
await
tester
.
pumpWidget
(
buildFrame
());
await
tester
.
pump
();
// Pump a frame for autofocus to take effect.
expect
(
focusNode
.
hasPrimaryFocus
,
isTrue
);
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
space
);
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
seconds:
1
));
// finish the menu animation
expect
(
value
,
equals
(
'one'
));
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
tab
);
// Focus 'two'
await
tester
.
pump
();
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
enter
);
// Select 'two', should work on web too
.
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
space
);
// Select 'two'
.
await
tester
.
pump
();
await
tester
.
pump
();
...
...
packages/flutter/test/material/ink_well_test.dart
View file @
0351c74a
...
...
@@ -4,6 +4,7 @@
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/src/services/keyboard_key.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/gestures.dart'
;
...
...
@@ -75,6 +76,38 @@ void main() {
expect
(
log
,
equals
(<
String
>[
'tap-down'
,
'tap-cancel'
]));
});
testWidgets
(
'InkWell invokes activation actions when expected'
,
(
WidgetTester
tester
)
async
{
final
List
<
String
>
log
=
<
String
>[];
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Shortcuts
(
shortcuts:
<
LogicalKeySet
,
Intent
>{
LogicalKeySet
(
LogicalKeyboardKey
.
space
):
const
ActivateIntent
(),
LogicalKeySet
(
LogicalKeyboardKey
.
enter
):
const
ButtonActivateIntent
(),
},
child:
Material
(
child:
Center
(
child:
InkWell
(
autofocus:
true
,
onTap:
()
{
log
.
add
(
'tap'
);
},
),
),
),
),
));
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
space
);
await
tester
.
pump
();
expect
(
log
,
equals
(<
String
>[
'tap'
]));
log
.
clear
();
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
enter
);
await
tester
.
pump
();
expect
(
log
,
equals
(<
String
>[
'tap'
]));
});
testWidgets
(
'long-press and tap on disabled should not throw'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
Material
(
child:
Directionality
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment