@@ -288,24 +288,24 @@ class TextField extends RoleManager {
288
288
_initializeForBlink ();
289
289
return ;
290
290
}
291
- num ? lastTouchStartOffsetX ;
292
- num ? lastTouchStartOffsetY ;
291
+ num ? lastPointerDownOffsetX ;
292
+ num ? lastPointerDownOffsetY ;
293
293
294
- editableElement.addEventListener ('touchstart ' ,
294
+ editableElement.addEventListener ('pointerdown ' ,
295
295
allowInterop ((DomEvent event) {
296
- final DomTouchEvent touchEvent = event as DomTouchEvent ;
297
- lastTouchStartOffsetX = touchEvent.changedTouches ! .last .clientX;
298
- lastTouchStartOffsetY = touchEvent.changedTouches ! .last .clientY;
296
+ final DomPointerEvent pointerEvent = event as DomPointerEvent ;
297
+ lastPointerDownOffsetX = pointerEvent .clientX;
298
+ lastPointerDownOffsetY = pointerEvent .clientY;
299
299
}), true );
300
300
301
301
editableElement.addEventListener (
302
- 'touchend ' , allowInterop ((DomEvent event) {
303
- final DomTouchEvent touchEvent = event as DomTouchEvent ;
302
+ 'pointerup ' , allowInterop ((DomEvent event) {
303
+ final DomPointerEvent pointerEvent = event as DomPointerEvent ;
304
304
305
- if (lastTouchStartOffsetX != null ) {
306
- assert (lastTouchStartOffsetY != null );
307
- final num offsetX = touchEvent.changedTouches ! .last. clientX;
308
- final num offsetY = touchEvent.changedTouches ! .last. clientY;
305
+ if (lastPointerDownOffsetX != null ) {
306
+ assert (lastPointerDownOffsetY != null );
307
+ final num deltaX = pointerEvent. clientX - lastPointerDownOffsetX ! ;
308
+ final num deltaY = pointerEvent. clientY - lastPointerDownOffsetY ! ;
309
309
310
310
// This should match the similar constant defined in:
311
311
//
@@ -314,17 +314,30 @@ class TextField extends RoleManager {
314
314
// The value is pre-squared so we have to do less math at runtime.
315
315
const double kTouchSlop = 18.0 * 18.0 ; // Logical pixels squared
316
316
317
- if (offsetX * offsetX + offsetY * offsetY < kTouchSlop) {
317
+ if (deltaX * deltaX + deltaY * deltaY < kTouchSlop) {
318
318
// Recognize it as a tap that requires a keyboard.
319
319
EnginePlatformDispatcher .instance.invokeOnSemanticsAction (
320
320
semanticsObject.id, ui.SemanticsAction .tap, null );
321
+
322
+ // We need to call focus for the following scenario:
323
+ // 1. The virtial keyboard in iOS gets dismissed by the 'Done' button
324
+ // located at the top right of the keyboard.
325
+ // 2. The user tries to focus on the input field again, either by
326
+ // VoiceOver or manually, but the keyboard does not show up.
327
+ //
328
+ // In this scenario, the Flutter framework does not send a semantic update,
329
+ // so we need to call focus after detecting a tap to make sure that the
330
+ // virtual keyboard will show.
331
+ if (semanticsObject.hasFocus) {
332
+ editableElement.focus ();
333
+ }
321
334
}
322
335
} else {
323
- assert (lastTouchStartOffsetY == null );
336
+ assert (lastPointerDownOffsetY == null );
324
337
}
325
338
326
- lastTouchStartOffsetX = null ;
327
- lastTouchStartOffsetY = null ;
339
+ lastPointerDownOffsetX = null ;
340
+ lastPointerDownOffsetY = null ;
328
341
}), true );
329
342
}
330
343
0 commit comments