-
Notifications
You must be signed in to change notification settings - Fork 152
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
Marker dragging: fix loss of drag events and difficulty observing marker positions #149
Comments
Regarding the loss of To make |
Regarding problems with hoisted state objects: remove I believe it is possible to completely separate the SDK's position changes and app-controlled position changes. I'm assuming that the only time the map SDK impl changes the marker position on its own is dragging. Dragging is reliably demarcated by maps-compose needs to box the SDK's dragging events. Dragging position should not generally be reflected in maps-compose marker position, but only be updated in response to To avoid visual artifacts, compose-maps needs to delay effectuating visual changes in Marker's Typically dragging callbacks will update The boolean The above proposal turns Map SDK's marker drag design on its head, replacing it with the default API a compose user would expect, and it can do it very cleanly, I believe. The only gotcha I can think of is an app's inability to influence the actual marker position on the map while the marker is being dragged. This is generally a bad idea due to visual artifacts, but there is one case I can think of where an app may choose to do it despite artifacts; more in a future comment. |
The use case I was alluding to in the last comment is marker dragging and keeping the marker from jumping out of place. When the marker starts dragging, Maps SDK moves the marker up and out of place a good amount to make it visible from underneath a user's "finger". This approach can cause a lot of problems, so in some cases one might choose to manually override the marker position upon each START/DRAG/END event to put the marker back in place. This causes visual artifacts, and is a grossly unsupported hack of map's data structures, but depending on the use case one might choose to try it anyway. Overriding marker drag position manually in this fashion would not work with the approach I sketched. Marker position set via composition during dragging will take effect only after dragging is finished. The issues with marker jump on drag were previously brought up with Maps SDK and dismissed. The main issue I saw is this: https://issuetracker.google.com/issues/35824023. If this is a concern then the best approach may be to open a new issue with Maps SDK. Perhaps it would be addressed with added leverage from @arriolac. The marker jump problem affects one of my use cases as well, where the marker needs precise repositioning upon dragging. Alternatively, hacky use cases like this could likely be implemented via the new direct access to Maps SDK's |
Upon implementing this new API, a public |
Thoughts? |
Thanks @bubenheimer for creating this issue. This is very detailed and helps us improve the API for marker dragging. I agree with a lot of the proposed changes—it will be a breaking change though and I'll label it as such. We may want to release this with any other breaking change requests/issues in the repo. |
Thanks @arriolac, makes sense. I made one clarification in the original comment that my primary use case is changing lists of markers, which is a more challenging problem than unordered collections. |
I have run a few experiments since my last comment in June, and what I've arrived at conforms with what I described above. In particular, I still believe
This behavior should be embodied in code by the Maps Compose API, not by the user. At that point |
@bubenheimer Are you able to share a minimum viable sample demonstrating the usability issues perhaps in a fork of the sample app? I think this'll give us a bit more color on how the current API is hard to work with in your use case. Thanks for your continued feedback on this issue. |
Just had to get a gist ready with a simple wrapper for NB: I am proposing this as a general approach, regardless of use case. I don't think the exposed |
Most importantly, the contract here is that the app's data model is not the sole source of truth, and updates from marker dragging need to be carried forward to the app's data model via a drag event handler. This could be worked around by the more involved approach I described in prior comments, yet that approach does not seem preferable. |
For justification of usability issues: it's not obvious how to get this kind of wrapper right, e.g. #198. It took me a bit myself to get the logic just right for updating |
One potential problem area is races between the 2 sources of truth at the time of switching (start/end of drag), which would require careful coding to know the actual truth. Perhaps not the most common scenario, but needs consideration. |
I think addressing these races can be left to the API user. A Marker change driven by the app data model can always be imposed cleanly by going down a different Compose graph subtree via |
There are small, but significant changes in the latest version of my gist: https://gist.github.com/bubenheimer/fe7580248a7f7f905f05b70ceaeb97ed In particular: The other gist changes are smaller refinements and bug fixes. The gist is the essence of what I think the Maps Compose API changes should look like. |
This is a non-breaking change following suggestions from @arriolac for addressing googlemaps#149: googlemaps#150 (comment) This PR does not add an `onDrag` callback parameter to `Marker()`, which would be a somewhat breaking change; this functionality is not strictly necessary and I see alternatives that may be preferable. Summary of changes: 1. Deprecate MarkerState.dragState and DragState enum. These were carried over from GoogleMap SDK; they are events that were mischaracterized as states. 2. Replace with MarkerState.isDragging boolean. 3. Clarify KDoc in several places. 4. Add several examples providing patterns for common use cases. 5. Organize Marker-related examples into their own folder. Fixes googlemaps#149
I don't believe the |
This is a non-breaking change following suggestions from @arriolac for addressing googlemaps#149: googlemaps#150 (comment) This PR does not add an `onDrag` callback parameter to `Marker()`, which would be a somewhat breaking change; this functionality is not strictly necessary and I see alternatives that may be preferable. Summary of changes: 1. Deprecate MarkerState.dragState and DragState enum. These were carried over from GoogleMap SDK; they are events that were mischaracterized as states. 2. Replace with MarkerState.isDragging boolean. 3. Clarify KDoc in several places. 4. Add several examples providing patterns for common use cases. 5. Organize Marker-related examples into their own folder. Fixes googlemaps#149
* fix: improve MarkerState API This is a non-breaking change following suggestions from @arriolac for addressing #149: #150 (comment) This PR does not add an `onDrag` callback parameter to `Marker()`, which would be a somewhat breaking change; this functionality is not strictly necessary and I see alternatives that may be preferable. Summary of changes: 1. Deprecate MarkerState.dragState and DragState enum. These were carried over from GoogleMap SDK; they are events that were mischaracterized as states. 2. Replace with MarkerState.isDragging boolean. 3. Clarify KDoc in several places. 4. Add several examples providing patterns for common use cases. 5. Organize Marker-related examples into their own folder. Fixes #149 * Add an example for how to efficiently create a derived list of MarkerStates from a changing model list of marker positions by collecting results from key() composable Rename marker examples folder to markerexamples for clarity * Refine example * Improve KDoc for example * Improve KDoc for example * Simplify and improve example --------- Co-authored-by: Uli Bubenheimer <bubenheimer@users.noreply.github.com>
## [5.0.3](v5.0.2...v5.0.3) (2024-06-06) ### Bug Fixes * improve MarkerState API ([#515](#515)) ([3b40b92](3b40b92)), closes [#149](#149) [/github.com//pull/150#discussion_r1016963262](https://github.com//github.com/googlemaps/android-maps-compose/pull/150/issues/discussion_r1016963262) [#149](#149)
🎉 This issue has been resolved in version 5.0.3 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
android-maps-compose 2.2.1
The current API design of
Marker
andMarkerState
poses significant challenges. This issue is a continuation of comments I made in #10; @arriolac asked to move discussion to a new issue.START
, but alsoDRAG
, and, theoretically, evenEND
.This is due to the characteristics of snapshot state in relation to events:
https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#snapshotFlow(kotlin.Function0)
I have a use case where I need to reliably detect
START
andEND
to temporarily keep a backup of the old marker location to restore in case the final marker drag location is deemed invalid by business logic.Hoisted state objects can be a suitable vessel for maintaining UI state. However, they are an anti-pattern for representing data that is ultimately maintained in an app data model. Observing requires using
snapshotFlow
for each indivdual state object, and updating implies feeding model data back to the state object in some manner.An app commonly maintains a collection of markers, so a collection of
MarkerState
objects is needed, one for each marker. Markers may be added or removed, adding significant complexity to the task of keeping separate collections of marker data in sync. Typically one will opt to recreate the entire collection if one element changes in any way.I will add more detail and proposals in comments below.
Clarification: In my main use case for this feature, markers define the corners of a polyline/polygon, so order is significant, and the marker collection is a list, where updates, inserts, and deletions can occur at any position. Keeping lists of variable size with changing marker content synchronized is a more challenging problem than for example maps of markers where order is not significant; I use the latter in another case, and it is easier to deal with.
The text was updated successfully, but these errors were encountered: