This is my attempt to handle
https://github.com/flutter/flutter/issues/6537 for the AnimatedSwitcher
widget.
---------
Co-authored-by: Tong Mu <dkwingsmt@users.noreply.github.com>
Co-authored-by: Victor Sanni <victorsanniay@gmail.com>
This is my attempt to handle
https://github.com/flutter/flutter/issues/6537 for the Expansible
widget.
Co-authored-by: Tong Mu <dkwingsmt@users.noreply.github.com>
Co-authored-by: Victor Sanni <victorsanniay@gmail.com>
## What's new?
- Implemented tooltip windows for the Win32 platform
- Implemented size-to-content on Win32
- Wired up the window metrics event with constraints
- Updated the example application to demonstrate tooltips
- Wrote a bunch of unit tests
## 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.
---------
Co-authored-by: Matej Knopp <matej.knopp@gmail.com>
The raw widget used to make a
[Tooltip](https://api.flutter.dev/flutter/material/Tooltip-class.html).
Design doc: flutter.dev/go/codeshare-tooltip
## Constructor
```dart
class RawTooltip extends StatefulWidget {
const RawTooltip({
super.key,
required this.semanticsTooltip,
required this.tooltipBuilder,
this.enableTapToDismiss = true,
this.triggerMode = TooltipTriggerMode.longPress,
this.enableFeedback = true,
this.onTriggered,
this.hoverDelay = Duration.zero,
this.touchDelay = const Duration(milliseconds: 1500),
this.dismissDelay = const Duration(milliseconds: 100),
this.animationStyle = _kDefaultAnimationStyle,
this.positionDelegate,
required this.child,
});
```
## Properties
```dart
final String semanticsTooltip;
final TooltipComponentBuilder tooltipBuilder;
final Duration hoverDelay;
final Duration touchDelay;
final Duration dismissDelay;
final bool enableTapToDismiss;
final TooltipTriggerMode triggerMode;
final bool enableFeedback;
final TooltipTriggeredCallback? onTriggered;
final AnimationStyle animationStyle;
final TooltipPositionDelegate? positionDelegate;
final Widget child;
```
Part of [☂️ Reinforcement: Add more basic components to the core
framework](https://github.com/flutter/flutter/issues/97496)
Part of [☂️ Reinforcement: Refactor widgets from design into the core
before decoupling](https://github.com/flutter/flutter/issues/53059)
Fixes [Custom Overlay for Tooltip Widget
](https://github.com/flutter/flutter/issues/45034)
---------
Co-authored-by: Tong Mu <dkwingsmt@users.noreply.github.com>
Co-authored-by: chunhtai <47866232+chunhtai@users.noreply.github.com>
Fix#180534
## 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.
This PR fixes https://github.com/flutter/flutter/issues/173491 by adding
the missing 'Share' option to the default iOS SystemContextMenu when
shareEnabled is true.
Changes:
Added IOSSystemContextMenuItemShare to getDefaultItems in
system_context_menu.dart.
Added a widget test to ensure Share is present in the default items for
non-empty selections on iOS.
Rationale:
This aligns Flutter's default iOS text selection context menu with
native iOS behavior, ensuring users see the expected 'Share' option when
selecting text.
Demo:
Video showing Share option in iOS context menu:
https://github.com/user-attachments/assets/e04cd1f9-7d92-4147-a09b-719f03d9c625
Closes https://github.com/flutter/flutter/issues/180031
### Description
- Adds `tooltip` support to `PlatformMenuItem` and `PlatformMenu`
- Updates `platform_menu_bar_test.dart` to cover `tooltip` related
changes and makes test-specific code private
- Updates `FlutterMenuPlugin.mm` to support `tooltip`
- Updates `FlutterMenuPluginTest.mm` to cover `tooltip` related changes
https://github.com/user-attachments/assets/abafc1ec-dc2f-45ae-a3b5-1e88759dac37
<details closed><summary>Code sample</summary>
```dart
// THIS SAMPLE ONLY WORKS ON MACOS.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/// Flutter code sample for [PlatformMenuBar].
void main() => runApp(const ExampleApp());
enum MenuSelection { about, showMessage }
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: Scaffold(body: PlatformMenuBarExample()));
}
}
class PlatformMenuBarExample extends StatefulWidget {
const PlatformMenuBarExample({super.key});
@override
State<PlatformMenuBarExample> createState() => _PlatformMenuBarExampleState();
}
class _PlatformMenuBarExampleState extends State<PlatformMenuBarExample> {
String _message = 'Hello';
bool _showMessage = false;
void _handleMenuSelection(MenuSelection value) {
switch (value) {
case MenuSelection.about:
showAboutDialog(
context: context,
applicationName: 'MenuBar Sample',
applicationVersion: '1.0.0',
);
case MenuSelection.showMessage:
setState(() {
_showMessage = !_showMessage;
});
}
}
@override
Widget build(BuildContext context) {
////////////////////////////////////
// THIS SAMPLE ONLY WORKS ON MACOS.
////////////////////////////////////
// This builds a menu hierarchy that looks like this:
// Flutter API Sample
// ├ About
// ├ ──────── (group divider)
// ├ Hide/Show Message
// ├ Messages
// │ ├ I am not throwing away my shot.
// │ └ There's a million things I haven't done, but just you wait.
// └ Quit
return PlatformMenuBar(
menus: <PlatformMenuItem>[
PlatformMenu(
label: 'Flutter API Sample',
menus: <PlatformMenuItem>[
PlatformMenuItemGroup(
members: <PlatformMenuItem>[
PlatformMenuItem(
label: 'About',
tooltip: 'Show information about APP_NAME',
onSelected: () {
_handleMenuSelection(MenuSelection.about);
},
),
],
),
PlatformMenuItemGroup(
members: <PlatformMenuItem>[
PlatformMenuItem(
onSelected: () {
_handleMenuSelection(MenuSelection.showMessage);
},
shortcut: const CharacterActivator('m'),
label: _showMessage ? 'Hide Message' : 'Show Message',
tooltip: _showMessage
? 'The message will be hidden.'
: 'The message will be shown.',
),
PlatformMenu(
label: 'Messages',
menus: <PlatformMenuItem>[
PlatformMenuItem(
label: 'I am not throwing away my shot.',
shortcut: const SingleActivator(
LogicalKeyboardKey.digit1,
meta: true,
),
onSelected: () {
setState(() {
_message = 'I am not throwing away my shot.';
});
},
),
PlatformMenuItem(
label:
"There's a million things I haven't done, but just you wait.",
shortcut: const SingleActivator(
LogicalKeyboardKey.digit2,
meta: true,
),
onSelected: () {
setState(() {
_message =
"There's a million things I haven't done, but just you wait.";
});
},
),
],
),
],
),
if (PlatformProvidedMenuItem.hasMenu(
PlatformProvidedMenuItemType.quit,
))
const PlatformProvidedMenuItem(
type: PlatformProvidedMenuItemType.quit,
),
],
),
],
child: Center(
child: Text(
_showMessage
? _message
: 'This space intentionally left blank.\n'
'Show a message here using the menu.',
),
),
);
}
}
```
</details>
## 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.
<!-- 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
## What's new?
- Add `PopupWindowController`, `PopupWindowControllerDelegate`, and
`PopupWindow`
- Implement reference logic for popup windows in the test bindings
- Add tests for the popup windows API
## 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.
This PR adds `SingleActivator` mappings for IBM CUA style clipboard
accessors, with which Shift-Delete, Ctrl-Insert and Shift-Insert are
equivalent to ^X ^C ^V. These mappings are natively supported on Windows
and Linux (but not OS X).
~Not sure what to do about:~
- ~Documentation: Are ^X ^C ^V already documented?~
- ~Tests: Are there existing tests for ^X ^C ^V already? Is it possible
to mock out the clipboard so that a test of this functionality doesn't
hit the actual system clipboard?~
- ~OS X: Is it a problem that, with this change, Flutter will accept
these additional shortcuts even though they aren't a part of the
platform paradigm?~
UPDATE:
I'm not aware of existing documentation of clipboard shortcuts.
I have added tests, both of the existing ^X ^C ^V and of the IBM CUA
style mappings added by this PR, and in the current iteration the
changes do not add IBM CUA style mappings on OS X.
Fixes: #178483
## 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.
---------
Co-authored-by: Loïc Sharma <737941+loic-sharma@users.noreply.github.com>
This PR adds a new `AutovalidateMode` value:
`onUserInteractionIfError`.
This mode allows `Form` and `FormField` widgets to auto-validate **only
when a field already has an error and the user interacts with it
again**.
### Why
- Current modes (`disabled`, `always`, `onUserInteraction`, `onUnfocus`)
do not cover the case where developers want validation **only when
correcting an error**.
- This improves UX by reducing unnecessary validation calls while still
ensuring errors disappear as soon as the user fixes them.
### How
- Added `onUserInteractionIfError` to `AutovalidateMode`.
- Updated Dartdoc with detailed description and example snippet.
- Added new unit tests to validate behavior.
- Verified no regressions in other modes (`always`, `onUnfocus`,
`onUserInteraction`).
### Example
```dart
TextFormField(
autovalidateMode: AutovalidateMode.onUserInteractionIfError,
validator: (value) => value!.isEmpty ? 'Required field' : null,
)
````
---
## Related Issues
Fixes #\<INSERT\_RELATED\_ISSUE\_NUMBER\_IF\_ANY>
---
## Tests
* Added widget tests to confirm that:
* No validation occurs until a field has an error.
* Once an error exists, validation runs automatically on user
interaction.
* Resetting the form clears errors correctly.
* Regression tests ensure that `always`, `onUserInteraction`, and
`onUnfocus` modes still behave correctly.
---
## Pre-launch / Reviewer Checklist
* [x] I have read the [[Contributor
Guide](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md)](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md)
* [x] I have read the \[Tree Hygiene] wiki page and followed its
guidance
* [x] I have read and followed the \[Flutter Style Guide]
* [x] I signed the \[CLA]
* [x] I added a new enum value with clear Dartdoc
(`onUserInteractionIfError`)
* [x] I added example code in the Dartdoc
* [x] I added new widget/unit tests for the new mode
* [x] All existing and new tests pass
* [x] I ran `flutter analyze` and fixed all issues
* [x] No breaking changes introduced (or marked accordingly)
---
## Breaking Change
* [x] Yes
* [x] No
---
## Screenshots / Demo (if applicable)
*(N/A — logic-only change)*
---
## Reviewer Notes
* The new mode reduces unnecessary validation until the user corrects an
error.
* All tests confirm correct behavior and no regressions in existing
modes.
---------
Co-authored-by: Loïc Sharma <737941+loic-sharma@users.noreply.github.com>
Fixed an issue #169659
This PR improves the StretchingOverscrollIndicator to better match
native Android behavior.
- Previously, the stretch effect worked well only for slow dragging, and
during fast flings it was absent or felt clipped.
- Implemented a Simulation-based animation that responds naturally to
both slow drags and high-velocity flings.
- The result closely resembles the native Android overscroll behavior
while maintaining Flutter's performance characteristics.
This change ensures that momentum-based gestures produce a more natural
and intuitive overscroll experience, especially for users accustomed to
native Android scroll views.
## Fling
[fling](https://github.com/user-attachments/assets/3944eef3-baaa-47df-82ca-9c49d4283fe4)
## Pull And Reduce
Also, a very similar animation is implemented when pulling as well.
[pull](https://github.com/user-attachments/assets/2a3025dc-0996-403d-b58b-d07f25487cda)
## 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.
---------
Co-authored-by: Tong Mu <dkwingsmt@users.noreply.github.com>
Co-authored-by: Victor Sanni <victorsanniay@gmail.com>
This change fixes a crash in `EditableText` that occurs when the text
editing value changes between two scrolls, when the second scroll ends
`_dataWhenToolbarShowScheduled` will be invalidated. If the second
scroll ends before the post frame callback scheduled by the first scroll
has a chance to execute, there will be a crash because
`_dataWhenToolbarShowScheduled` is being accessed while null.
This change also invalidates a scheduled toolbar if the text editing
value has changed before the post-frame callback has a chance to run.
Fixes#179164
## 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.
---------
Co-authored-by: Renzo Olivares <roliv@google.com>