-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Add spread-to-add gesture for inserting items in ReorderableListView
#172740
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
Add spread-to-add gesture for inserting items in ReorderableListView
#172740
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
48c3a47 to
918b28a
Compare
918b28a to
5598ff8
Compare
Adds SpreadGestureDetector widget that detects two-finger spread (mobile) or trackpad pinch (macOS) gestures to insert new items between list items. Key features: - Platform-specific gesture detection (Pointer API for mobile, Scale for Mac) - Insertion point calculation based on item midpoints - Spread threshold detection with visual feedback callbacks - Auto-scrolling support during spread gesture - Configurable thresholds and maximum gap height
5598ff8 to
0848d3e
Compare
ReorderableListView
…animation (#173241) When rapidly dragging items in a ReorderableList before animations complete, items would jump to their expected positions rather than smoothly transitioning. ## Problem <p align="center"> <img src="https://github.com/user-attachments/assets/0efb250c-2960-4942-959f-59eccc20cefb" alt="demo2" width="250"> </p> The issue occurs when a reorder animation is interrupted by starting a new drag operation. The interrupted animation would reset to the starting position of the original animation rather than capturing the current animated position, causing a visual jump. ## Solution This PR fixes the issue by: 1. Storing the previous target offset before updating to a new target 2. When an animation is interrupted, calculating the actual current position based on the animation's progress 3. Using this calculated position as the new starting point for the next animation <p align="center"> <img src="https://github.com/user-attachments/assets/c24e4834-1c6b-41c1-8f44-17b4c79e0993" alt="demo2" width="250"> </p> This PR is part of a series of `ReorderableList` enhancements I've developed for [TimeFinder](https://timefinder.app): - #172740 - #172380 - #172739 - #172738 Fixes #173243 ## Code Changes ```dart // Before _startOffset = offset; // After final double currentAnimValue = Curves.easeInOut.transform(_offsetAnimation\!.value); final Offset currentPosition = Offset.lerp(_startOffset, previousTarget, currentAnimValue)\!; _startOffset = currentPosition; ``` This ensures smooth transitions without visual jumping, making rapid reordering gestures feel more responsive and natural. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I listed at least one issue that this PR fixes in the description above. - [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 [migration guide] as needed. - [x] All existing and new tests are passing. - [x] The analyzer (`flutter analyze --flutter-repo`) does not report any problems on my PR. - [x] I am willing to follow-up on review comments in a timely manner. [Contributor Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md [Flutter Style Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [test-exempt]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#tests [breaking change policy]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#handling-breaking-changes [migration guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#create-a-migration-guide
…animation (flutter#173241) When rapidly dragging items in a ReorderableList before animations complete, items would jump to their expected positions rather than smoothly transitioning. ## Problem <p align="center"> <img src="https://github.com/user-attachments/assets/0efb250c-2960-4942-959f-59eccc20cefb" alt="demo2" width="250"> </p> The issue occurs when a reorder animation is interrupted by starting a new drag operation. The interrupted animation would reset to the starting position of the original animation rather than capturing the current animated position, causing a visual jump. ## Solution This PR fixes the issue by: 1. Storing the previous target offset before updating to a new target 2. When an animation is interrupted, calculating the actual current position based on the animation's progress 3. Using this calculated position as the new starting point for the next animation <p align="center"> <img src="https://github.com/user-attachments/assets/c24e4834-1c6b-41c1-8f44-17b4c79e0993" alt="demo2" width="250"> </p> This PR is part of a series of `ReorderableList` enhancements I've developed for [TimeFinder](https://timefinder.app): - flutter#172740 - flutter#172380 - flutter#172739 - flutter#172738 Fixes flutter#173243 ## Code Changes ```dart // Before _startOffset = offset; // After final double currentAnimValue = Curves.easeInOut.transform(_offsetAnimation\!.value); final Offset currentPosition = Offset.lerp(_startOffset, previousTarget, currentAnimValue)\!; _startOffset = currentPosition; ``` This ensures smooth transitions without visual jumping, making rapid reordering gestures feel more responsive and natural. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I listed at least one issue that this PR fixes in the description above. - [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 [migration guide] as needed. - [x] All existing and new tests are passing. - [x] The analyzer (`flutter analyze --flutter-repo`) does not report any problems on my PR. - [x] I am willing to follow-up on review comments in a timely manner. [Contributor Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md [Flutter Style Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [test-exempt]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#tests [breaking change policy]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#handling-breaking-changes [migration guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#create-a-migration-guide
…animation (flutter#173241) When rapidly dragging items in a ReorderableList before animations complete, items would jump to their expected positions rather than smoothly transitioning. ## Problem <p align="center"> <img src="https://github.com/user-attachments/assets/0efb250c-2960-4942-959f-59eccc20cefb" alt="demo2" width="250"> </p> The issue occurs when a reorder animation is interrupted by starting a new drag operation. The interrupted animation would reset to the starting position of the original animation rather than capturing the current animated position, causing a visual jump. ## Solution This PR fixes the issue by: 1. Storing the previous target offset before updating to a new target 2. When an animation is interrupted, calculating the actual current position based on the animation's progress 3. Using this calculated position as the new starting point for the next animation <p align="center"> <img src="https://github.com/user-attachments/assets/c24e4834-1c6b-41c1-8f44-17b4c79e0993" alt="demo2" width="250"> </p> This PR is part of a series of `ReorderableList` enhancements I've developed for [TimeFinder](https://timefinder.app): - flutter#172740 - flutter#172380 - flutter#172739 - flutter#172738 Fixes flutter#173243 ## Code Changes ```dart // Before _startOffset = offset; // After final double currentAnimValue = Curves.easeInOut.transform(_offsetAnimation\!.value); final Offset currentPosition = Offset.lerp(_startOffset, previousTarget, currentAnimValue)\!; _startOffset = currentPosition; ``` This ensures smooth transitions without visual jumping, making rapid reordering gestures feel more responsive and natural. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I listed at least one issue that this PR fixes in the description above. - [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 [migration guide] as needed. - [x] All existing and new tests are passing. - [x] The analyzer (`flutter analyze --flutter-repo`) does not report any problems on my PR. - [x] I am willing to follow-up on review comments in a timely manner. [Contributor Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md [Flutter Style Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [test-exempt]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#tests [breaking change policy]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#handling-breaking-changes [migration guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#create-a-migration-guide
Note: The feature introduced in this PR is admittedly quite niche, and I don't expect it to be merged; I've filed it here mostly as an example of a visually interesting & intuitive feature made possible through the Flutter framework and its extensibility.
Description
This PR introduces a novel interaction pattern to
ReorderableListView: the ability to insert new items by spreading two fingers (or pinching out on a trackpad) between existing list items. This gesture, first popularized by the Clear to-do list app, creates an intuitive, discoverable way for users to add items exactly where they want them in a list.The video above demonstrates the spread-to-add gesture on an iOS simulator, showing the animated placeholder and insertion behavior.
This PR is part of a series of
ReorderableListenhancements I've developed for TimeFinder:ReorderableListproxy animation for partial drag-back #172380ReorderableListitems jumping when drag direction reverses mid-animation #173241ReorderableListView#172739onReorderUpdatecallback to ReorderableListView #172738Key Features
This PR introduces a novel feature and does not address any existing issues or requests.
Implementation Details
The implementation includes:
SpreadGestureDetectorwidget that handles multi-touch and trackpad gesturesSpreadConfigDesign Considerations
Technical Architecture
Platform Support
Testing
Pre-launch Checklist
///).Breaking Change
Does your PR require Flutter developers to manually update their apps to accommodate your change?
This change is fully backward compatible. The spread-to-add functionality is disabled by default (
spreadEnabled: false) and requires explicit opt-in.