Skip to content

Instantly share code, notes, and snippets.

@bubenheimer
Last active November 11, 2022 17:46
Show Gist options
  • Save bubenheimer/fe7580248a7f7f905f05b70ceaeb97ed to your computer and use it in GitHub Desktop.
Save bubenheimer/fe7580248a7f7f905f05b70ceaeb97ed to your computer and use it in GitHub Desktop.
MarkerState encapsulation
import androidx.compose.runtime.*
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.compose.DragState.*
import com.google.maps.android.compose.GoogleMapComposable
import com.google.maps.android.compose.Marker
import com.google.maps.android.compose.MarkerState
import kotlinx.coroutines.flow.onCompletion
@Immutable
interface DragOps {
fun onMove(position: LatLng)
fun onCancel()
fun onEnd()
}
@Composable
@GoogleMapComposable
fun Marker(
modelPosition: LatLng,
draggable: Boolean,
/* ... */
onDrag: ((LatLng) -> Unit) -> DragOps
) {
val markerState: MarkerState = remember { MarkerState() }
Marker(
markerState,
draggable = draggable,
/* ... */
)
var dragOps: DragOps? by remember { mutableStateOf(null) }
// Sync marker state to model if model position changed without dragging;
// if model position simply aligns with markerState nothing happens
LaunchedEffect(modelPosition) {
if (dragOps == null) markerState.position = modelPosition
}
val currentOnDrag: ((LatLng) -> Unit) -> DragOps by rememberUpdatedState(onDrag)
// Naive dragging observer that would not work reliably currently
LaunchedEffect(Unit) {
snapshotFlow { markerState.dragState to markerState.position }
.onCompletion {
dragOps?.let {
dragOps = null
it.onCancel()
}
}
.collect { (dragState, position) ->
when (dragState) {
START -> {
dragOps = currentOnDrag { markerState.position = it }
dragOps!!.onMove(position)
}
DRAG -> dragOps!!.onMove(position)
END -> {
dragOps!!.let {
it.onMove(position)
dragOps = null
it.onEnd()
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment