Unable to dismiss popup menu in specific iOS devices with voiceover
Copied from Google internal issue b/374241149. See this issue for more context, links, and repro video.
Unable to dismiss the popup menu by double tapping outside the menu in voice over mode in specific iOS devices.
PopupMenuButton pushes _PopupMenuRoute which extends PopupRoute which extends ModalRoute which uses for rendering the scrim.
The double tap to dismiss is handled by the ModalBarrier by calling Navigator.maybePop().
Issue: This particular call is getting stuck in some iPhones (Example: My test device is an iPhone XR with iOS version 15.5). I tested this in the Hello Flutter codelab app.
Upon further debugging, its getting stuck at exactly await lastEntry.route.willPop().
lastEntry.route here is _PopupMenuRoute.
Tracing the willPop() implementations using debug print statements, I observed the following:
- _PopupMenuRoute does not have willPop() implementation.
- PopupRoute does not have willPop() implementation.
- ModalRoute's willPop() completes and calls super.willPop().
- LocalHistoryRoute's willPop() completes and calls super.willPop().
- ... no other implementations of willPop() in between.
- Route's willPop() is called.
- But apparently the last call is getting stuck for some reason because
await lastEntry.route.willPop()is stuck without a return value here: https://github.com/flutter/flutter/blob/1d5087eb30382a763b17ddaff68011383faaa7d4/packages/flutter/lib/src/widgets/navigator.dart#L5335
Repro project
The bug can be reproduced in any flutter app with the following:
PopupMenuButton<int>(
// Set tooltip to empty to prevent the screen reader announcing
// 'show menu'.
tooltip: '',
itemBuilder: (context) {
return [
PopupMenuItem<int>(
value: 1,
child: Text('Item 1'),
),
PopupMenuItem<int>(
value: 2,
child: Text('Item 2'),
),
PopupMenuItem<int>(
value: 3,
child: Text('Item 3'),
),
];
},
),
Reproduced this issue on iOS (VoiceOver) with iPhone 7, iOS 15.8 and Android (TalkBack) with Pixel 7, Android 14.
This looks like a regression as the issue only appears on Flutter beta (depends on platforms) and master channels but not on stable 3.24.3.
- stable 3.24.3: ✅
- master 3.27.0-1.0.pre.181: ❗
- beta 3.27.0-0.1.pre:
- iOS:❗
- Android: ✅
Complete sample code
import 'package:flutter/material.dart';
/// Flutter code sample for [PopupMenuButton].
// This is the type used by the popup menu below.
enum SampleItem { itemOne, itemTwo, itemThree }
void main() => runApp(const PopupMenuApp());
class PopupMenuApp extends StatelessWidget {
const PopupMenuApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: PopupMenuExample(),
);
}
}
class PopupMenuExample extends StatefulWidget {
const PopupMenuExample({super.key});
@override
State<PopupMenuExample> createState() => _PopupMenuExampleState();
}
class _PopupMenuExampleState extends State<PopupMenuExample> {
SampleItem? selectedItem;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('PopupMenuButton')),
body: Center(
child: PopupMenuButton<SampleItem>(
initialValue: selectedItem,
tooltip: '',
onSelected: (SampleItem item) {
setState(() {
selectedItem = item;
});
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<SampleItem>>[
const PopupMenuItem<SampleItem>(
value: SampleItem.itemOne,
child: Text('Item 1'),
),
const PopupMenuItem<SampleItem>(
value: SampleItem.itemTwo,
child: Text('Item 2'),
),
const PopupMenuItem<SampleItem>(
value: SampleItem.itemThree,
child: Text('Item 3'),
),
],
),
),
);
}
}
Demo video on iOS device
https://github.com/user-attachments/assets/bc27521c-b61f-41c5-b19f-6643174adb50
flutter versions (stable, beta and master)
[✓] Flutter (Channel stable, 3.24.3, on macOS 15.0 24A335 darwin-x64, locale en-VN)
• Flutter version 3.24.3 on channel stable at /Users/huynq/Documents/GitHub/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 2663184aa7 (3 weeks ago), 2024-09-11 16:27:48 -0500
• Engine revision 36335019a8
• Dart version 3.5.3
• DevTools version 2.37.3
[!] Flutter (Channel beta, 3.27.0-0.1.pre, on macOS 15.0 24A335 darwin-x64, locale en-VN)
• Flutter version 3.27.0-0.1.pre on channel beta at /Users/huynq/Documents/GitHub/flutter_beta
! Warning: `flutter` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_beta. Consider adding /Users/huynq/Documents/GitHub/flutter_beta/bin to the front of your path.
! Warning: `dart` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_beta. Consider adding /Users/huynq/Documents/GitHub/flutter_beta/bin to the front of your path.
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 2e2c358c9b (12 hours ago), 2024-10-22 11:02:13 -0400
• Engine revision af0f0d559c
• Dart version 3.6.0 (build 3.6.0-334.3.beta)
• DevTools version 2.40.1
• If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.
[!] Flutter (Channel master, 3.27.0-1.0.pre.181, on macOS 15.0 24A335 darwin-x64, locale en-VN)
• Flutter version 3.27.0-1.0.pre.181 on channel master at /Users/huynq/Documents/GitHub/flutter_master
! Warning: `flutter` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path.
! Warning: `dart` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path.
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 7504abcc14 (45 minutes ago), 2024-10-23 10:20:40 +0800
• Engine revision 2d3f0f41b9
• Dart version 3.7.0 (build 3.7.0-50.0.dev)
• DevTools version 2.40.1
• If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.
Marking this issue as P1 to match the internal bug.
This is interesting. Hi @justinmc since you have touched this part before, I wonder if you have bandwidth to look into this?
We suspect the same issue is causing b/372446456
@huycozy Strangely I wasn't able to reproduce this using your code when I tried on a physical iPhone 7 iOS 15.6.1 with voiceover enabled or on a physical Pixel 9 Android 15 with talkback enabled. I tried on both master and v3.27.0-0.1 pre. I should just double tap to show the menu and then double tap the background to attempt to close it, right? It closed for me. I will update the iPhone to 15.8.3 and try again tomorrow.
I can't think of a reason why willPop would stall out like that.
I should just double tap to show the menu and then double tap the background to attempt to close it, right?
@justinmc When the menu is showing and VoiceOver auto-focus on the 1st item, you should do a single tap on the outside menu (underlying background) to make sure the focus is not on the 1st item anymore, then do a double tap on the outside menu again, you will see the menu cannot be dismissed.
I still can't get it! This is iOS 15.8.3 now, using master.
https://github.com/user-attachments/assets/a3282cf7-9d51-4cb8-806c-3e25f89429b3
is this issue still reproducible?
This issue is marked P1 but has had no recent status updates.
The P1 label indicates high-priority issues that are at the top of the work list. This is the highest priority level a bug can have if it isn't affecting a top-tier customer or breaking the build. Bugs marked P1 are generally actively being worked on unless the assignee is dealing with a P0 bug (or another P1 bug). Issues at this level should be resolved in a matter of months and should have monthly updates on GitHub.
Please consider where this bug really falls in our current priorities, and label it or assign it accordingly. This allows people to have a clearer picture of what work is actually planned. Thanks!
Another ping before closing. We are still waiting for repro
@chunhtai Hi, we'll verify this and share our findings here soon.
Hi @jacobsimionato, we tested the code sample in https://github.com/flutter/flutter/issues/157376#issuecomment-2431335974 on an iPhone 6s running iOS 15.3.1 and an iPhone 8 running iOS 13.5.1 on the latest stable & master but cannot seem to reproduce the issue.
Does this still reproduce for you on the latest stable/master?
Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now. If you find this problem please file a new issue with the same description, what happens, logs and the output of 'flutter doctor -v'. All system setups can be slightly different so it's always better to open new issues and reference the related ones. Thanks for your contribution.
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.