Skip to content

Instantly share code, notes, and snippets.

@p-fischer
Last active March 26, 2019 14:43
Show Gist options
  • Save p-fischer/163057034807c76766eef80cb3eda989 to your computer and use it in GitHub Desktop.
Save p-fischer/163057034807c76766eef80cb3eda989 to your computer and use it in GitHub Desktop.
Mapbox dragging
fun MapboxMap.resolveSymbolId(location: LatLng) = resolveAnnotationId(location, SymbolManager.ID_GEOJSON_LAYER)
fun MapboxMap.resolveSymbolId(screenLocation: PointF) = resolveAnnotationId(screenLocation, SymbolManager.ID_GEOJSON_LAYER)
/**
* Check if an annotation is located at a given coordinate.
*
* @param location click location in real world coordinates
*
* @return annotation ID if an annotation exists, null otherwise
*/
private fun MapboxMap.resolveAnnotationId(location: LatLng, vararg layerIds: String): Long? =
resolveAnnotationId(projection.toScreenLocation(location), *layerIds)
/**
* Check if an annotation is located at a given coordinate.
*
* @param screenLocation click location in device coordinates
*
* @return annotation ID if an annotation exists, null otherwise
*/
private fun MapboxMap.resolveAnnotationId(screenLocation: PointF, vararg layerIds: String): Long?
{
val features = queryRenderedFeatures(screenLocation, *layerIds)
if (features.isNotEmpty())
{
return features[0].getProperty("id").asLong
}
return null
}
import android.graphics.PointF
import android.view.MotionEvent
import android.view.View
import com.anfema.pingonaut.utils.Log
import com.anfema.pingonaut.utils.resolveSymbolId
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.plugins.annotation.OnSymbolDragListener
import com.mapbox.mapboxsdk.plugins.annotation.Symbol
import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager
/**
* Make a single symbol draggable.
*
* @param onSymbolDragListener optional interface to receive dragging callback events
*/
class SymbolDraggingHandler(private val mapBox: MapboxMap, private val symbolManager: SymbolManager, private val onSymbolDragListener: OnSymbolDragListener?) : View.OnTouchListener
{
var symbol: Symbol? = null
private var touchDelta = PointF() // initial distance of touch event to anchor of symbol icon
private var isDragged: Boolean = false
override fun onTouch(v: View?, event: MotionEvent): Boolean
{
val symbol = symbol ?: return false
val action = event.actionMasked
if (action == MotionEvent.ACTION_DOWN)
{
if (isSymbolTouched(event, symbol))
{
isDragged = true
val initialScreenLocation = mapBox.projection.toScreenLocation(symbol.latLng)
touchDelta.apply {
x = initialScreenLocation.x - event.x
y = initialScreenLocation.y - event.y
}
}
}
if (isDragged)
{
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP)
{
isDragged = false
onSymbolDragListener?.onAnnotationDragFinished(symbol)
}
else
{
val latLng = mapBox.projection.fromScreenLocation(PointF(event.x + touchDelta.x, event.y + touchDelta.y))
symbol.latLng = latLng
symbolManager.update(symbol)
Log.d("Marker", "position $latLng")
onSymbolDragListener?.onAnnotationDrag(symbol)
}
return true
}
else
{
return false
}
}
private fun isSymbolTouched(event: MotionEvent, symbol: Symbol) = mapBox.resolveSymbolId(PointF(event.x, event.y)) == symbol.id
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment