From 70470bf7e990790618e6a2e84dd48c597f296288 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 28 Aug 2015 20:12:33 -0700 Subject: [PATCH] #894 - Basic port of InfoWindow --- .../mapboxgl/annotations/Annotation.java | 3 +- .../mapboxgl/annotations/InfoWindow.java | 189 ++++++++++++++++++ .../annotations/InfoWindowTipView.java | 40 ++++ .../mapbox/mapboxgl/annotations/Marker.java | 55 +++-- .../src/main/res/layout/infowindow.xml | 52 +++++ .../src/main/res/values/colors.xml | 5 + .../src/main/res/values/strings.xml | 3 + 7 files changed, 332 insertions(+), 15 deletions(-) create mode 100644 android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindow.java create mode 100644 android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindowTipView.java create mode 100644 android/java/MapboxGLAndroidSDK/src/main/res/layout/infowindow.xml create mode 100644 android/java/MapboxGLAndroidSDK/src/main/res/values/colors.xml diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java index 4f172c6e2bf..c4dea205e04 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java @@ -2,7 +2,6 @@ import com.mapbox.mapboxgl.views.MapView; - public abstract class Annotation { /** @@ -11,7 +10,7 @@ public abstract class Annotation { * Internal C++ id is stored as unsigned int. */ protected long id = -1; // -1 unless added to a MapView - private MapView mapView; + protected MapView mapView; float alpha = 1.0f; boolean visible = true; diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindow.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindow.java new file mode 100644 index 00000000000..924012db525 --- /dev/null +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindow.java @@ -0,0 +1,189 @@ +package com.mapbox.mapboxgl.annotations; + +import android.content.Context; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import com.mapbox.mapboxgl.geometry.LatLng; +import com.mapbox.mapboxgl.views.MapView; + +/** + * A tooltip view + */ +public class InfoWindow { + + private Marker boundMarker; + private MapView mMapView; + private boolean mIsVisible; + protected View mView; + + static int mTitleId = 0; + static int mDescriptionId = 0; + static int mSubDescriptionId = 0; + static int mImageId = 0; + + public InfoWindow(int layoutResId, MapView mapView) { + mMapView = mapView; + mIsVisible = false; + ViewGroup parent = (ViewGroup) mapView.getParent(); + Context context = mapView.getContext(); + LayoutInflater inflater = + (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mView = inflater.inflate(layoutResId, parent, false); + + if (mTitleId == 0) { + setResIds(mapView.getContext()); + } + + // default behavior: close it when clicking on the tooltip: + setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent e) { + if (e.getAction() == MotionEvent.ACTION_UP) { + close(); + } + return true; + } + }); + } + + public InfoWindow(View view, MapView mapView) { + mMapView = mapView; + mIsVisible = false; + ViewGroup parent = (ViewGroup) mapView.getParent(); + Context context = mapView.getContext(); + LayoutInflater inflater = + (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mView = view; + + // default behavior: close it when clicking on the tooltip: + setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent e) { + if (e.getAction() == MotionEvent.ACTION_UP) { + close(); + } + return true; + } + }); + } + + /** + * open the window at the specified position. + * + * @param object the graphical object on which is hooked the view + * @param position to place the window on the map + * @param offsetX (&offsetY) the offset of the view to the position, in pixels. + * This allows to offset the view from the object position. + * @return this infowindow + */ + public InfoWindow open(Marker object, LatLng position, int offsetX, int offsetY) { + onOpen(object); + MapView.LayoutParams lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, + MapView.LayoutParams.WRAP_CONTENT, Gravity.CENTER|Gravity.BOTTOM); + close(); //if it was already opened + mMapView.addView(mView, lp); + mIsVisible = true; + return this; + } + + /** + * Close this InfoWindow if it is visible, otherwise don't do anything. + * + * @return this info window + */ + public InfoWindow close() { + if (mIsVisible) { + mIsVisible = false; + ((ViewGroup) mView.getParent()).removeView(mView); +// this.boundMarker.blur(); + setBoundMarker(null); + onClose(); + } + return this; + } + + /** + * Returns the Android view. This allows to set its content. + * + * @return the Android view + */ + public View getView() { + return mView; + } + + /** + * Returns the mapView this InfoWindow is bound to + * + * @return the mapView + */ + public MapView getMapView() { + return mMapView; + } + + /** + * Constructs the view that is displayed when the InfoWindow opens. + * This retrieves data from overlayItem and shows it in the tooltip. + * + * @param overlayItem the tapped overlay item + */ + public void onOpen(Marker overlayItem) { + String title = overlayItem.getTitle(); + ((TextView) mView.findViewById(mTitleId /*R.id.title*/)).setText(title); + String snippet = overlayItem.getSnippet(); + ((TextView) mView.findViewById(mDescriptionId /*R.id.description*/)).setText(snippet); + +/* + //handle sub-description, hiding or showing the text view: + TextView subDescText = (TextView) mView.findViewById(mSubDescriptionId); + String subDesc = overlayItem.getSubDescription(); + if ("".equals(subDesc)) { + subDescText.setVisibility(View.GONE); + } else { + subDescText.setText(subDesc); + subDescText.setVisibility(View.VISIBLE); + } +*/ + } + + public void onClose() { + //by default, do nothing + } + + public InfoWindow setBoundMarker(Marker aBoundMarker) { + this.boundMarker = aBoundMarker; + return this; + } + + public Marker getBoundMarker() { + return boundMarker; + } + + /** + * Given a context, set the resource ids for the layout + * of the InfoWindow. + * + * @param context + */ + private static void setResIds(Context context) { + String packageName = context.getPackageName(); //get application package name + mTitleId = context.getResources().getIdentifier("id/infowindow_title", null, packageName); + mDescriptionId = + context.getResources().getIdentifier("id/infowindow_description", null, packageName); + mSubDescriptionId = context.getResources() + .getIdentifier("id/infowindow_subdescription", null, packageName); + mImageId = context.getResources().getIdentifier("id/infowindow_image", null, packageName); + } + + /** + * Use to override default touch events handling on InfoWindow (ie, close automatically) + * + * @param listener New View.OnTouchListener to use + */ + public void setOnTouchListener(View.OnTouchListener listener) { + mView.setOnTouchListener(listener); + } +} diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindowTipView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindowTipView.java new file mode 100644 index 00000000000..657e63a840d --- /dev/null +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindowTipView.java @@ -0,0 +1,40 @@ +package com.mapbox.mapboxgl.annotations; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.util.AttributeSet; +import android.view.View; + +public class InfoWindowTipView extends View { + + private Paint mPaint; + private Path mPath; + + public InfoWindowTipView(Context context, AttributeSet attrs) { + super(context, attrs); + + mPath = new Path(); + + this.mPaint = new Paint(); + this.mPaint.setColor(Color.WHITE); + this.mPaint.setAntiAlias(true); + this.mPaint.setStrokeWidth(0.0f); + this.mPaint.setStyle(Paint.Style.FILL); + } + + @Override + protected void onDraw(Canvas canvas) { + int height = getMeasuredHeight(); + int width = getMeasuredWidth(); + + mPath.rewind(); + mPath.moveTo((width / 2) - height, 0); + mPath.lineTo((width / 2) + height, 0); + mPath.lineTo((width / 2), height); + mPath.lineTo((width / 2) - height, 0); + canvas.drawPath(mPath, this.mPaint); + } +} diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java index 515852ae6fa..4776c37bf37 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java @@ -1,7 +1,8 @@ package com.mapbox.mapboxgl.annotations; +import android.graphics.Point; import com.mapbox.mapboxgl.geometry.LatLng; - +import com.mapbox.mapboxgl.views.R; public class Marker extends Annotation { @@ -16,10 +17,16 @@ public class Marker extends Annotation { String snippet; String sprite = "default_marker"; String title; + private InfoWindow infoWindow = null; private boolean infoWindowShown = false; - public Marker() {} + /** + * Constructor + */ + public Marker() { + super(); + } /** * If two markers have the same LatLng, they are equal. @@ -41,6 +48,10 @@ public float getAlpha() { return alpha; } + public Point getAnchor() { + return new Point((int)anchorU, (int)anchorV); + } + public float getAnchorU() { return anchorU; } @@ -66,7 +77,7 @@ public String getTitle() { } public void hideInfoWindow() { - //TODO hideInfoWindow + infoWindow.close(); infoWindowShown = false; } @@ -82,33 +93,33 @@ public boolean isInfoWindowShown () { return infoWindowShown; } - void setAnchor(float u, float v) { + public void setAnchor(float u, float v) { this.anchorU = u; this.anchorV = v; } - void setDraggable(boolean draggable) { + public void setDraggable(boolean draggable) { this.draggable = draggable; } - void setFlat(boolean flat) { + public void setFlat(boolean flat) { this.flat = flat; } - void setInfoWindowAnchor(float u, float v) { + public void setInfoWindowAnchor(float u, float v) { infoWindowAnchorU = u; infoWindowAnchorV = v; } - void setPosition(LatLng latlng) { + public void setPosition(LatLng latlng) { this.position = position; } - void setRotation(float rotation) { + public void setRotation(float rotation) { this.rotation = rotation; } - void setSnippet(String snippet) { + public void setSnippet(String snippet) { this.snippet = snippet; } @@ -120,18 +131,36 @@ void setSnippet(String snippet) { * * @param sprite */ - void setSprite(String sprite) { + public void setSprite(String sprite) { this.sprite = sprite; } - void setTitle(String title) { + public void setTitle(String title) { this.title = title; } - void showInfoWindow() { + public void showInfoWindow() { + + if (!isVisible() || mapView == null) { + return; + } + + if (infoWindow == null) { + infoWindow = new InfoWindow(R.layout.infowindow, mapView); + } + + infoWindow.open(this, getPosition(), (int)anchorU, (int)anchorV); + infoWindow.setBoundMarker(this); infoWindowShown = true; } + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + if (!visible && infoWindowShown) { + hideInfoWindow(); + } + } // TODO Method in Google Maps Android API // public int hashCode() diff --git a/android/java/MapboxGLAndroidSDK/src/main/res/layout/infowindow.xml b/android/java/MapboxGLAndroidSDK/src/main/res/layout/infowindow.xml new file mode 100644 index 00000000000..af05e2fd40e --- /dev/null +++ b/android/java/MapboxGLAndroidSDK/src/main/res/layout/infowindow.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + diff --git a/android/java/MapboxGLAndroidSDK/src/main/res/values/colors.xml b/android/java/MapboxGLAndroidSDK/src/main/res/values/colors.xml new file mode 100644 index 00000000000..bf3f4843138 --- /dev/null +++ b/android/java/MapboxGLAndroidSDK/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + + #FFFFFF + #000000 + diff --git a/android/java/MapboxGLAndroidSDK/src/main/res/values/strings.xml b/android/java/MapboxGLAndroidSDK/src/main/res/values/strings.xml index df022a4679a..ff91a160ded 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/res/values/strings.xml +++ b/android/java/MapboxGLAndroidSDK/src/main/res/values/strings.xml @@ -1,4 +1,7 @@ Map compass. Click to reset the map rotation to North. + Title + Description + Address