Back to project page smartnavi.
The source code is released under:
Apache License
If you think the Android project smartnavi listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package org.osmdroid.bonuspack.overlays; //from www .j av a 2s. c o m import android.content.Context; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.Log; import android.view.MotionEvent; import org.osmdroid.DefaultResourceProxyImpl; import org.osmdroid.ResourceProxy; import org.osmdroid.ResourceProxy.bitmap; import org.osmdroid.bonuspack.utils.BonusPackHelper; import org.osmdroid.util.GeoPoint; import org.osmdroid.views.MapView; import org.osmdroid.views.Projection; import org.osmdroid.views.overlay.Overlay; /** * An icon placed at a particular point on the map's surface. * Mimics the Marker class from Google Maps Android API v2 as much as possible. Main differences:<br/> * - Doesn't support Z-Index: as other osmdroid overlays, Marker is drawn in the order of appearance. <br/> * - The icon can be any standard Android Drawable, instead of the BitmapDescriptor introduced in Google Maps API v2. <br/> * - The icon can be changed at any time. <br/> * - The InfoWindow hosts a standard Android View. It can handle Android widgets like buttons and so on. <br/> * - Supports a "sub-description", to be displayed in the InfoWindow, under the snippet, in a smaller text font. <br/> * - Supports an image, to be displayed in the InfoWindow. <br/> * - Supports "panning to view" on/off option (when touching a marker, center the map on marker position). <br/> * - Opening a Marker InfoWindow automatically close others only if it's the same InfoWindow shared between Markers. <br/> * - Events listeners are set per marker, not per map. <br/> * <p/> * TODO: <br/> * Impact of marker rotation on hitTest<br/> * When map is rotated, when panning the map, bug on the InfoWindow positioning (osmdroid issue #524)<br/> * * @author M.Kergall * @see MarkerInfoWindow * @see http://developer.android.com/reference/com/google/android/gms/maps/model/Marker.html */ public class Marker extends Overlay { /** * Usual values in the (U,V) coordinates system of the icon image */ public static final float ANCHOR_CENTER = 0.5f, ANCHOR_LEFT = 0.0f, ANCHOR_TOP = 0.0f, ANCHOR_RIGHT = 1.0f, ANCHOR_BOTTOM = 1.0f; protected static MarkerInfoWindow mDefaultInfoWindow = null; protected static Drawable mDefaultIcon = null; //cache for default icon (resourceProxy.getDrawable being slow) /*attributes for standard features:*/ protected Drawable mIcon; protected GeoPoint mPosition; protected float mBearing; protected float mAnchorU, mAnchorV; protected float mIWAnchorU, mIWAnchorV; protected float mAlpha; protected String mTitle, mSnippet; protected boolean mDraggable, mIsDragged; protected MarkerInfoWindow mInfoWindow; protected boolean mFlat; protected OnMarkerClickListener mOnMarkerClickListener; protected OnMarkerDragListener mOnMarkerDragListener; /*attributes for non-standard features:*/ protected Drawable mImage; protected String mSubDescription; protected boolean mPanToView; protected Object mRelatedObject; /*internals*/ protected Point mPositionPixels; public Marker(MapView mapView) { this(mapView, new DefaultResourceProxyImpl(mapView.getContext())); } public Marker(MapView mapView, final ResourceProxy resourceProxy) { super(resourceProxy); mBearing = 0.0f; mAlpha = 1.0f; //opaque mPosition = new GeoPoint(0.0, 0.0); mAnchorU = ANCHOR_CENTER; mAnchorV = ANCHOR_CENTER; mIWAnchorU = ANCHOR_CENTER; mIWAnchorV = ANCHOR_TOP; mDraggable = false; mIsDragged = false; mPositionPixels = new Point(); mPanToView = true; mFlat = false; //billboard mOnMarkerClickListener = null; mOnMarkerDragListener = null; if (mDefaultIcon == null) mDefaultIcon = resourceProxy.getDrawable(bitmap.marker_default); mIcon = mDefaultIcon; if (mDefaultInfoWindow == null || mDefaultInfoWindow.mMapView != mapView) { //build default bubble, that will be shared between all markers using the default one: Context context = mapView.getContext(); String packageName = context.getPackageName(); int defaultLayoutResId = context.getResources().getIdentifier("bonuspack_bubble", "layout", packageName); if (defaultLayoutResId == 0) Log.e(BonusPackHelper.LOG_TAG, "Marker: layout/bonuspack_bubble not found in " + packageName); else mDefaultInfoWindow = new MarkerInfoWindow(defaultLayoutResId, mapView); } mInfoWindow = mDefaultInfoWindow; } /** * Sets the icon for the marker. Can be changed at any time. * * @param icon if null, the default osmdroid marker is used. */ public void setIcon(Drawable icon) { if (icon != null) mIcon = icon; else mIcon = mDefaultIcon; } public GeoPoint getPosition() { return mPosition; } public void setPosition(GeoPoint position) { mPosition = position.clone(); } public float getRotation() { return mBearing; } public void setRotation(float rotation) { mBearing = rotation; } public void setAnchor(float anchorU, float anchorV) { mAnchorU = anchorU; mAnchorV = anchorV; } public void setInfoWindowAnchor(float anchorU, float anchorV) { mIWAnchorU = anchorU; mIWAnchorV = anchorV; } public float getAlpha() { return mAlpha; } public void setAlpha(float alpha) { mAlpha = alpha; } public String getTitle() { return mTitle; } public void setTitle(String title) { mTitle = title; } public String getSnippet() { return mSnippet; } public void setSnippet(String snippet) { mSnippet = snippet; } public boolean isDraggable() { return mDraggable; } public void setDraggable(boolean draggable) { mDraggable = draggable; } public boolean isFlat() { return mFlat; } public void setFlat(boolean flat) { mFlat = flat; } /** * Removes this Marker from the MapView. * Note that this method will operate only if the Marker is in the MapView overlays * (it should not be included in a container like a FolderOverlay). * * @param mapView */ public void remove(MapView mapView) { mapView.getOverlays().remove(this); } public void setOnMarkerClickListener(OnMarkerClickListener listener) { mOnMarkerClickListener = listener; } public void setOnMarkerDragListener(OnMarkerDragListener listener) { mOnMarkerDragListener = listener; } public String getSubDescription() { return mSubDescription; } /** * set the "sub-description", an optional text to be shown in the InfoWindow, below the snippet, in a smaller text size */ public void setSubDescription(String subDescription) { mSubDescription = subDescription; } /** * get the image to be shown in the InfoWindow - this is not the marker icon */ public Drawable getImage() { return mImage; } /** * set an image to be shown in the InfoWindow - this is not the marker icon */ public void setImage(Drawable image) { mImage = image; } /** * Set the InfoWindow to be used. * Default is a MarkerInfoWindow, with the layout named "bonuspack_bubble". * You can use this method either to use your own layout, or to use your own sub-class of InfoWindow. * Note that this InfoWindow will receive the Marker object as an input, so it MUST be able to handle Marker attributes. * If you don't want any InfoWindow to open, you can set it to null. */ public void setInfoWindow(MarkerInfoWindow infoWindow) { mInfoWindow = infoWindow; } /** * If set to true, when clicking the marker, the map will be centered on the marker position. * Default is true. */ public void setPanToView(boolean panToView) { mPanToView = panToView; } /** * @return the related object. */ public Object getRelatedObject() { return mRelatedObject; } /** * Allows to link an Object (any Object) to this marker. * This is particularly useful to handle custom InfoWindow. */ public void setRelatedObject(Object relatedObject) { mRelatedObject = relatedObject; } public void showInfoWindow() { if (mInfoWindow == null) return; int markerWidth = 0, markerHeight = 0; markerWidth = mIcon.getIntrinsicWidth(); markerHeight = mIcon.getIntrinsicHeight(); int offsetX = (int) (mIWAnchorU * markerWidth) - (int) (mAnchorU * markerWidth); int offsetY = (int) (mIWAnchorV * markerHeight) - (int) (mAnchorV * markerHeight); mInfoWindow.open(this, mPosition, offsetX, offsetY); } public void hideInfoWindow() { if (mInfoWindow != null) mInfoWindow.close(); } public boolean isInfoWindowShown() { return (mInfoWindow != null) && mInfoWindow.isOpen() && (mInfoWindow.mMarkerRef == this); } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { if (shadow) return; if (mIcon == null) return; final Projection pj = mapView.getProjection(); pj.toPixels(mPosition, mPositionPixels); int width = mIcon.getIntrinsicWidth(); int height = mIcon.getIntrinsicHeight(); Rect rect = new Rect(0, 0, width, height); rect.offset(-(int) (mAnchorU * width), -(int) (mAnchorV * height)); mIcon.setBounds(rect); mIcon.setAlpha((int) (mAlpha * 255)); float rotationOnScreen = (mFlat ? -mBearing : mapView.getMapOrientation() - mBearing); drawAt(canvas, mIcon, mPositionPixels.x, mPositionPixels.y, false, rotationOnScreen); } public boolean hitTest(final MotionEvent event, final MapView mapView) { final Projection pj = mapView.getProjection(); pj.toPixels(mPosition, mPositionPixels); final Rect screenRect = pj.getIntrinsicScreenRect(); int x = -mPositionPixels.x + screenRect.left + (int) event.getX(); int y = -mPositionPixels.y + screenRect.top + (int) event.getY(); boolean hit = mIcon.getBounds().contains(x, y); return hit; } @Override public boolean onSingleTapConfirmed(final MotionEvent event, final MapView mapView) { boolean touched = hitTest(event, mapView); if (touched) { if (mOnMarkerClickListener == null) { return onMarkerClickDefault(this, mapView); } else { return mOnMarkerClickListener.onMarkerClick(this, mapView); } } else return touched; } public void moveToEventPosition(final MotionEvent event, final MapView mapView) { final Projection pj = mapView.getProjection(); mPosition = (GeoPoint) pj.fromPixels((int) event.getX(), (int) event.getY()); mapView.invalidate(); } @Override public boolean onLongPress(final MotionEvent event, final MapView mapView) { boolean touched = hitTest(event, mapView); if (touched) { if (mDraggable) { //starts dragging mode: mIsDragged = true; hideInfoWindow(); if (mOnMarkerDragListener != null) mOnMarkerDragListener.onMarkerDragStart(this); moveToEventPosition(event, mapView); } } return touched; } @Override public boolean onTouchEvent(final MotionEvent event, final MapView mapView) { if (mDraggable && mIsDragged) { if (event.getAction() == MotionEvent.ACTION_UP) { mIsDragged = false; if (mOnMarkerDragListener != null) mOnMarkerDragListener.onMarkerDragEnd(this); return true; } else if (event.getAction() == MotionEvent.ACTION_MOVE) { moveToEventPosition(event, mapView); if (mOnMarkerDragListener != null) mOnMarkerDragListener.onMarkerDrag(this); return true; } else return false; } else return false; } //-- Marker events listener interfaces ------------------------------------ /** * default behaviour when no click listener is set */ protected boolean onMarkerClickDefault(Marker marker, MapView mapView) { marker.showInfoWindow(); if (marker.mPanToView) mapView.getController().animateTo(marker.getPosition()); return true; } public interface OnMarkerClickListener { abstract boolean onMarkerClick(Marker marker, MapView mapView); } public interface OnMarkerDragListener { abstract void onMarkerDrag(Marker marker); abstract void onMarkerDragEnd(Marker marker); abstract void onMarkerDragStart(Marker marker); } }