From 9895921a5ccc67dc011de0511785c9bbacbd431b Mon Sep 17 00:00:00 2001 From: Frank Knoll Date: Sat, 14 Aug 2021 15:06:21 +0200 Subject: [PATCH] Draggable marker sample (#869) --- vtm-android-example/AndroidManifest.xml | 3 + .../res/layout/activity_map_draggable.xml | 10 ++ .../android/drag/DragAndDropListener.java | 26 +++++ .../android/drag/DragGestureHandler.java | 65 +++++++++++ .../org/oscim/android/drag/DragMapView.java | 62 +++++++++++ .../android/drag/DraggableItemizedLayer.java | 82 ++++++++++++++ .../android/drag/DraggableMarkerItem.java | 43 +++++++ .../org/oscim/android/drag/ItemDragger.java | 96 ++++++++++++++++ .../test/DraggableMarkerOverlayActivity.java | 105 ++++++++++++++++++ .../src/org/oscim/android/test/Samples.java | 1 + 10 files changed, 493 insertions(+) create mode 100644 vtm-android-example/res/layout/activity_map_draggable.xml create mode 100644 vtm-android-example/src/org/oscim/android/drag/DragAndDropListener.java create mode 100644 vtm-android-example/src/org/oscim/android/drag/DragGestureHandler.java create mode 100644 vtm-android-example/src/org/oscim/android/drag/DragMapView.java create mode 100644 vtm-android-example/src/org/oscim/android/drag/DraggableItemizedLayer.java create mode 100644 vtm-android-example/src/org/oscim/android/drag/DraggableMarkerItem.java create mode 100644 vtm-android-example/src/org/oscim/android/drag/ItemDragger.java create mode 100644 vtm-android-example/src/org/oscim/android/test/DraggableMarkerOverlayActivity.java diff --git a/vtm-android-example/AndroidManifest.xml b/vtm-android-example/AndroidManifest.xml index 9e6be991..45fd562d 100644 --- a/vtm-android-example/AndroidManifest.xml +++ b/vtm-android-example/AndroidManifest.xml @@ -34,6 +34,9 @@ + diff --git a/vtm-android-example/res/layout/activity_map_draggable.xml b/vtm-android-example/res/layout/activity_map_draggable.xml new file mode 100644 index 00000000..b5dd1b75 --- /dev/null +++ b/vtm-android-example/res/layout/activity_map_draggable.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/vtm-android-example/src/org/oscim/android/drag/DragAndDropListener.java b/vtm-android-example/src/org/oscim/android/drag/DragAndDropListener.java new file mode 100644 index 00000000..04c86495 --- /dev/null +++ b/vtm-android-example/src/org/oscim/android/drag/DragAndDropListener.java @@ -0,0 +1,26 @@ +/* + * Copyright 2021 Frank Knoll + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.android.drag; + +import org.oscim.core.GeoPoint; + +public interface DragAndDropListener { + + void startDragItemAtGeoPoint(DraggableMarkerItem item, GeoPoint geoPoint); + + void ongoingDragItemToGeoPoint(DraggableMarkerItem item, GeoPoint geoPoint); + + void dropItemAtGeoPoint(DraggableMarkerItem item, GeoPoint geoPoint); +} diff --git a/vtm-android-example/src/org/oscim/android/drag/DragGestureHandler.java b/vtm-android-example/src/org/oscim/android/drag/DragGestureHandler.java new file mode 100644 index 00000000..902a6b86 --- /dev/null +++ b/vtm-android-example/src/org/oscim/android/drag/DragGestureHandler.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013 Hannes Janetzek + * Copyright 2016 devemux86 + * Copyright 2021 Frank Knoll + * + * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.android.drag; + +import android.view.MotionEvent; +import org.oscim.android.input.AndroidMotionEvent; +import org.oscim.android.input.GestureHandler; +import org.oscim.event.Gesture; +import org.oscim.map.Map; + +class DragGestureHandler extends GestureHandler { + + public static final Gesture START_DRAG = new Gesture() { + }; + public static final Gesture ONGOING_DRAG = new Gesture() { + }; + public static final Gesture END_DRAG = new Gesture() { + }; + + private final AndroidMotionEvent mMotionEvent; + private final Map mMap; + private boolean scrolling = false; + + public DragGestureHandler(Map map) { + super(map); + mMotionEvent = new AndroidMotionEvent(); + mMap = map; + } + + public boolean isScrolling() { + return scrolling; + } + + public void setScrolling(boolean scrolling) { + this.scrolling = scrolling; + } + + @Override + public void onShowPress(MotionEvent e) { + scrolling = true; + mMap.handleGesture(START_DRAG, mMotionEvent.wrap(e)); + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + scrolling = true; + return mMap.handleGesture(ONGOING_DRAG, mMotionEvent.wrap(e2)); + } +} diff --git a/vtm-android-example/src/org/oscim/android/drag/DragMapView.java b/vtm-android-example/src/org/oscim/android/drag/DragMapView.java new file mode 100644 index 00000000..877ecc7f --- /dev/null +++ b/vtm-android-example/src/org/oscim/android/drag/DragMapView.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012 Hannes Janetzek + * Copyright 2016-2020 devemux86 + * Copyright 2018-2019 Gustl22 + * Copyright 2021 Frank Knoll + * + * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.android.drag; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.GestureDetector; +import org.oscim.android.MapView; +import org.oscim.map.Map; +import org.oscim.utils.Parameters; + +public class DragMapView extends MapView { + + private DragGestureHandler gestureHandler; + + public DragMapView(Context context) { + super(context); + } + + public DragMapView(Context context, AttributeSet attributeSet) { + super(context, attributeSet); + + if (!Parameters.MAP_EVENT_LAYER2) { + gestureHandler = new DragGestureHandler(mMap); + mGestureDetector = new GestureDetector(context, gestureHandler); + mGestureDetector.setOnDoubleTapListener(gestureHandler); + } + } + + @Override + public boolean onTouchEvent(android.view.MotionEvent motionEvent) { + if (!isClickable()) { + return false; + } + + if (motionEvent.getAction() == android.view.MotionEvent.ACTION_UP) { + if (gestureHandler.isScrolling()) { + gestureHandler.setScrolling(false); + return ((Map) mMap).handleGesture(DragGestureHandler.END_DRAG, mMotionEvent.wrap(motionEvent)); + } + } + + return super.onTouchEvent(motionEvent); + } +} diff --git a/vtm-android-example/src/org/oscim/android/drag/DraggableItemizedLayer.java b/vtm-android-example/src/org/oscim/android/drag/DraggableItemizedLayer.java new file mode 100644 index 00000000..266e4f9e --- /dev/null +++ b/vtm-android-example/src/org/oscim/android/drag/DraggableItemizedLayer.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012 osmdroid authors: Nicolas Gramlich, Theodore Hong, Fred Eisele + * + * Copyright 2013 Hannes Janetzek + * Copyright 2016-2021 devemux86 + * Copyright 2016 Stephan Leuschner + * Copyright 2016 Pedinel + * Copyright 2019 Carlos Alberto Martínez Gadea + * Copyright 2021 Frank Knoll + * + * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.android.drag; + +import org.oscim.core.GeoPoint; +import org.oscim.event.Gesture; +import org.oscim.event.GestureListener; +import org.oscim.event.MotionEvent; +import org.oscim.layers.marker.ItemizedLayer; +import org.oscim.layers.marker.MarkerInterface; +import org.oscim.layers.marker.MarkerSymbol; +import org.oscim.map.Map; + +import java.util.List; + +import static org.oscim.android.drag.DragGestureHandler.*; + +public class DraggableItemizedLayer extends ItemizedLayer implements GestureListener { + + private final ItemDragger itemDragger; + + public DraggableItemizedLayer(Map map, + List markerItems, + MarkerSymbol defaultMarker, + OnItemGestureListener listener) { + super(map, markerItems, defaultMarker, listener); + itemDragger = new ItemDragger(this, map); + } + + @Override + protected boolean activateSelectedItems(MotionEvent event, ActiveItem task) { + return super.activateSelectedItems(event, task); + } + + protected List getMarkerItems() { + return mItemList; + } + + @Override + public boolean onGesture(Gesture gesture, MotionEvent event) { + if (!isEnabled()) { + return false; + } + + if (gesture == START_DRAG) { + return itemDragger.startDragItem(event, getGeoPoint(event)); + } else if (gesture == ONGOING_DRAG) { + return itemDragger.ongoingDragItemTo(getGeoPoint(event)); + } else if (gesture == END_DRAG) { + return itemDragger.dropItemAt(getGeoPoint(event)); + } else { + itemDragger.noDrag(); + } + + return super.onGesture(gesture, event); + } + + private GeoPoint getGeoPoint(MotionEvent event) { + return map().viewport().fromScreenPoint(event.getX(), event.getY()); + } +} diff --git a/vtm-android-example/src/org/oscim/android/drag/DraggableMarkerItem.java b/vtm-android-example/src/org/oscim/android/drag/DraggableMarkerItem.java new file mode 100644 index 00000000..a31396bf --- /dev/null +++ b/vtm-android-example/src/org/oscim/android/drag/DraggableMarkerItem.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012 osmdroid authors: + * Copyright 2012 Nicolas Gramlich + * Copyright 2012 Theodore Hong + * Copyright 2012 Fred Eisele + * + * Copyright 2014 Hannes Janetzek + * Copyright 2016 devemux86 + * Copyright 2016 Erik Duisters + * Copyright 2017 Longri + * Copyright 2021 Frank Knoll + * + * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.android.drag; + +import org.oscim.core.GeoPoint; +import org.oscim.layers.marker.MarkerItem; + +public class DraggableMarkerItem extends MarkerItem { + + private final DragAndDropListener dragAndDropListener; + + public DraggableMarkerItem(String title, String description, GeoPoint geoPoint, DragAndDropListener dragAndDropListener) { + super(title, description, geoPoint); + this.dragAndDropListener = dragAndDropListener; + } + + public DragAndDropListener getDragAndDropListener() { + return dragAndDropListener; + } +} diff --git a/vtm-android-example/src/org/oscim/android/drag/ItemDragger.java b/vtm-android-example/src/org/oscim/android/drag/ItemDragger.java new file mode 100644 index 00000000..da09fd2e --- /dev/null +++ b/vtm-android-example/src/org/oscim/android/drag/ItemDragger.java @@ -0,0 +1,96 @@ +/* + * Copyright 2021 Frank Knoll + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.android.drag; + +import org.oscim.core.GeoPoint; +import org.oscim.event.MotionEvent; +import org.oscim.layers.marker.ItemizedLayer; +import org.oscim.layers.marker.MarkerItem; +import org.oscim.layers.marker.MarkerLayer; +import org.oscim.map.Map; + +class ItemDragger { + + private final DraggableItemizedLayer draggableItemizedLayer; + private final DragAndDropListener dragItemAndRedrawListener; + private DraggableMarkerItem dragItem; + + public ItemDragger(DraggableItemizedLayer draggableItemizedLayer, Map map) { + this.draggableItemizedLayer = draggableItemizedLayer; + this.dragItemAndRedrawListener = createDragItemAndRedrawListener(draggableItemizedLayer, map); + } + + public boolean startDragItem(MotionEvent event, final GeoPoint geoPoint) { + dragItem = null; + return draggableItemizedLayer.activateSelectedItems( + event, + new ItemizedLayer.ActiveItem() { + @Override + public boolean run(int index) { + dragItem = (DraggableMarkerItem) draggableItemizedLayer.getMarkerItems().get(index); + dragItemAndRedrawListener.startDragItemAtGeoPoint(dragItem, geoPoint); + return true; + } + }); + } + + public boolean ongoingDragItemTo(GeoPoint geoPoint) { + if (dragItem == null) { + return false; + } + dragItemAndRedrawListener.ongoingDragItemToGeoPoint(dragItem, geoPoint); + return true; + } + + public boolean dropItemAt(GeoPoint geoPoint) { + if (dragItem == null) { + return false; + } + dragItemAndRedrawListener.dropItemAtGeoPoint(dragItem, geoPoint); + return true; + } + + public void noDrag() { + dragItem = null; + } + + private DragAndDropListener createDragItemAndRedrawListener(final MarkerLayer markerLayer, final Map map) { + return new DragAndDropListener() { + @Override + public void startDragItemAtGeoPoint(DraggableMarkerItem item, GeoPoint geoPoint) { + item.getDragAndDropListener().startDragItemAtGeoPoint(item, geoPoint); + updateLocationOfMarkerItemAndRedraw(item, geoPoint); + } + + @Override + public void ongoingDragItemToGeoPoint(DraggableMarkerItem item, GeoPoint geoPoint) { + item.getDragAndDropListener().ongoingDragItemToGeoPoint(item, geoPoint); + updateLocationOfMarkerItemAndRedraw(item, geoPoint); + } + + @Override + public void dropItemAtGeoPoint(DraggableMarkerItem item, GeoPoint geoPoint) { + item.getDragAndDropListener().dropItemAtGeoPoint(item, geoPoint); + updateLocationOfMarkerItemAndRedraw(item, geoPoint); + } + + private void updateLocationOfMarkerItemAndRedraw(MarkerItem markerItem, GeoPoint location) { + markerItem.geoPoint = location; + markerLayer.populate(); + map.render(); + } + }; + } +} diff --git a/vtm-android-example/src/org/oscim/android/test/DraggableMarkerOverlayActivity.java b/vtm-android-example/src/org/oscim/android/test/DraggableMarkerOverlayActivity.java new file mode 100644 index 00000000..89a8fc96 --- /dev/null +++ b/vtm-android-example/src/org/oscim/android/test/DraggableMarkerOverlayActivity.java @@ -0,0 +1,105 @@ +/* + * Copyright 2014 Hannes Janetzek + * Copyright 2016-2020 devemux86 + * Copyright 2021 Frank Knoll + * + * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.android.test; + +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.util.Log; +import org.oscim.android.canvas.AndroidBitmap; +import org.oscim.android.drag.DragAndDropListener; +import org.oscim.android.drag.DraggableItemizedLayer; +import org.oscim.android.drag.DraggableMarkerItem; +import org.oscim.core.GeoPoint; +import org.oscim.layers.marker.ItemizedLayer; +import org.oscim.layers.marker.MarkerInterface; +import org.oscim.layers.marker.MarkerSymbol; +import org.oscim.layers.marker.MarkerSymbol.HotspotPlace; +import org.oscim.layers.tile.bitmap.BitmapTileLayer; +import org.oscim.tiling.source.OkHttpEngine; +import org.oscim.tiling.source.UrlTileSource; +import org.oscim.tiling.source.bitmap.DefaultSources; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class DraggableMarkerOverlayActivity extends MapActivity { + + public DraggableMarkerOverlayActivity() { + super(R.layout.activity_map_draggable); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + createLayers(); + } + + void createLayers() { + UrlTileSource tileSource = DefaultSources.OPENSTREETMAP + .httpFactory(new OkHttpEngine.OkHttpFactory()) + .build(); + tileSource.setHttpRequestHeaders(Collections.singletonMap("User-Agent", "vtm-android-example")); + mMap.layers().add(new BitmapTileLayer(mMap, tileSource)); + + ItemizedLayer mMarkerLayer = new DraggableItemizedLayer( + mMap, + new ArrayList(), + new MarkerSymbol( + new AndroidBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.marker_poi)), + HotspotPlace.BOTTOM_CENTER), + null); + mMap.layers().add(mMarkerLayer); + + DragAndDropListener dragAndDropListener = new DragAndDropListener() { + @Override + public void startDragItemAtGeoPoint(DraggableMarkerItem item, GeoPoint geoPoint) { + Log.i(DraggableMarkerOverlayActivity.this.getClass().getSimpleName(), "startDragItemAtGeoPoint: " + geoPoint); + } + + @Override + public void ongoingDragItemToGeoPoint(DraggableMarkerItem item, GeoPoint geoPoint) { + Log.i(DraggableMarkerOverlayActivity.this.getClass().getSimpleName(), "ongoingDragItemToGeoPoint: " + geoPoint); + } + + @Override + public void dropItemAtGeoPoint(DraggableMarkerItem item, GeoPoint geoPoint) { + Log.i(DraggableMarkerOverlayActivity.this.getClass().getSimpleName(), "dropItemAtGeoPoint: " + geoPoint); + } + }; + + List pts = new ArrayList<>(); + for (double lat = -90; lat <= 90; lat += 45) { + for (double lon = -180; lon <= 180; lon += 45) { + pts.add(new DraggableMarkerItem(lat + "/" + lon, "", new GeoPoint(lat, lon), dragAndDropListener)); + } + } + + mMarkerLayer.addItems(pts); + } + + @Override + protected void onResume() { + super.onResume(); + + /* ignore saved position */ + mMap.setMapPosition(0, 0, 1 << 2); + } +} diff --git a/vtm-android-example/src/org/oscim/android/test/Samples.java b/vtm-android-example/src/org/oscim/android/test/Samples.java index 23ae7c7c..32cd113a 100644 --- a/vtm-android-example/src/org/oscim/android/test/Samples.java +++ b/vtm-android-example/src/org/oscim/android/test/Samples.java @@ -124,6 +124,7 @@ public class Samples extends Activity { linearLayout.addView(createButton(JeoIndoorActivity.class)); linearLayout.addView(createButton(GdxPoi3DActivity.class)); linearLayout.addView(createButton(OverpassActivity.class)); + linearLayout.addView(createButton(DraggableMarkerOverlayActivity.class)); linearLayout.addView(createButton(ClusterMarkerOverlayActivity.class)); linearLayout.addView(createButton(FragmentActivity.class)); }