Skip to content

Full Keyboard Access on iOS Breaks External Keyboard Navigation in Flutter App #166683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
SaadSafan opened this issue Apr 7, 2025 · 4 comments
Assignees
Labels
a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: text input Entering text in a text field or keyboard related problems e: device-specific Only manifests on certain devices framework flutter/packages/flutter repository. See also f: labels. fyi-accessibility For the attention of Framework Accessibility team fyi-text-input For the attention of Text Input team P2 Important issues not at the top of the work list platform-ios iOS applications specifically team-ios Owned by iOS platform team triaged-ios Triaged by iOS platform team

Comments

@SaadSafan
Copy link

SaadSafan commented Apr 7, 2025

Description

Basic support for Full Keyboard Access (FKA) should now be available as noted here:

With flutter/engine#56842 and #159811 merged I think the basic FKA support should be there. I'm going to close this soon (after verifying the implementation works in certain apps) and create new issues for the remaining items (see the PR description of flutter/engine#56606). Please file issues for FKA-related bugs and feature requests, thank you!

Originally posted by @LongCatIsLooong in #76497

However, there is an issue when using an external keyboard with Full Keyboard Access enabled:

When connecting an external keyboard to an iOS device, Flutter apps typically function correctly. However, once "Full Keyboard Access" is enabled in iOS Accessibility settings, the external keyboard stops responding. The app becomes unresponsive to keyboard inputs, making navigation and button interactions impossible.

Steps to reproduce

  1. Run the Flutter app (see minimal sample below) on an iOS device or simulator.
  2. Connect an external keyboard. Verify that the keyboard works normally (e.g., text input and focus navigation function correctly).
  3. On the iOS device, go to Settings > Accessibility > Full Keyboard Access and enable it.
  4. Return to the app and observe that the external keyboard no longer allows navigation or interaction with UI elements (buttons, text fields, etc.).

Expected results

The app should continue to function normally and accept external keyboard input for navigation and actions even when Full Keyboard Access is enabled.

Actual results

Enabling Full Keyboard Access causes the app to lose responsiveness to external keyboard events. Neither navigation nor button clicks work, making the app unusable for keyboard users.

Code sample

Code sample
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: FocusExamplePage(),
    );
  }
}

class FocusExamplePage extends StatefulWidget {
  const FocusExamplePage({super.key});

  @override
  State<FocusExamplePage> createState() => _FocusExamplePageState();
}

class _FocusExamplePageState extends State<FocusExamplePage> {
  final FocusNode _customFocusNode = FocusNode();

