[flutter] tab navigation does not notify the focus scope node (#86141)
This commit is contained in:
parent
731360fd84
commit
6d8c850ee7
@ -2011,11 +2011,8 @@ class _FocusTrap extends SingleChildRenderObjectWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior {
|
class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior {
|
||||||
_RenderFocusTrap(this._focusScopeNode) {
|
_RenderFocusTrap(this._focusScopeNode);
|
||||||
focusScopeNode.addListener(_currentFocusListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
FocusNode? currentFocus;
|
|
||||||
Rect? currentFocusRect;
|
Rect? currentFocusRect;
|
||||||
Expando<BoxHitTestResult> cachedResults = Expando<BoxHitTestResult>();
|
Expando<BoxHitTestResult> cachedResults = Expando<BoxHitTestResult>();
|
||||||
|
|
||||||
@ -2024,13 +2021,7 @@ class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior {
|
|||||||
set focusScopeNode(FocusScopeNode value) {
|
set focusScopeNode(FocusScopeNode value) {
|
||||||
if (focusScopeNode == value)
|
if (focusScopeNode == value)
|
||||||
return;
|
return;
|
||||||
focusScopeNode.removeListener(_currentFocusListener);
|
|
||||||
_focusScopeNode = value;
|
_focusScopeNode = value;
|
||||||
focusScopeNode.addListener(_currentFocusListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _currentFocusListener() {
|
|
||||||
currentFocus = focusScopeNode.focusedChild;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -2069,11 +2060,11 @@ class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior {
|
|||||||
|| event.buttons != kPrimaryButton
|
|| event.buttons != kPrimaryButton
|
||||||
|| event.kind != PointerDeviceKind.mouse
|
|| event.kind != PointerDeviceKind.mouse
|
||||||
|| _shouldIgnoreEvents
|
|| _shouldIgnoreEvents
|
||||||
|| currentFocus == null) {
|
|| _focusScopeNode.focusedChild == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final BoxHitTestResult? result = cachedResults[entry];
|
final BoxHitTestResult? result = cachedResults[entry];
|
||||||
final FocusNode? focusNode = currentFocus;
|
final FocusNode? focusNode = _focusScopeNode.focusedChild;
|
||||||
if (focusNode == null || result == null)
|
if (focusNode == null || result == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@ -429,4 +430,62 @@ void main() {
|
|||||||
expect(focusNodeA.hasFocus, false);
|
expect(focusNodeA.hasFocus, false);
|
||||||
expect(focusNodeB.hasFocus, true);
|
expect(focusNodeB.hasFocus, true);
|
||||||
}, variant: TargetPlatformVariant.desktop());
|
}, variant: TargetPlatformVariant.desktop());
|
||||||
|
|
||||||
|
testWidgets('A Focused text-field will lose focus when clicking outside of its hitbox with a mouse on desktop after tab navigation', (WidgetTester tester) async {
|
||||||
|
final FocusNode focusNodeA = FocusNode();
|
||||||
|
final FocusNode focusNodeB = FocusNode();
|
||||||
|
final Key key = UniqueKey();
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: ListView(
|
||||||
|
children: <Widget>[
|
||||||
|
const TextField(),
|
||||||
|
const TextField(),
|
||||||
|
TextField(
|
||||||
|
focusNode: focusNodeA,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
key: key,
|
||||||
|
height: 200,
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
focusNode: focusNodeB,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// Tab over to the 3rd text field.
|
||||||
|
for (int i = 0; i < 3; i += 1) {
|
||||||
|
await tester.sendKeyDownEvent(LogicalKeyboardKey.tab);
|
||||||
|
await tester.sendKeyUpEvent(LogicalKeyboardKey.tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(focusNodeA.hasFocus, true);
|
||||||
|
expect(focusNodeB.hasFocus, false);
|
||||||
|
|
||||||
|
// Click on the container to not hit either text field.
|
||||||
|
final TestGesture down2 = await tester.startGesture(tester.getCenter(find.byKey(key)), kind: PointerDeviceKind.mouse);
|
||||||
|
await tester.pump();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await down2.up();
|
||||||
|
await down2.removePointer();
|
||||||
|
|
||||||
|
expect(focusNodeA.hasFocus, false);
|
||||||
|
expect(focusNodeB.hasFocus, false);
|
||||||
|
|
||||||
|
// Second text field can still gain focus.
|
||||||
|
|
||||||
|
final TestGesture down3 = await tester.startGesture(tester.getCenter(find.byType(TextField).last), kind: PointerDeviceKind.mouse);
|
||||||
|
await tester.pump();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await down3.up();
|
||||||
|
await down3.removePointer();
|
||||||
|
|
||||||
|
expect(focusNodeA.hasFocus, false);
|
||||||
|
expect(focusNodeB.hasFocus, true);
|
||||||
|
}, variant: TargetPlatformVariant.desktop());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user