vtm-app: revive / update with latest VTM, closes #90
This commit is contained in:
99
vtm-app/src/org/osmdroid/overlays/DefaultInfoWindow.java
Normal file
99
vtm-app/src/org/osmdroid/overlays/DefaultInfoWindow.java
Normal file
@@ -0,0 +1,99 @@
|
||||
package org.osmdroid.overlays;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.oscim.android.MapView;
|
||||
import org.oscim.app.App;
|
||||
import org.osmdroid.utils.BonusPackHelper;
|
||||
|
||||
/**
|
||||
* Default implementation of InfoWindow. It handles a text and a description. It
|
||||
* also handles optionally a sub-description and an image. Clicking on the
|
||||
* bubble will close it.
|
||||
*
|
||||
* @author M.Kergall
|
||||
*/
|
||||
public class DefaultInfoWindow extends InfoWindow {
|
||||
|
||||
// resource ids
|
||||
private static int mTitleId = 0, mDescriptionId = 0, mSubDescriptionId = 0, mImageId = 0;
|
||||
|
||||
private static void setResIds(Context context) {
|
||||
// get application package name
|
||||
String packageName = context.getPackageName();
|
||||
Resources res = context.getResources();
|
||||
|
||||
mTitleId = res.getIdentifier("id/bubble_title", null, packageName);
|
||||
mDescriptionId = res.getIdentifier("id/bubble_description", null, packageName);
|
||||
mSubDescriptionId = res.getIdentifier("id/bubble_subdescription", null, packageName);
|
||||
mImageId = res.getIdentifier("id/bubble_image", null, packageName);
|
||||
|
||||
if (mTitleId == 0 || mDescriptionId == 0) {
|
||||
Log.e(BonusPackHelper.LOG_TAG, "DefaultInfoWindow: unable to get res ids in "
|
||||
+ packageName);
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultInfoWindow(int layoutResId, MapView mapView) {
|
||||
super(layoutResId, mapView);
|
||||
|
||||
if (mTitleId == 0)
|
||||
setResIds(App.activity);
|
||||
|
||||
// default behaviour: close it when clicking on the bubble:
|
||||
mView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ExtendedMarkerItem item) {
|
||||
String title = item.getTitle();
|
||||
if (title == null)
|
||||
title = "";
|
||||
|
||||
((TextView) mView.findViewById(mTitleId)).setText(title);
|
||||
|
||||
String snippet = item.getDescription();
|
||||
if (snippet == null)
|
||||
snippet = "";
|
||||
|
||||
((TextView) mView.findViewById(mDescriptionId)).setText(snippet);
|
||||
|
||||
// handle sub-description, hidding or showing the text view:
|
||||
TextView subDescText = (TextView) mView.findViewById(mSubDescriptionId);
|
||||
String subDesc = item.getSubDescription();
|
||||
if (subDesc != null && !("".equals(subDesc))) {
|
||||
subDescText.setText(subDesc);
|
||||
subDescText.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
subDescText.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// handle image
|
||||
ImageView imageView = (ImageView) mView.findViewById(mImageId);
|
||||
Drawable image = item.getImage();
|
||||
if (image != null) {
|
||||
// or setBackgroundDrawable(image)?
|
||||
imageView.setImageDrawable(image);
|
||||
imageView.setVisibility(View.VISIBLE);
|
||||
} else
|
||||
imageView.setVisibility(View.GONE);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
// by default, do nothing
|
||||
}
|
||||
|
||||
}
|
||||
123
vtm-app/src/org/osmdroid/overlays/ExtendedMarkerItem.java
Normal file
123
vtm-app/src/org/osmdroid/overlays/ExtendedMarkerItem.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package org.osmdroid.overlays;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import org.oscim.core.GeoPoint;
|
||||
import org.oscim.layers.marker.MarkerItem;
|
||||
import org.oscim.map.Map;
|
||||
|
||||
/**
|
||||
* An OverlayItem to use in ItemizedOverlayWithBubble<br>
|
||||
* - more complete: can contain an image and a sub-description that will be
|
||||
* displayed in the bubble, <br>
|
||||
* - and flexible: attributes are modifiable<br>
|
||||
* Known Issues:<br>
|
||||
* - Bubble offset is not perfect on h&xhdpi resolutions, due to an osmdroid
|
||||
* issue on marker drawing<br>
|
||||
* - Bubble offset is at 0 when using the default marker => set the marker on
|
||||
* each item!<br>
|
||||
*
|
||||
* @author M.Kergall
|
||||
* @see ItemizedOverlayWithBubble
|
||||
*/
|
||||
public class ExtendedMarkerItem extends MarkerItem {
|
||||
|
||||
// now, they are modifiable
|
||||
private String mTitle, mDescription;
|
||||
// now, they are modifiable
|
||||
// a third field that can be displayed in
|
||||
// the infowindow, on a third line
|
||||
// that will be shown in the infowindow.
|
||||
//unfortunately, this is not so simple...
|
||||
private String mSubDescription;
|
||||
private Drawable mImage;
|
||||
private Object mRelatedObject; // reference to an object (of any kind)
|
||||
// linked to this item.
|
||||
|
||||
public ExtendedMarkerItem(String aTitle, String aDescription, GeoPoint aGeoPoint) {
|
||||
super(aTitle, aDescription, aGeoPoint);
|
||||
mTitle = aTitle;
|
||||
mDescription = aDescription;
|
||||
mSubDescription = null;
|
||||
mImage = null;
|
||||
mRelatedObject = null;
|
||||
}
|
||||
|
||||
public void setTitle(String aTitle) {
|
||||
mTitle = aTitle;
|
||||
}
|
||||
|
||||
public void setDescription(String aDescription) {
|
||||
mDescription = aDescription;
|
||||
}
|
||||
|
||||
public void setSubDescription(String aSubDescription) {
|
||||
mSubDescription = aSubDescription;
|
||||
}
|
||||
|
||||
public void setImage(Drawable anImage) {
|
||||
mImage = anImage;
|
||||
}
|
||||
|
||||
public void setRelatedObject(Object o) {
|
||||
mRelatedObject = o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
public String getSubDescription() {
|
||||
return mSubDescription;
|
||||
}
|
||||
|
||||
public Drawable getImage() {
|
||||
return mImage;
|
||||
}
|
||||
|
||||
public Object getRelatedObject() {
|
||||
return mRelatedObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates this bubble with all item info:
|
||||
* <ul>
|
||||
* title and description in any case,
|
||||
* </ul>
|
||||
* <ul>
|
||||
* image and sub-description if any.
|
||||
* </ul>
|
||||
* and centers the map on the item. <br>
|
||||
*
|
||||
* @param bubble ...
|
||||
* @param map ...
|
||||
*/
|
||||
public void showBubble(InfoWindow bubble, Map map) {
|
||||
// offset the bubble to be top-centered on the marker:
|
||||
// Drawable marker = getMarker(0 /* OverlayItem.ITEM_STATE_FOCUSED_MASK */);
|
||||
// int markerWidth = 0, markerHeight = 0;
|
||||
// if (marker != null) {
|
||||
// markerWidth = marker.getIntrinsicWidth();
|
||||
// markerHeight = marker.getIntrinsicHeight();
|
||||
// } // else... we don't have the default marker size => don't user default
|
||||
// // markers!!!
|
||||
// Point markerH = getHotspot(getMarkerHotspot(), markerWidth, markerHeight);
|
||||
// Point bubbleH = getHotspot(HotspotPlace.TOP_CENTER, markerWidth, markerHeight);
|
||||
// bubbleH.offset(-markerH.x, -markerH.y);
|
||||
//
|
||||
// bubble.open(this, bubbleH.x, bubbleH.y);
|
||||
// OverlayMarker marker = getMarker();
|
||||
// PointF hotspot = marker.getHotspot();
|
||||
// Bitmap b = marker.getBitmap();
|
||||
|
||||
//bubble.open(this, (int)(-b.getWidth() * hotspot.x), (int)(-b.getHeight()));
|
||||
//bubble.open(this, 0, (int)(b.getHeight()));
|
||||
|
||||
bubble.open(this, 0, 0);
|
||||
}
|
||||
}
|
||||
135
vtm-app/src/org/osmdroid/overlays/InfoWindow.java
Normal file
135
vtm-app/src/org/osmdroid/overlays/InfoWindow.java
Normal file
@@ -0,0 +1,135 @@
|
||||
package org.osmdroid.overlays;
|
||||
|
||||
// TODO composite view as texture overlay and only allow one bubble at a time.
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import org.oscim.android.MapView;
|
||||
|
||||
/**
|
||||
* View that can be displayed on an OSMDroid map, associated to a GeoPoint.
|
||||
* Typical usage: cartoon-like bubbles displayed when clicking an overlay item.
|
||||
* It mimics the InfoWindow class of Google Maps JavaScript API V3. Main
|
||||
* differences are:
|
||||
* <ul>
|
||||
* <li>Structure and content of the view is let to the responsibility of the
|
||||
* caller.</li>
|
||||
* <li>The same InfoWindow can be associated to many items.</li>
|
||||
* </ul>
|
||||
* Known issues:
|
||||
* <ul>
|
||||
* <li>It disappears when zooming in/out (osmdroid issue #259 on osmdroid 3.0.8,
|
||||
* should be fixed in next version).</li>
|
||||
* <li>The window is displayed "above" the marker, so the queue of the bubble
|
||||
* can hide the marker.</li>
|
||||
* </ul>
|
||||
* This is an abstract class.
|
||||
*
|
||||
* @author M.Kergall
|
||||
* @see DefaultInfoWindow
|
||||
*/
|
||||
public abstract class InfoWindow {
|
||||
|
||||
protected View mView;
|
||||
protected boolean mIsVisible = false;
|
||||
protected RelativeLayout mLayout;
|
||||
private android.widget.RelativeLayout.LayoutParams mLayoutPos;
|
||||
|
||||
private MapView mMap;
|
||||
|
||||
/**
|
||||
* @param layoutResId the id of the view resource.
|
||||
* @param mapView the mapview on which is hooked the view
|
||||
*/
|
||||
public InfoWindow(int layoutResId, MapView mapView) {
|
||||
ViewGroup parent = (ViewGroup) mapView.getParent();
|
||||
Context context = mapView.getContext();
|
||||
LayoutInflater inflater = (LayoutInflater) context
|
||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mView = inflater.inflate(layoutResId, parent, false);
|
||||
|
||||
RelativeLayout.LayoutParams rlp =
|
||||
new RelativeLayout.LayoutParams(
|
||||
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
mLayout = new RelativeLayout(context);
|
||||
mLayout.setWillNotDraw(true);
|
||||
mLayout.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
|
||||
mLayout.setLayoutParams(rlp);
|
||||
mLayoutPos = rlp;
|
||||
mView.setDrawingCacheEnabled(true);
|
||||
mLayout.addView(mView);
|
||||
|
||||
mIsVisible = false;
|
||||
mLayout.setVisibility(View.GONE);
|
||||
mMap = mapView;
|
||||
|
||||
parent.addView(mLayout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Android view. This allows to set its content.
|
||||
*
|
||||
* @return the Android view
|
||||
*/
|
||||
public View getView() {
|
||||
return (mView);
|
||||
}
|
||||
|
||||
private int mHeight;
|
||||
|
||||
/**
|
||||
* open the window at the specified position.
|
||||
*
|
||||
* @param item the item on which is hooked the view
|
||||
* @param offsetX (&offsetY) the offset of the view to the position, in pixels.
|
||||
* This allows to offset the view from the marker position.
|
||||
* @param offsetY ...
|
||||
*/
|
||||
public void open(ExtendedMarkerItem item, int offsetX, int offsetY) {
|
||||
|
||||
onOpen(item);
|
||||
close();
|
||||
|
||||
mView.buildDrawingCache();
|
||||
|
||||
mHeight = mMap.getHeight();
|
||||
mLayout.setVisibility(View.VISIBLE);
|
||||
mIsVisible = true;
|
||||
|
||||
}
|
||||
|
||||
public void position(int x, int y) {
|
||||
RelativeLayout.LayoutParams rlp = mLayoutPos;
|
||||
rlp.leftMargin = x;
|
||||
rlp.rightMargin = -x;
|
||||
rlp.topMargin = y;
|
||||
rlp.bottomMargin = mHeight / 2 - y;
|
||||
mLayout.setLayoutParams(rlp);
|
||||
mLayout.requestLayout();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
||||
if (mIsVisible) {
|
||||
mIsVisible = false;
|
||||
mLayout.setVisibility(View.GONE);
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return mIsVisible;
|
||||
}
|
||||
|
||||
// Abstract methods to implement:
|
||||
public abstract void onOpen(ExtendedMarkerItem item);
|
||||
|
||||
public abstract void onClose();
|
||||
|
||||
}
|
||||
195
vtm-app/src/org/osmdroid/overlays/ItemizedOverlayWithBubble.java
Normal file
195
vtm-app/src/org/osmdroid/overlays/ItemizedOverlayWithBubble.java
Normal file
@@ -0,0 +1,195 @@
|
||||
package org.osmdroid.overlays;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.oscim.app.App;
|
||||
import org.oscim.core.GeoPoint;
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Point;
|
||||
import org.oscim.event.Event;
|
||||
import org.oscim.event.MotionEvent;
|
||||
import org.oscim.layers.marker.ItemizedLayer;
|
||||
import org.oscim.layers.marker.MarkerItem;
|
||||
import org.oscim.layers.marker.MarkerSymbol;
|
||||
import org.oscim.map.Map;
|
||||
import org.osmdroid.utils.BonusPackHelper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An itemized overlay with an InfoWindow or "bubble" which opens when the user
|
||||
* taps on an overlay item, and displays item attributes. <br>
|
||||
* Items must be ExtendedMarkerItem. <br>
|
||||
*
|
||||
* @param <Item> ...
|
||||
* @author M.Kergall
|
||||
* @see ExtendedMarkerItem
|
||||
* @see InfoWindow
|
||||
*/
|
||||
public class ItemizedOverlayWithBubble<Item extends MarkerItem> extends
|
||||
ItemizedLayer<Item> implements
|
||||
ItemizedLayer.OnItemGestureListener<Item>, Map.UpdateListener {
|
||||
|
||||
/* only one for all items of this overlay => one at a time */
|
||||
protected InfoWindow mBubble;
|
||||
|
||||
/* the item currently showing the bubble. Null if none. */
|
||||
protected MarkerItem mItemWithBubble;
|
||||
|
||||
static int layoutResId = 0;
|
||||
|
||||
public ItemizedOverlayWithBubble(Map map, Context context,
|
||||
MarkerSymbol marker, List<Item> list, InfoWindow bubble) {
|
||||
super(map, list, marker, null);
|
||||
|
||||
if (bubble != null) {
|
||||
mBubble = bubble;
|
||||
} else {
|
||||
// build default bubble:
|
||||
String packageName = context.getPackageName();
|
||||
if (layoutResId == 0) {
|
||||
layoutResId = context.getResources().getIdentifier(
|
||||
"layout/bonuspack_bubble",
|
||||
null,
|
||||
packageName);
|
||||
if (layoutResId == 0)
|
||||
Log.e(BonusPackHelper.LOG_TAG,
|
||||
"ItemizedOverlayWithBubble: layout/bonuspack_bubble not found in "
|
||||
+ packageName);
|
||||
}
|
||||
mBubble = new DefaultInfoWindow(layoutResId, App.view);
|
||||
}
|
||||
|
||||
mItemWithBubble = null;
|
||||
mOnItemGestureListener = this;
|
||||
}
|
||||
|
||||
public ItemizedOverlayWithBubble(Map map, Context context,
|
||||
MarkerSymbol marker, List<Item> aList) {
|
||||
this(map, context, marker, aList, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongPress(int index, MarkerItem item) {
|
||||
if (mBubble.isOpen())
|
||||
hideBubble();
|
||||
else
|
||||
showBubble(index);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemSingleTapUp(int index, MarkerItem item) {
|
||||
showBubble(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private final Point mTmpPoint = new Point();
|
||||
|
||||
@Override
|
||||
protected boolean activateSelectedItems(MotionEvent event, ActiveItem task) {
|
||||
boolean hit = super.activateSelectedItems(event, task);
|
||||
|
||||
if (!hit)
|
||||
hideBubble();
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapEvent(Event e, MapPosition mapPosition) {
|
||||
if (mBubble.isOpen()) {
|
||||
GeoPoint gp = mItemWithBubble.getPoint();
|
||||
|
||||
Point p = mTmpPoint;
|
||||
mMap.viewport().toScreenPoint(gp, p);
|
||||
|
||||
mBubble.position((int) p.x, (int) p.y);
|
||||
}
|
||||
}
|
||||
|
||||
void showBubble(int index) {
|
||||
showBubbleOnItem(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the bubble on the item. For each ItemizedOverlay, only one bubble
|
||||
* is opened at a time. If you want more bubbles opened simultaneously, use
|
||||
* many ItemizedOverlays.
|
||||
*
|
||||
* @param index of the overlay item to show
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void showBubbleOnItem(int index) {
|
||||
ExtendedMarkerItem item = (ExtendedMarkerItem) (mItemList.get(index));
|
||||
mItemWithBubble = item;
|
||||
if (item != null) {
|
||||
item.showBubble(mBubble, (Map) mMap);
|
||||
|
||||
mMap.animator().animateTo(item.geoPoint);
|
||||
|
||||
mMap.updateMap(true);
|
||||
setFocus((Item) item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the bubble (if it's opened).
|
||||
*/
|
||||
public void hideBubble() {
|
||||
mBubble.close();
|
||||
mItemWithBubble = null;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean onSingleTapUp(final MotionEvent event) {
|
||||
// boolean handled = super.onSingleTapUp(event);
|
||||
// if (!handled)
|
||||
// hideBubble();
|
||||
// return handled;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected boolean onSingleTapUpHelper(final int index, final Item item) {
|
||||
// showBubbleOnItem(index);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @return the item currenty showing the bubble, or null if none.
|
||||
*/
|
||||
public MarkerItem getBubbledItem() {
|
||||
if (mBubble.isOpen())
|
||||
return mItemWithBubble;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the index of the item currenty showing the bubble, or -1 if none.
|
||||
*/
|
||||
public int getBubbledItemId() {
|
||||
MarkerItem item = getBubbledItem();
|
||||
if (item == null)
|
||||
return -1;
|
||||
|
||||
return mItemList.indexOf(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeItem(final Item item) {
|
||||
boolean result = super.removeItem(item);
|
||||
if (mItemWithBubble == item) {
|
||||
hideBubble();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllItems() {
|
||||
super.removeAllItems();
|
||||
hideBubble();
|
||||
}
|
||||
}
|
||||
34
vtm-app/src/org/osmdroid/overlays/MapEventsReceiver.java
Normal file
34
vtm-app/src/org/osmdroid/overlays/MapEventsReceiver.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package org.osmdroid.overlays;
|
||||
|
||||
import org.oscim.core.GeoPoint;
|
||||
|
||||
/**
|
||||
* Interface for objects that need to handle map events thrown by a
|
||||
* MapEventsOverlay.
|
||||
*
|
||||
* @author M.Kergall
|
||||
*/
|
||||
public interface MapEventsReceiver {
|
||||
|
||||
/**
|
||||
* @param p the position where the event occurred.
|
||||
* @return true if the event has been "consumed" and should not be handled
|
||||
* by other objects.
|
||||
*/
|
||||
boolean singleTapUpHelper(GeoPoint p);
|
||||
|
||||
/**
|
||||
* @param p the position where the event occurred.
|
||||
* @return true if the event has been "consumed" and should not be handled
|
||||
* by other objects.
|
||||
*/
|
||||
boolean longPressHelper(GeoPoint p);
|
||||
|
||||
/**
|
||||
* @param p1 p2
|
||||
* the position where the event occurred for 2 finger.
|
||||
* @return true if the event has been "consumed" and should not be handled
|
||||
* by other objects.
|
||||
*/
|
||||
boolean longPressHelper(GeoPoint p1, GeoPoint p2);
|
||||
}
|
||||
Reference in New Issue
Block a user