  @override
  void dispose() {
    _customFocusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Focus Border Example'),
        actions: [
          IconButton(
            style: ButtonStyle(
              side: WidgetStateProperty.resolveWith<BorderSide>(
                (states) => states.contains(WidgetState.focused)
                    ? const BorderSide(color: Colors.blue, width: 2)
                    : BorderSide.none,
              ),
            ),
            onPressed: () {},
            icon: const Icon(Icons.settings),
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            // ElevatedButton with focus border
            ElevatedButton(
              style: ButtonStyle(
                side: WidgetStateProperty.resolveWith<BorderSide>(
                  (states) => states.contains(WidgetState.focused)
                      ? const BorderSide(color: Colors.blue, width: 2)
                      : BorderSide.none,
                ),
              ),
              onPressed: () {},
              child: const Text('First Button'),
            ),

            const SizedBox(height: 20),

            // TextButton with focus border
            TextButton(
              style: ButtonStyle(
                side: WidgetStateProperty.resolveWith<BorderSide>(
                  (states) => states.contains(WidgetState.focused)
                      ? const BorderSide(color: Colors.blue, width: 2)
                      : BorderSide.none,
                ),
              ),
              onPressed: () {},
              child: Text('Second Button'),
            ),

            const SizedBox(height: 20),

            // TextField with custom focus border
            const TextField(
              decoration: InputDecoration(
                labelText: 'Type something',
                focusedBorder: OutlineInputBorder(
                  borderSide: BorderSide(color: Colors.blue, width: 2),
                ),
              ),
            ),

            const SizedBox(height: 20),

            // Custom focusable widget
            Focus(
              focusNode: _customFocusNode,
              child: Builder(
                builder: (context) {
                  final isFocused = Focus.of(context).hasFocus;
                  return Container(
                    width: 100,
                    height: 100,
                    decoration: BoxDecoration(
                      color: Colors.grey[200],
                      border: isFocused
                          ? Border.all(color: Colors.blue, width: 2)
                          : null,
                    ),
                    alignment: Alignment.center,
                    child: const Icon(Icons.star, size: 40),
                  );
                },
              ),
            ),

            const SizedBox(height: 20),

            // IconButton with focus border
            IconButton(
              style: ButtonStyle(
                side: WidgetStateProperty.resolveWith<BorderSide>(
                  (states) => states.contains(WidgetState.focused)
                      ? const BorderSide(color: Colors.blue, width: 2)
                      : BorderSide.none,
                ),
              ),
              onPressed: () {},
              icon: const Icon(Icons.settings),
            ),
          ],
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration
FKA.deactivated.mov
FKA.activated.mov

Flutter Doctor output

Doctor output
[✓] Flutter (Channel beta, 3.31.0-0.1.pre, on macOS 15.3.2 24D81 darwin-arm64, locale en-US) [739ms]
    • Flutter version 3.31.0-0.1.pre on channel beta
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision fce807530a (3 weeks ago), 2025-03-17 16:47:17 +0000
    • Engine revision 50f226569f
    • Dart version 3.8.0 (build 3.8.0-171.0.dev)
    • DevTools version 2.44.0

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [1,272ms]
    • Android SDK 
    • Platform android-35, build-tools 35.0.0
    • Java binary
      This JDK is specified in your Flutter configuration.
      To change the current JDK, run: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment JBR-17.0.12+1-1087.25-nomod (build 17.0.12+1-b1087.25)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.2) [793ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16C5032a
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [11ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.2) [10ms]
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.3+-79915917-b509.11)

[✓] VS Code (version 1.99.0) [9ms]
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.108.0

[✓] Connected device (6 available) [6.2s]
    • iPhone 12 Pro (wireless) (mobile) • 00008101-001348201A98001E            • ios            • iOS 18.4 22E5232a


[✓] Network resources [246ms]
    • All expected network resources are available.

• No issues found!
@maheshj01 maheshj01 added the in triage Presently being triaged by the triage team label Apr 7, 2025
@maheshj01
Copy link
Member

maheshj01 commented Apr 8, 2025

Hey @SaadSafan, Thanks for filing the issue. What device are you seeing this issue on is that a physical device? I tried to reproduce it on iphone 16 plus simulator IOS 18 and I was not able to reproduce it

Screen.Recording.2025-04-07.at.18.59.16.mov
flutter doctor -v

master

✓] Flutter (Channel master, 3.31.0-1.0.pre.345, on macOS 15.1.1 24B2091 darwin-arm64, locale en-US) [2.6s]
    • Flutter version 3.31.0-1.0.pre.345 on channel master at /Users/mahesh/Development/flutter_master
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 9ce60b743d (2 hours ago), 2025-03-31 23:50:27 +0300
    • Engine revision 9ce60b743d
    • Dart version 3.8.0 (build 3.8.0-245.0.dev)
    • DevTools version 2.45.0-dev.0

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [3.1s]
    • Android SDK at /Users/mahesh/Library/Android/sdk
    • Platform android-35, build-tools 35.0.0
    • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.0) [1,745ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16A242d
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [147ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.3) [146ms]
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)

[✓] IntelliJ IDEA Community Edition (version 2021.2.1) [144ms]
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 61.2.4
    • Dart plugin version 212.5080.8

[✓] VS Code (version 1.96.2) [19ms]
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.102.0

[✓] Connected device (2 available) [7.0s]
    • macOS (desktop) • macos  • darwin-arm64   • macOS 15.1.1 24B2091 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 131.0.6778.265

[✓] Network resources [688ms]
    • All expected network resources are available.

• No issues found!

stable

[✓] Flutter (Channel stable, 3.29.2, on macOS 15.1.1 24B2091 darwin-arm64, locale en-US) [822ms]
    • Flutter version 3.29.2 on channel stable at /Users/mahesh/Development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision c236373904 (2 weeks ago), 2025-03-13 16:17:06 -0400
    • Engine revision 18b71d647a
    • Dart version 3.7.2
    • DevTools version 2.42.3
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [3.2s]
    • Android SDK at /Users/mahesh/Library/Android/sdk
    • Platform android-35, build-tools 35.0.0
    • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.0) [3.1s]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16A242d
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [136ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.3) [135ms]
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)

