Implement CupertinoMenu and CupertinoNestedMenu#137936
Conversation
|
Thank you very much for putting this together! I'll block out some time to go through the design. On basing it off of the pull_down_package, that might be fine, but the most foolproof way to make the lawyers happy is if @notDmDrl was willing to sign a CLA. If not, that's perfectly fine and we can see what guidance is available. |
|
@MitchellGoodwin @davidhicks980 I signed CLA |
Thank you! |
|
@notDmDrl just for the complete avoidance of doubt, can you confirm whether you are ok with this code landing with the usual Flutter license and copyright rather than your MIT license and copyright? |
|
@Hixie, yes, I am ok with it :) If there is anything that needs to be done with my package for this PR to land, please let me know |
|
Thanks @Piinks and team for taking a look and giving feedback! I'm still moving things around and fixing issues so I appreciate you all directing me towards any code I may have forgotten to prune. Also, some features that were missing have since been added -- in particular, sticky submenu headers. Whenever I have a moment, I'll draft up an overview of the mechanics of the menu in case any of my comments are ambiguous. Screen.Recording.2023-11-12.at.7.34.06.AM.mov |
Piinks
left a comment
There was a problem hiding this comment.
As this is still a draft I have not been through it entirely, but I wanted to ask:
- Why should this be in the framework instead of in a separate package? We typically ask this in so far as weighing the maintenance burden of adopting this into the framework.
- Can it be split up into multiple PRs so it is easier to review? I think I saw mention of different features that have been added here. Landing a basic version and adding features in follow up PRs might be easier to do, since reviewers can better focus on one aspect at a time rather than everything all at once.
|
Sounds great.
Whoops, I meant this, but you said it a lot more clearly!
I'm asking this here but it could also be asked in the first PR. I spent some time trying to wrap this around the MenuAnchor, but there were a few problems. The implementation appears to have changed since I last took a look -- I think it's now using an OverlayPortal instead of an OverlayEntry, and the bulk of the widget has moved out of the _MenuAnchorState._open method. However, it'd still be hard to work around the following:
@override
Widget build(BuildContext context) {
Widget child = OverlayPortal(
controller: _overlayController,
overlayChildBuilder: (BuildContext context) {
return _Submenu( // Submenu
anchor: this,
menuStyle: widget.style,
alignmentOffset: widget.alignmentOffset ?? Offset.zero,
menuPosition: _menuPosition,
clipBehavior: widget.clipBehavior,
menuChildren: widget.menuChildren,
crossAxisUnconstrained: widget.crossAxisUnconstrained,
);
},
child: _buildContents(context),
);
//...
Screen.Recording.2023-11-28.at.3.15.28.PM.mov
I actually began working on this menu using overlays, but there were some more issues I came across. When scaling nested layers, the untransformed position of the nested anchor couldn't be easily be accessed via context.renderObject(), because the position would be affected by individual widget scaling and the scale of the entire menu. Scaling of underlying layers led to fragile alignment between the top nested anchor and the bottom nested anchor, which need to align perfectly after the menu has fully closed. MatrixUtils could be used to perform an inverse transform, but complexity grew to a point where the FlowDelegate appeared to be a much simpler solution. Simulator.Screen.Recording.-.iPhone.15.Pro.-.2023-11-28.at.15.50.45.mp4Simulator.Screen.Recording.-.iPhone.15.Pro.-.2023-11-28.at.16.07.32.mp4
// Runs a simulation on the given animation controller, and returns whether or
// not the simulation has stopped running.
Future<bool> _runSimulation({
required _AnimationControllerWithStatusOverride controller,
required SpringSimulation simulation,
required bool forward,
}) {
final Completer<bool> simulationCompleter = Completer<bool>();
// Each layer has an animation controller that serves as a source-of-truth
// regarding the opened/opening/closed/closing status of the menu layer.
controller
..overrideStatus(
forward
? AnimationStatus.forward
: AnimationStatus.reverse,
)
..animateWith(simulation)
.whenCompleteOrCancel(() {
if (!controller.isAnimating) {
controller.overrideStatus(
forward
? AnimationStatus.completed
: AnimationStatus.dismissed,
);
simulationCompleter.complete(true);
} else {
simulationCompleter.complete(false);
}
});
return simulationCompleter.future;
}
// Sums all current layer animations. A function is used instead of a
// CompoundAnimation to make it easier to add/remove animations.
void _updateAnimationValue() {
double value = 0;
for (
final _AnimationControllerWithStatusOverride controller
in _layerIdToAnimation.values
) {
value += controller.value;
}
_nestingAnimation?.value = value;
}Simulator.Screen.Recording.-.iPhone.15.Pro.-.2023-11-28.at.16.54.03.mp4Simulator.Screen.Recording.-.iPhone.15.Pro.-.2023-11-28.at.16.53.32.mp4Anyways, sorry for the essay! Also, I went back and fixed some of the language.. let me know if it makes sense, though. I'll start splitting things up and sending PRs to get feedback. Thank you for taking the time to look through everything -- hopefully we can start landing features! |
|
@davidhicks980 These screenshots look epic. Anxiously awaiting this! Thanks so much for your work 👍 🥇 👍 🥇 |
|
Quick update on this: I did a small rewrite to use a MenuAnchor that exposed an "overlayChildBuilder" on the MenuAnchor base class and it seems to work well at the moment. Also removed most of the hacky bits. I'll submit a PR soon. @protected
Widget overlayChildBuilder(BuildContext context) {
return _Submenu(
anchor: this,
menuStyle: widget.style,
alignmentOffset: widget.alignmentOffset ?? Offset.zero,
menuPosition: _menuPosition,
clipBehavior: widget.clipBehavior,
menuChildren: widget.menuChildren,
crossAxisUnconstrained: widget.crossAxisUnconstrained,
);
} |
…onsider preventing scroll once the menu layer begins closing.
6dd5ab5 to
6bd9029
Compare
|
@davidhicks980 Thanks for the work! Looking forward to it |
|
Any update on this? Would love for some way to try this out in the interim @davidhicks980, this is just what I need for my app. |
|
@JaidynBluesky If you need all of the features right now, you should be able to copy the menu_item.dart and the menu.dart: https://github.com/flutter/flutter/blob/6bd90293300da86e31d9f0644c5e21a8e52c1a82/packages/flutter/lib/src/cupertino/menu.dart Just place menu.dart and menu_item.dart in your project folder and replace the local imports with a single "import package:flutter/cupertino": /// In menu.dart + menu_item.dart
/// Replace this:
import 'colors.dart';
import 'constants.dart';
import 'icons.dart';
/// With this
import 'package:flutter/cupertino.dart';From there, you should just be able to import like any other file: /// Import from wherever you copied the files
import 'menu_item.dart';
import 'menu.dart';
///.... Use like any other widget
CupertinoMenuButton<int>(
itemBuilder: (BuildContext context) {
return <CupertinoMenuEntry<int>>[
const CupertinoMenuItem<int>(value: 1, child: Text('A')),
const CupertinoMenuItem<int>(value: 2, child: Text('B')),
const CupertinoMenuItem<int>(value: 3, child: Text('C')),
CupertinoNestedMenu<int>(
itemBuilder: (BuildContext context) {
return [
const CupertinoMenuItem<int>(value: 1, child: Text('D')),
const CupertinoMenuItem<int>(value: 2, child: Text('E')),
const CupertinoMenuItem<int>(value: 3, child: Text('F')),
];
},
subtitle: const Text('Subtitle'),
title: const TextSpan(text: 'Nested Menu'),
),
];
},
child: Icon(CupertinoIcons.plus, size: 24)
);
///....
(I'm not on a device I can test at the moment, so sorry in advance for any errors you may encounter. Let me know if anything is complicated though): That said, if you only need a simple menu with a single layer of items, the new version based on MenuAnchor will probably be closer to the final version of the menu, and has many more tests: |
|
Hey @davidhicks980, we just came across this in triage today. Is #143712 meant to replace this PR? If so, should we close this? |
|
@Piinks - yes to both! I'll go ahead and close. |
…using RawMenuAnchor (#174695) This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves #60298, notDmDrl/pull_down_button#26, #137936. https://github.com/user-attachments/assets/551f2169-cac4-4078-890b-6728ab9c2ae5 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…MenuItem using RawMenuAnchor (#174695)" (#182010) <!-- start_original_pr_link --> Reverts: #174695 <!-- end_original_pr_link --> <!-- start_initiating_author --> Initiated by: jtmcdole <!-- end_initiating_author --> <!-- start_revert_reason --> Reason for reverting: post submits are broken Please do not directly add to the merge queue until all presubmits pass. #21 main.<anonymous closure> (file:///C:/b/s/w/ir/x/w/flutter/packages/flutter/test/cupertino/menu_anchor_test.dart:969:18) <!-- end_revert_reason --> <!-- start_original_pr_author --> Original PR Author: davidhicks980 <!-- end_original_pr_author --> <!-- start_reviewers --> Reviewed By: {dkwingsmt} <!-- end_reviewers --> <!-- start_revert_body --> This change reverts the following previous change: This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, and `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves #60298, notDmDrl/pull_down_button#26, #137936. https://github.com/user-attachments/assets/551f2169-cac4-4078-890b-6728ab9c2ae5 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md <!-- end_revert_body --> Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
…using RawMenuAnchor (flutter#174695) This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves flutter#60298, notDmDrl/pull_down_button#26, flutter#137936. https://github.com/user-attachments/assets/551f2169-cac4-4078-890b-6728ab9c2ae5 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…MenuItem using RawMenuAnchor (flutter#174695)" (flutter#182010) <!-- start_original_pr_link --> Reverts: flutter#174695 <!-- end_original_pr_link --> <!-- start_initiating_author --> Initiated by: jtmcdole <!-- end_initiating_author --> <!-- start_revert_reason --> Reason for reverting: post submits are broken Please do not directly add to the merge queue until all presubmits pass. flutter#21 main.<anonymous closure> (file:///C:/b/s/w/ir/x/w/flutter/packages/flutter/test/cupertino/menu_anchor_test.dart:969:18) <!-- end_revert_reason --> <!-- start_original_pr_author --> Original PR Author: davidhicks980 <!-- end_original_pr_author --> <!-- start_reviewers --> Reviewed By: {dkwingsmt} <!-- end_reviewers --> <!-- start_revert_body --> This change reverts the following previous change: This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, and `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves flutter#60298, notDmDrl/pull_down_button#26, flutter#137936. https://github.com/user-attachments/assets/551f2169-cac4-4078-890b-6728ab9c2ae5 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md <!-- end_revert_body --> Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
…using RawMenuAnchor (flutter#174695) This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves flutter#60298, notDmDrl/pull_down_button#26, flutter#137936. https://github.com/user-attachments/assets/551f2169-cac4-4078-890b-6728ab9c2ae5 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…MenuItem using RawMenuAnchor (flutter#174695)" (flutter#182010) <!-- start_original_pr_link --> Reverts: flutter#174695 <!-- end_original_pr_link --> <!-- start_initiating_author --> Initiated by: jtmcdole <!-- end_initiating_author --> <!-- start_revert_reason --> Reason for reverting: post submits are broken Please do not directly add to the merge queue until all presubmits pass. flutter#21 main.<anonymous closure> (file:///C:/b/s/w/ir/x/w/flutter/packages/flutter/test/cupertino/menu_anchor_test.dart:969:18) <!-- end_revert_reason --> <!-- start_original_pr_author --> Original PR Author: davidhicks980 <!-- end_original_pr_author --> <!-- start_reviewers --> Reviewed By: {dkwingsmt} <!-- end_reviewers --> <!-- start_revert_body --> This change reverts the following previous change: This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, and `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves flutter#60298, notDmDrl/pull_down_button#26, flutter#137936. https://github.com/user-attachments/assets/551f2169-cac4-4078-890b-6728ab9c2ae5 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md <!-- end_revert_body --> Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
…MenuItem using RawMenuAnchor (flutter#174695)" (flutter#182010) <!-- start_original_pr_link --> Reverts: flutter#174695 <!-- end_original_pr_link --> <!-- start_initiating_author --> Initiated by: jtmcdole <!-- end_initiating_author --> <!-- start_revert_reason --> Reason for reverting: post submits are broken Please do not directly add to the merge queue until all presubmits pass. #21 main.<anonymous closure> (file:///C:/b/s/w/ir/x/w/flutter/packages/flutter/test/cupertino/menu_anchor_test.dart:969:18) <!-- end_revert_reason --> <!-- start_original_pr_author --> Original PR Author: davidhicks980 <!-- end_original_pr_author --> <!-- start_reviewers --> Reviewed By: {dkwingsmt} <!-- end_reviewers --> <!-- start_revert_body --> This change reverts the following previous change: This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, and `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves flutter#60298, notDmDrl/pull_down_button#26, flutter#137936. https://github.com/user-attachments/assets/551f2169-cac4-4078-890b-6728ab9c2ae5 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md <!-- end_revert_body --> Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
…using RawMenuAnchor (flutter#174695) This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves flutter#60298, notDmDrl/pull_down_button#26, flutter#137936. https://github.com/user-attachments/assets/551f2169-cac4-4078-890b-6728ab9c2ae5 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…MenuItem using RawMenuAnchor (flutter#174695)" (flutter#182010) <!-- start_original_pr_link --> Reverts: flutter#174695 <!-- end_original_pr_link --> <!-- start_initiating_author --> Initiated by: jtmcdole <!-- end_initiating_author --> <!-- start_revert_reason --> Reason for reverting: post submits are broken Please do not directly add to the merge queue until all presubmits pass. flutter#21 main.<anonymous closure> (file:///C:/b/s/w/ir/x/w/flutter/packages/flutter/test/cupertino/menu_anchor_test.dart:969:18) <!-- end_revert_reason --> <!-- start_original_pr_author --> Original PR Author: davidhicks980 <!-- end_original_pr_author --> <!-- start_reviewers --> Reviewed By: {dkwingsmt} <!-- end_reviewers --> <!-- start_revert_body --> This change reverts the following previous change: This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, and `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves flutter#60298, notDmDrl/pull_down_button#26, flutter#137936. https://github.com/user-attachments/assets/551f2169-cac4-4078-890b-6728ab9c2ae5 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md <!-- end_revert_body --> Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
…using RawMenuAnchor (#182036) This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, and `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves #60298, notDmDrl/pull_down_button#26, #137936. https://github.com/user-attachments/assets/cdaee8da-888b-4f64-8bf3-49c873f6d6e1 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ---- Edit: Reland of #174695 after revert #182010 due to breakage when tests were randomized. Per @jason-simmons - > The error seen on CI can be reproduced by running: > flutter test --test-randomize-ordering-seed=20260206 test/cupertino/menu_anchor_test.dart Thanks to those who caught the error -- sorry I didn't notice. From what I can deduce, two errors were present. **Test 1: Menus do not close on root menu internal scroll (and others)** The first error occurred due to TestPointers being created with an existing pointer number. This was fixed by using tester.nextPointer instead of a fixed number. Code: https://github.com/davidhicks980/flutter/blob/054f3b03f2ab04822760c600e4259fbd828ebd4d/packages/flutter/test/cupertino/menu_anchor_test.dart#L968 ```dart final pointer = TestPointer( 1, // Fixed with tester.nextPointer ui.PointerDeviceKind.mouse ); await tester.sendEventToBinding(pointer.hover(tester.getCenter(find.text(Tag.a.text)))); await tester.pump(); ``` **Test 2: `Menu scale rebounds to full size when swipe gesture ends`** The second error occurred due to the _SwipeRegion's GestureRecognizer outliving its state and calling didSwipeLeave on a disposed CupertinoMenuItem. <s>This shouldn't be a problem -- swiping is supposed to continue so long as a user has their pointer down -- but the CupertinoMenuItem should have checked whether it was mounted before entering code that could schedule a rebuild (e.g. _handleActivation, isSwiped)</s> Nevermind -- I realize now there isn't much of a reason for letting the swipe outlive the region, so I just disposed of the swipe when the SwipeRegion is unmounted. I still kept the mounted check. Code: https://github.com/davidhicks980/flutter/blob/054f3b03f2ab04822760c600e4259fbd828ebd4d/packages/flutter/test/cupertino/menu_anchor_test.dart#L1285 ```dart @OverRide void didSwipeLeave({bool pointerUp = false}) { // This function could be called after disposal, but _handleActivation and isSwiped both could trigger rebuilds. // Fix: // if (!mounted) { // return // } if (isEnabled && pointerUp) { _handleActivation(); } isSwiped = false; } ``` I ran an additional 500 randomized menu_anchor_test.dart runs and did not experience another exception. I believe everything should be good-to-go, but I'll pay closer attention to cocoon. --- ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…using RawMenuAnchor (flutter#182036) This PR implements `CupertinoMenuAnchor`, `CupertinoMenuItem`, and `CupertinoMenuDivider` using `RawMenuAnchor`. Resolves flutter#60298, notDmDrl/pull_down_button#26, flutter#137936. https://github.com/user-attachments/assets/cdaee8da-888b-4f64-8bf3-49c873f6d6e1 Dartpad: https://dartpad.dev/8c6bba779b6a00e95582b61b132292bc @dkwingsmt ---- Edit: Reland of flutter#174695 after revert flutter#182010 due to breakage when tests were randomized. Per @jason-simmons - > The error seen on CI can be reproduced by running: > flutter test --test-randomize-ordering-seed=20260206 test/cupertino/menu_anchor_test.dart Thanks to those who caught the error -- sorry I didn't notice. From what I can deduce, two errors were present. **Test 1: Menus do not close on root menu internal scroll (and others)** The first error occurred due to TestPointers being created with an existing pointer number. This was fixed by using tester.nextPointer instead of a fixed number. Code: https://github.com/davidhicks980/flutter/blob/054f3b03f2ab04822760c600e4259fbd828ebd4d/packages/flutter/test/cupertino/menu_anchor_test.dart#L968 ```dart final pointer = TestPointer( 1, // Fixed with tester.nextPointer ui.PointerDeviceKind.mouse ); await tester.sendEventToBinding(pointer.hover(tester.getCenter(find.text(Tag.a.text)))); await tester.pump(); ``` **Test 2: `Menu scale rebounds to full size when swipe gesture ends`** The second error occurred due to the _SwipeRegion's GestureRecognizer outliving its state and calling didSwipeLeave on a disposed CupertinoMenuItem. <s>This shouldn't be a problem -- swiping is supposed to continue so long as a user has their pointer down -- but the CupertinoMenuItem should have checked whether it was mounted before entering code that could schedule a rebuild (e.g. _handleActivation, isSwiped)</s> Nevermind -- I realize now there isn't much of a reason for letting the swipe outlive the region, so I just disposed of the swipe when the SwipeRegion is unmounted. I still kept the mounted check. Code: https://github.com/davidhicks980/flutter/blob/054f3b03f2ab04822760c600e4259fbd828ebd4d/packages/flutter/test/cupertino/menu_anchor_test.dart#L1285 ```dart @OverRide void didSwipeLeave({bool pointerUp = false}) { // This function could be called after disposal, but _handleActivation and isSwiped both could trigger rebuilds. // Fix: // if (!mounted) { // return // } if (isEnabled && pointerUp) { _handleActivation(); } isSwiped = false; } ``` I ran an additional 500 randomized menu_anchor_test.dart runs and did not experience another exception. I believe everything should be good-to-go, but I'll pay closer attention to cocoon. --- ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Resolves #60298, notDmDrl/pull_down_button#26
This PR adds a CupertinoMenu, CupertinoNestedMenu, and associated widgets that increase feature parity with iOS.
I'm submitting a draft PR to collect feedback on the overall API and layout design before writing more extensive layout and API tests. I have added a few tests based on the PopupMenu widget, and I've done some manual accessibility testing across iOS, Android, and MacOS. Comments and an example have been added, but could use review. I also added TODO annotations for any particularly pressing questions I have.
I'm still fairly new to Flutter, so I apologize for any unconventional code. Let me know if there are any pieces we need to tear out or rethink. I'm interested to hear different ideas regarding how to solve this menu, so I appreciate you all taking a look!
Also, I used @notDmDrl's repo as a base for my contributions: https://github.com/notDmDrl/pull_down_button, so I'm not sure whether I should contact him with regards to signing a CLA.
Basic example:
Screen.Recording.2023-11-06.at.7.00.25.AM.mov
@MitchellGoodwin
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.