[✓] IntelliJ IDEA Community Edition (version 2021.2.1) [134ms]
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 61.2.4
    • Dart plugin version 212.5080.8

[✓] VS Code (version 1.96.2) [18ms]
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.102.0

[✓] Connected device (4 available) [6.7s]
    • iPad Pro 11-inch (M4) (mobile)  • A97192B5-5CFD-4164-BF2A-A6E2972614FF • ios            • com.apple.CoreSimulator.SimRuntime.iOS-18-0
      (simulator)
    • macOS (desktop)                 • macos                                • darwin-arm64   • macOS 15.1.1 24B2091 darwin-arm64
    • Mac Designed for iPad (desktop) • mac-designed-for-ipad                • darwin         • macOS 15.1.1 24B2091 darwin-arm64
    • Chrome (web)                    • chrome                               • web-javascript • Google Chrome 131.0.6778.265

[✓] Network resources [294ms]
    • All expected network resources are available.

! Doctor found issues in 1 category.

@maheshj01 maheshj01 added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Apr 8, 2025
@SaadSafan
Copy link
Author

Hey @maheshj01, thank you for testing.
I was able to reproduce this on a real device—iPhone 12 Pro Max running iOS 18.4. I also tested it just now on the simulator for iPhone 16 Pro Max running iOS 18.2, and it actually worked.
However, I tried it with the simulator for iPhone 15 Pro running iOS 17.5, and I was able to reproduce the problem there as well.

Screen.Recording.2025-04-08.at.10.mp4

@github-actions github-actions bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Apr 8, 2025
@maheshj01
Copy link
Member

Thanks for the details @SaadSafan, Unfortunately I am unable to reproduce it on my end. Given that you are able to reproduce on some of the devices I am going to label this issue as device specific for further investigation.

Screen.Recording.2025-04-08.at.19.43.32.mov
flutter doctor -v

master

✓] Flutter (Channel master, 3.31.0-1.0.pre.345, on macOS 15.1.1 24B2091 darwin-arm64, locale en-US) [2.6s]
    • Flutter version 3.31.0-1.0.pre.345 on channel master at /Users/mahesh/Development/flutter_master
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 9ce60b743d (2 hours ago), 2025-03-31 23:50:27 +0300
    • Engine revision 9ce60b743d
    • Dart version 3.8.0 (build 3.8.0-245.0.dev)
    • DevTools version 2.45.0-dev.0

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [3.1s]
    • Android SDK at /Users/mahesh/Library/Android/sdk
    • Platform android-35, build-tools 35.0.0
    • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.0) [1,745ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16A242d
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [147ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.3) [146ms]
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)

[✓] IntelliJ IDEA Community Edition (version 2021.2.1) [144ms]
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 61.2.4
    • Dart plugin version 212.5080.8

[✓] VS Code (version 1.96.2) [19ms]
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.102.0

[✓] Connected device (2 available) [7.0s]
    • macOS (desktop) • macos  • darwin-arm64   • macOS 15.1.1 24B2091 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 131.0.6778.265

[✓] Network resources [688ms]
    • All expected network resources are available.

• No issues found!

@maheshj01 maheshj01 added a: text input Entering text in a text field or keyboard related problems e: device-specific Only manifests on certain devices platform-ios iOS applications specifically a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) team-ios Owned by iOS platform team framework flutter/packages/flutter repository. See also f: labels. and removed in triage Presently being triaged by the triage team a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) labels Apr 8, 2025
@justinmc justinmc added the fyi-text-input For the attention of Text Input team label Apr 10, 2025
@justinmc
Copy link
Contributor

FYI @LongCatIsLooong from triage (who is out for the moment).

@cbracken cbracken added a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) fyi-accessibility For the attention of Framework Accessibility team P2 Important issues not at the top of the work list triaged-ios Triaged by iOS platform team labels May 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: text input Entering text in a text field or keyboard related problems e: device-specific Only manifests on certain devices framework flutter/packages/flutter repository. See also f: labels. fyi-accessibility For the attention of Framework Accessibility team fyi-text-input For the attention of Text Input team P2 Important issues not at the top of the work list platform-ios iOS applications specifically team-ios Owned by iOS platform team triaged-ios Triaged by iOS platform team
Projects
None yet
Development

No branches or pull requests

5 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy