Java tutorial
/** * Appcelerator Titanium Mobile * Copyright (c) 2013 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ package ti.map; import java.util.ArrayList; import java.util.HashMap; import org.appcelerator.kroll.KrollDict; import org.appcelerator.kroll.KrollProxy; import org.appcelerator.kroll.common.Log; import org.appcelerator.titanium.TiBlob; import org.appcelerator.titanium.TiC; import org.appcelerator.titanium.proxy.TiViewProxy; import org.appcelerator.titanium.util.TiConvert; import org.appcelerator.titanium.view.TiUIFragment; import ti.map.Shape.Boundary; import ti.map.Shape.IShape; import ti.map.Shape.PolylineBoundary; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Point; import android.location.Location; import android.os.Build; import android.support.v4.app.Fragment; import android.view.MotionEvent; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMapOptions; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.Circle; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; public class TiUIMapView extends TiUIFragment implements GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener, GoogleMap.OnCameraChangeListener, GoogleMap.OnMarkerDragListener, GoogleMap.OnInfoWindowClickListener, GoogleMap.InfoWindowAdapter, GoogleMap.OnMapLongClickListener, GoogleMap.OnMapLoadedCallback, OnMapReadyCallback { private static final String TAG = "TiUIMapView"; private GoogleMap map; protected boolean animate = false; protected boolean preLayout = true; protected LatLngBounds preLayoutUpdateBounds; protected ArrayList<TiMarker> timarkers; protected AnnotationProxy selectedAnnotation; private ArrayList<CircleProxy> currentCircles; private ArrayList<PolygonProxy> currentPolygons; private ArrayList<PolylineProxy> currentPolylines; public TiUIMapView(final TiViewProxy proxy, Activity activity) { super(proxy, activity); timarkers = new ArrayList<TiMarker>(); currentCircles = new ArrayList<CircleProxy>(); currentPolygons = new ArrayList<PolygonProxy>(); currentPolylines = new ArrayList<PolylineProxy>(); } /** * Traverses through the view hierarchy to locate the SurfaceView and set * the background to transparent. * * @param v * the root view */ private void setBackgroundTransparent(View v) { if (v instanceof SurfaceView) { SurfaceView sv = (SurfaceView) v; sv.setBackgroundColor(Color.TRANSPARENT); } if (v instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) v; for (int i = 0; i < viewGroup.getChildCount(); i++) { setBackgroundTransparent(viewGroup.getChildAt(i)); } } } @Override protected Fragment createFragment() { if (proxy == null) { Fragment map = SupportMapFragment.newInstance(); if (map instanceof SupportMapFragment) { ((SupportMapFragment) map).getMapAsync(this); } return map; } else { boolean zOrderOnTop = TiConvert.toBoolean(proxy.getProperty(MapModule.PROPERTY_ZORDER_ON_TOP), false); GoogleMapOptions gOptions = new GoogleMapOptions(); gOptions.zOrderOnTop(zOrderOnTop); Fragment map = SupportMapFragment.newInstance(gOptions); if (map instanceof SupportMapFragment) { ((SupportMapFragment) map).getMapAsync(this); } return map; } } protected void processPreloadRoutes() { ArrayList<RouteProxy> routes = ((ViewProxy) proxy).getPreloadRoutes(); for (int i = 0; i < routes.size(); i++) { addRoute(routes.get(i)); } } protected void processPreloadCircles() { ArrayList<CircleProxy> circles = ((ViewProxy) proxy).getPreloadCircles(); for (int i = 0; i < circles.size(); i++) { addCircle(circles.get(i)); } } protected void processPreloadPolygons() { ArrayList<PolygonProxy> polygons = ((ViewProxy) proxy).getPreloadPolygons(); for (int i = 0; i < polygons.size(); i++) { addPolygon(polygons.get(i)); } } protected void processPreloadPolylines() { ArrayList<PolylineProxy> polylines = ((ViewProxy) proxy).getPreloadPolylines(); for (int i = 0; i < polylines.size(); i++) { addPolyline(polylines.get(i)); } } @Override public void onMapReady(GoogleMap gMap) { map = gMap; //A workaround for https://code.google.com/p/android/issues/detail?id=11676 pre Jelly Bean. //This problem doesn't exist on 4.1+ since the map base view changes to TextureView from SurfaceView. if (Build.VERSION.SDK_INT < 16) { View rootView = proxy.getActivity().findViewById(android.R.id.content); setBackgroundTransparent(rootView); } processMapProperties(proxy.getProperties()); processPreloadRoutes(); processPreloadPolygons(); processPreloadCircles(); processPreloadPolylines(); map.setOnMarkerClickListener(this); map.setOnMapClickListener(this); map.setOnCameraChangeListener(this); map.setOnMarkerDragListener(this); map.setOnInfoWindowClickListener(this); map.setInfoWindowAdapter(this); map.setOnMapLongClickListener(this); map.setOnMapLoadedCallback(this); ((ViewProxy) proxy).clearPreloadObjects(); } @Override public void processProperties(KrollDict d) { super.processProperties(d); if (map == null) { return; } processMapProperties(d); } public void processMapProperties(KrollDict d) { if (d.containsKey(TiC.PROPERTY_USER_LOCATION)) { setUserLocationEnabled(TiConvert.toBoolean(d, TiC.PROPERTY_USER_LOCATION, false)); } if (d.containsKey(MapModule.PROPERTY_USER_LOCATION_BUTTON)) { setUserLocationButtonEnabled(TiConvert.toBoolean(d, MapModule.PROPERTY_USER_LOCATION_BUTTON, true)); } if (d.containsKey(MapModule.PROPERTY_MAP_TOOLBAR_ENABLED)) { setMapToolbarEnabled(TiConvert.toBoolean(d, MapModule.PROPERTY_MAP_TOOLBAR_ENABLED, true)); } if (d.containsKey(TiC.PROPERTY_MAP_TYPE)) { setMapType(d.getInt(TiC.PROPERTY_MAP_TYPE)); } if (d.containsKey(MapModule.PROPERTY_TRAFFIC)) { setTrafficEnabled(d.getBoolean(MapModule.PROPERTY_TRAFFIC)); } if (d.containsKey(TiC.PROPERTY_ANIMATE)) { animate = d.getBoolean(TiC.PROPERTY_ANIMATE); } if (d.containsKey(TiC.PROPERTY_REGION)) { updateCamera(d.getKrollDict(TiC.PROPERTY_REGION)); } if (d.containsKey(TiC.PROPERTY_ANNOTATIONS)) { Object[] annotations = (Object[]) d.get(TiC.PROPERTY_ANNOTATIONS); addAnnotations(annotations); } if (d.containsKey(MapModule.PROPERTY_POLYGONS)) { Object[] polygons = (Object[]) d.get(MapModule.PROPERTY_POLYGONS); addPolygons(polygons); } if (d.containsKey(MapModule.PROPERTY_POLYLINES)) { Object[] polylines = (Object[]) d.get(MapModule.PROPERTY_POLYLINES); addPolylines(polylines); } if (d.containsKey(MapModule.PROPERTY_CIRCLES)) { Object[] circles = (Object[]) d.get(MapModule.PROPERTY_CIRCLES); addCircles(circles); } if (d.containsKey(TiC.PROPERTY_ENABLE_ZOOM_CONTROLS)) { setZoomControlsEnabled(TiConvert.toBoolean(d, TiC.PROPERTY_ENABLE_ZOOM_CONTROLS, true)); } if (d.containsKey(MapModule.PROPERTY_COMPASS_ENABLED)) { setCompassEnabled(TiConvert.toBoolean(d, MapModule.PROPERTY_COMPASS_ENABLED, true)); } } @Override public void propertyChanged(String key, Object oldValue, Object newValue, KrollProxy proxy) { if (newValue == null) { return; } if (key.equals(TiC.PROPERTY_USER_LOCATION)) { setUserLocationEnabled(TiConvert.toBoolean(newValue)); } else if (key.equals(MapModule.PROPERTY_USER_LOCATION_BUTTON)) { setUserLocationButtonEnabled(TiConvert.toBoolean(newValue)); } else if (key.equals(MapModule.PROPERTY_MAP_TOOLBAR_ENABLED)) { setMapToolbarEnabled(TiConvert.toBoolean(newValue)); } else if (key.equals(TiC.PROPERTY_MAP_TYPE)) { setMapType(TiConvert.toInt(newValue)); } else if (key.equals(TiC.PROPERTY_REGION)) { updateCamera((HashMap) newValue); } else if (key.equals(MapModule.PROPERTY_TRAFFIC)) { setTrafficEnabled(TiConvert.toBoolean(newValue)); } else if (key.equals(TiC.PROPERTY_ANIMATE)) { animate = TiConvert.toBoolean(newValue); } else if (key.equals(TiC.PROPERTY_ANNOTATIONS)) { updateAnnotations((Object[]) newValue); } else if (key.equals(MapModule.PROPERTY_COMPASS_ENABLED)) { setCompassEnabled(TiConvert.toBoolean(newValue, true)); } else if (key.equals(TiC.PROPERTY_ENABLE_ZOOM_CONTROLS)) { setZoomControlsEnabled(TiConvert.toBoolean(newValue, true)); } else { super.propertyChanged(key, oldValue, newValue, proxy); } } public GoogleMap getMap() { return map; } protected void setUserLocationEnabled(boolean enabled) { map.setMyLocationEnabled(enabled); } protected void setCompassEnabled(boolean enabled) { map.getUiSettings().setCompassEnabled(enabled); } protected void setUserLocationButtonEnabled(boolean enabled) { map.getUiSettings().setMyLocationButtonEnabled(enabled); } protected void setMapToolbarEnabled(boolean enabled) { map.getUiSettings().setMapToolbarEnabled(enabled); } public float getMaxZoomLevel() { return map.getMaxZoomLevel(); } public float getMinZoomLevel() { return map.getMinZoomLevel(); } protected void setMapType(int type) { map.setMapType(type); } protected void setTrafficEnabled(boolean enabled) { map.setTrafficEnabled(enabled); } protected void setZoomControlsEnabled(boolean enabled) { map.getUiSettings().setZoomControlsEnabled(enabled); } public void updateCamera(HashMap<String, Object> dict) { double longitude = 0; double longitudeDelta = 0; double latitude = 0; double latitudeDelta = 0; float bearing = 0; float tilt = 0; float zoom = 0; // In the setLocation() method, the old map module allows the user to // provide two more properties - "animate" and "regionFit". // In this map module, no matter "regionFit" is set to true or false, we // will always make sure the specified // latitudeDelta / longitudeDelta bounds are centered on screen at the // greatest possible zoom level. boolean anim = animate; if (dict.containsKey(TiC.PROPERTY_ANIMATE)) { anim = TiConvert.toBoolean(dict, TiC.PROPERTY_ANIMATE, animate); } if (dict.containsKey(MapModule.PROPERTY_BEARING)) { bearing = TiConvert.toFloat(dict, MapModule.PROPERTY_BEARING, 0); } if (dict.containsKey(MapModule.PROPERTY_TILT)) { tilt = TiConvert.toFloat(dict, MapModule.PROPERTY_TILT, 0); } if (dict.containsKey(MapModule.PROPERTY_ZOOM)) { zoom = TiConvert.toFloat(dict, MapModule.PROPERTY_ZOOM, 0); } // Workaround for toDouble since there is no method that allows you to set defaults if (dict.containsKey(TiC.PROPERTY_LATITUDE) && dict.get(TiC.PROPERTY_LATITUDE) != null) { latitude = TiConvert.toDouble(dict, TiC.PROPERTY_LATITUDE); } if (dict.containsKey(TiC.PROPERTY_LONGITUDE) && dict.get(TiC.PROPERTY_LONGITUDE) != null) { longitude = TiConvert.toDouble(dict, TiC.PROPERTY_LONGITUDE); } CameraPosition.Builder cameraBuilder = new CameraPosition.Builder(); LatLng location = new LatLng(latitude, longitude); cameraBuilder.target(location); cameraBuilder.bearing(bearing); cameraBuilder.tilt(tilt); cameraBuilder.zoom(zoom); if (dict.containsKey(TiC.PROPERTY_LATITUDE_DELTA) && dict.get(TiC.PROPERTY_LATITUDE_DELTA) != null) { latitudeDelta = TiConvert.toDouble(dict, TiC.PROPERTY_LATITUDE_DELTA); } if (dict.containsKey(TiC.PROPERTY_LONGITUDE_DELTA) && dict.get(TiC.PROPERTY_LONGITUDE_DELTA) != null) { longitudeDelta = TiConvert.toDouble(dict, TiC.PROPERTY_LONGITUDE_DELTA); } if (latitudeDelta != 0 && longitudeDelta != 0) { LatLng northeast = new LatLng(latitude + (latitudeDelta / 2.0), longitude + (longitudeDelta / 2.0)); LatLng southwest = new LatLng(latitude - (latitudeDelta / 2.0), longitude - (longitudeDelta / 2.0)); final LatLngBounds bounds = new LatLngBounds(southwest, northeast); if (preLayout) { preLayoutUpdateBounds = bounds; return; } else { moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), anim); return; } } CameraPosition position = cameraBuilder.build(); CameraUpdate camUpdate = CameraUpdateFactory.newCameraPosition(position); moveCamera(camUpdate, anim); } protected void moveCamera(CameraUpdate camUpdate, boolean anim) { if (anim) { map.animateCamera(camUpdate); } else { map.moveCamera(camUpdate); } } protected void addAnnotation(AnnotationProxy annotation) { // if annotation already on map, remove it first then re-add it TiMarker tiMarker = annotation.getTiMarker(); if (tiMarker != null) { removeAnnotation(tiMarker); } annotation.processOptions(); // add annotation to map view Marker marker = map.addMarker(annotation.getMarkerOptions()); tiMarker = new TiMarker(marker, annotation); annotation.setTiMarker(tiMarker); timarkers.add(tiMarker); } protected void addAnnotations(Object[] annotations) { for (int i = 0; i < annotations.length; i++) { Object obj = annotations[i]; if (obj instanceof AnnotationProxy) { AnnotationProxy annotation = (AnnotationProxy) obj; addAnnotation(annotation); } } } protected void updateAnnotations(Object[] annotations) { // First, remove old annotations from map removeAllAnnotations(); // Then we add new annotations to the map addAnnotations(annotations); } protected void removeAllAnnotations() { for (int i = 0; i < timarkers.size(); i++) { TiMarker timarker = timarkers.get(i); timarker.getMarker().remove(); AnnotationProxy proxy = timarker.getProxy(); if (proxy != null) { proxy.setTiMarker(null); } } timarkers.clear(); } public TiMarker findMarkerByTitle(String title) { for (int i = 0; i < timarkers.size(); i++) { TiMarker timarker = timarkers.get(i); AnnotationProxy annoProxy = timarker.getProxy(); if (annoProxy != null && annoProxy.getTitle().equals(title)) { return timarker; } } return null; } protected void removeAnnotation(Object annotation) { TiMarker timarker = null; if (annotation instanceof TiMarker) { timarker = (TiMarker) annotation; } else if (annotation instanceof AnnotationProxy) { timarker = ((AnnotationProxy) annotation).getTiMarker(); } else if (annotation instanceof String) { timarker = findMarkerByTitle((String) annotation); } if (timarker != null && timarkers.remove(timarker)) { timarker.getMarker().remove(); AnnotationProxy proxy = timarker.getProxy(); if (proxy != null) { proxy.setTiMarker(null); } } } protected void selectAnnotation(Object annotation) { if (annotation instanceof AnnotationProxy) { AnnotationProxy proxy = (AnnotationProxy) annotation; if (proxy.getTiMarker() != null) { proxy.showInfo(); selectedAnnotation = proxy; } } else if (annotation instanceof String) { String title = (String) annotation; TiMarker marker = findMarkerByTitle(title); if (marker != null) { marker.getMarker().showInfoWindow(); selectedAnnotation = marker.getProxy(); } } } protected void deselectAnnotation(Object annotation) { if (annotation instanceof AnnotationProxy) { AnnotationProxy proxy = (AnnotationProxy) annotation; if (proxy.getTiMarker() != null) { ((AnnotationProxy) annotation).hideInfo(); } } else if (annotation instanceof String) { String title = (String) annotation; TiMarker marker = findMarkerByTitle(title); if (marker != null) { marker.getMarker().hideInfoWindow(); } } selectedAnnotation = null; } private AnnotationProxy getProxyByMarker(Marker m) { if (m != null) { for (int i = 0; i < timarkers.size(); i++) { TiMarker timarker = timarkers.get(i); if (m.equals(timarker.getMarker())) { return timarker.getProxy(); } } } return null; } public void addRoute(RouteProxy r) { // check if route already added. if (r.getRoute() != null) { return; } r.processOptions(); r.setRoute(map.addPolyline(r.getOptions())); } public void removeRoute(RouteProxy r) { if (r.getRoute() == null) { return; } r.getRoute().remove(); r.setRoute(null); } /** * Polygon */ public void addPolygon(PolygonProxy p) { // check if polygon already added. if (p.getPolygon() != null) { return; } p.processOptions(); p.setPolygon(map.addPolygon(p.getOptions())); currentPolygons.add(p); } protected void addPolygons(Object[] polygons) { for (int i = 0; i < polygons.length; i++) { Object obj = polygons[i]; if (obj instanceof PolygonProxy) { PolygonProxy polygon = (PolygonProxy) obj; addPolygon(polygon); } } } public void removePolygon(PolygonProxy p) { if (p.getPolygon() == null) { return; } if (currentPolygons.contains(p)) { p.getPolygon().remove(); p.setPolygon(null); currentPolygons.remove(p); } } public void removeAllPolygons() { for (PolygonProxy polygonProxy : currentPolygons) { polygonProxy.getPolygon().remove(); polygonProxy.setPolygon(null); } currentPolygons.clear(); } /** * Polyline */ public void addPolyline(PolylineProxy p) { // check if polyline already added. if (p.getPolyline() != null) { return; } p.processOptions(); p.setPolyline(map.addPolyline(p.getOptions())); currentPolylines.add(p); } protected void addPolylines(Object[] polylines) { for (int i = 0; i < polylines.length; i++) { Object obj = polylines[i]; if (obj instanceof PolylineProxy) { PolylineProxy polyline = (PolylineProxy) obj; addPolyline(polyline); } } } public void removePolyline(PolylineProxy p) { if (p.getPolyline() == null) { return; } if (currentPolylines.contains(p)) { p.getPolyline().remove(); p.setPolyline(null); currentPolylines.remove(p); } } public void removeAllPolylines() { for (PolylineProxy polylineProxy : currentPolylines) { polylineProxy.getPolyline().remove(); polylineProxy.setPolyline(null); } currentPolylines.clear(); } /** * Circle */ protected void addCircles(Object[] circles) { for (int i = 0; i < circles.length; i++) { Object obj = circles[i]; if (obj instanceof CircleProxy) { CircleProxy circle = (CircleProxy) obj; addCircle(circle); } } } public void addCircle(CircleProxy c) { if (currentCircles.contains(c)) { return; } c.processOptions(); c.setCircle(map.addCircle(c.getOptions())); currentCircles.add(c); } public void removeCircle(CircleProxy c) { if (!currentCircles.contains(c)) { return; } c.getCircle().remove(); c.setCircle(null); currentCircles.remove(c); } public void removeAllCircles() { for (CircleProxy circleProxy : currentCircles) { circleProxy.getCircle().remove(); circleProxy.setCircle(null); } currentCircles.clear(); } public void changeZoomLevel(int delta) { CameraUpdate camUpdate = CameraUpdateFactory.zoomBy(delta); moveCamera(camUpdate, animate); } public void fireShapeClickEvent(LatLng clickPosition, IShape shapeProxy, String clickSource) { KrollDict d = new KrollDict(); d.put(TiC.PROPERTY_LATITUDE, clickPosition.latitude); d.put(TiC.PROPERTY_LONGITUDE, clickPosition.longitude); d.put(MapModule.PROPERTY_MAP, proxy); d.put(TiC.PROPERTY_TYPE, TiC.EVENT_CLICK); d.put(TiC.PROPERTY_SOURCE, shapeProxy); d.put(TiC.EVENT_PROPERTY_CLICKSOURCE, clickSource); // In iOS, sometimes the source property is forced to the mapProxy and // so we have to send along a more robust message via 'shape' and // 'shapeType'. d.put(MapModule.PROPERTY_SHAPE, shapeProxy); d.put(MapModule.PROPERTY_SHAPE_TYPE, clickSource); proxy.fireEvent(TiC.EVENT_CLICK, d); } public void fireClickEvent(Marker marker, AnnotationProxy annoProxy, String clickSource) { KrollDict d = new KrollDict(); String title = null; String subtitle = null; TiMapInfoWindow infoWindow = annoProxy.getMapInfoWindow(); if (infoWindow != null) { title = infoWindow.getTitle(); subtitle = infoWindow.getSubtitle(); } d.put(TiC.PROPERTY_TITLE, title); d.put(TiC.PROPERTY_SUBTITLE, subtitle); d.put(TiC.PROPERTY_LATITUDE, marker.getPosition().latitude); d.put(TiC.PROPERTY_LONGITUDE, marker.getPosition().longitude); d.put(TiC.PROPERTY_ANNOTATION, annoProxy); d.put(MapModule.PROPERTY_MAP, proxy); d.put(TiC.PROPERTY_TYPE, TiC.EVENT_CLICK); d.put(TiC.PROPERTY_SOURCE, proxy); d.put(TiC.EVENT_PROPERTY_CLICKSOURCE, clickSource); proxy.fireEvent(TiC.EVENT_CLICK, d); } public void fireLongClickEvent(LatLng point) { KrollDict d = new KrollDict(); d.put(TiC.PROPERTY_LATITUDE, point.latitude); d.put(TiC.PROPERTY_LONGITUDE, point.longitude); d.put(MapModule.PROPERTY_MAP, proxy); d.put(TiC.PROPERTY_TYPE, TiC.EVENT_LONGCLICK); d.put(TiC.PROPERTY_SOURCE, proxy); proxy.fireEvent(TiC.EVENT_LONGCLICK, d); } public void firePinChangeDragStateEvent(Marker marker, AnnotationProxy annoProxy, int dragState) { KrollDict d = new KrollDict(); String title = null; TiMapInfoWindow infoWindow = annoProxy.getMapInfoWindow(); if (infoWindow != null) { title = infoWindow.getTitle(); } d.put(TiC.PROPERTY_TITLE, title); d.put(TiC.PROPERTY_ANNOTATION, annoProxy); d.put(MapModule.PROPERTY_MAP, proxy); d.put(TiC.PROPERTY_SOURCE, proxy); d.put(MapModule.PROPERTY_NEWSTATE, dragState); d.put(TiC.PROPERTY_TYPE, MapModule.EVENT_PIN_CHANGE_DRAG_STATE); proxy.fireEvent(MapModule.EVENT_PIN_CHANGE_DRAG_STATE, d); } @Override public boolean onMarkerClick(Marker marker) { AnnotationProxy annoProxy = getProxyByMarker(marker); if (annoProxy == null) { Log.e(TAG, "Marker can not be found, click event won't fired.", Log.DEBUG_MODE); return false; } else if (selectedAnnotation != null && selectedAnnotation.equals(annoProxy)) { selectedAnnotation.hideInfo(); selectedAnnotation = null; fireClickEvent(marker, annoProxy, MapModule.PROPERTY_PIN); return true; } fireClickEvent(marker, annoProxy, MapModule.PROPERTY_PIN); selectedAnnotation = annoProxy; boolean showInfoWindow = TiConvert.toBoolean(annoProxy.getProperty(MapModule.PROPERTY_SHOW_INFO_WINDOW), true); // Returning false here will enable native behavior, which shows the // info window. if (showInfoWindow) { return false; } else { return true; } } @Override public void onMapClick(LatLng point) { if (selectedAnnotation != null) { TiMarker tiMarker = selectedAnnotation.getTiMarker(); if (tiMarker != null) { fireClickEvent(tiMarker.getMarker(), selectedAnnotation, null); } selectedAnnotation = null; } // currentCircles if (currentCircles.size() > 0) { for (CircleProxy circleProxy : currentCircles) { Circle circle = circleProxy.getCircle(); LatLng center = circle.getCenter(); double radius = circle.getRadius(); float[] distance = new float[1]; Location.distanceBetween(point.latitude, point.longitude, center.latitude, center.longitude, distance); boolean clicked = distance[0] < radius; if (clicked) { fireShapeClickEvent(point, circleProxy, MapModule.PROPERTY_CIRCLE); } } } // currentPolygons if (currentPolygons.size() > 0) { Boundary boundary = new Boundary(); ArrayList<PolygonProxy> clickedPolygon = boundary.contains(currentPolygons, point); boundary = null; if (clickedPolygon.size() > 0) { for (PolygonProxy polygonProxy : clickedPolygon) { fireShapeClickEvent(point, polygonProxy, MapModule.PROPERTY_POLYGON); } } } // currentPolylines if (currentPolylines.size() > 0) { PolylineBoundary boundary = new PolylineBoundary(); double baseVal = 2; LatLngBounds b = map.getProjection().getVisibleRegion().latLngBounds; double side1 = b.northeast.latitude > b.southwest.latitude ? (b.northeast.latitude - b.southwest.latitude) : (b.southwest.latitude - b.northeast.latitude); double side2 = b.northeast.longitude > b.southwest.longitude ? (b.northeast.longitude - b.southwest.longitude) : (b.southwest.longitude - b.northeast.longitude); double diagonal = Math.sqrt((side1 * side1) + (side2 * side2)); double val = diagonal / map.getCameraPosition().zoom; ArrayList<PolylineProxy> clickedPolylines = boundary.contains(currentPolylines, point, val); boundary = null; if (clickedPolylines.size() > 0) { for (PolylineProxy polylineProxy : clickedPolylines) { fireShapeClickEvent(point, polylineProxy, MapModule.PROPERTY_POLYLINE); } } } } @Override public void onMapLongClick(LatLng point) { fireLongClickEvent(point); } @Override public void onMarkerDrag(Marker marker) { Log.d(TAG, "The annotation is dragged.", Log.DEBUG_MODE); } @Override public void onMarkerDragEnd(Marker marker) { AnnotationProxy annoProxy = getProxyByMarker(marker); if (annoProxy != null) { LatLng position = marker.getPosition(); annoProxy.setProperty(TiC.PROPERTY_LONGITUDE, position.longitude); annoProxy.setProperty(TiC.PROPERTY_LATITUDE, position.latitude); firePinChangeDragStateEvent(marker, annoProxy, MapModule.ANNOTATION_DRAG_STATE_END); } } @Override public void onMarkerDragStart(Marker marker) { AnnotationProxy annoProxy = getProxyByMarker(marker); if (annoProxy != null) { firePinChangeDragStateEvent(marker, annoProxy, MapModule.ANNOTATION_DRAG_STATE_START); } } @Override public void onInfoWindowClick(Marker marker) { AnnotationProxy annoProxy = getProxyByMarker(marker); if (annoProxy != null) { String clicksource = annoProxy.getMapInfoWindow().getClicksource(); // The clicksource is null means the click event is not inside // "leftPane", "title", "subtible" // or "rightPane". In this case, use "infoWindow" as the // clicksource. if (clicksource == null) { clicksource = MapModule.PROPERTY_INFO_WINDOW; } fireClickEvent(marker, annoProxy, clicksource); } } @Override public View getInfoContents(Marker marker) { AnnotationProxy annoProxy = getProxyByMarker(marker); if (annoProxy != null) { return annoProxy.getMapInfoWindow(); } return null; } @Override public View getInfoWindow(Marker marker) { return null; } @Override public void release() { selectedAnnotation = null; if (map != null) { map.clear(); } currentCircles = null; currentPolygons = null; currentPolylines = null; map = null; timarkers.clear(); super.release(); } @Override public void onCameraChange(CameraPosition position) { if (preLayout) { if (preLayoutUpdateBounds != null) { moveCamera(CameraUpdateFactory.newLatLngBounds(preLayoutUpdateBounds, 0), animate); preLayoutUpdateBounds = null; } else { // moveCamera will trigger another callback, so we do this to // make sure // we don't fire event when region is set initially preLayout = false; } } else if (proxy != null) { KrollDict d = new KrollDict(); d.put(TiC.PROPERTY_LATITUDE, position.target.latitude); d.put(TiC.PROPERTY_LONGITUDE, position.target.longitude); d.put(TiC.PROPERTY_SOURCE, proxy); LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; d.put(TiC.PROPERTY_LATITUDE_DELTA, (bounds.northeast.latitude - bounds.southwest.latitude)); d.put(TiC.PROPERTY_LONGITUDE_DELTA, (bounds.northeast.longitude - bounds.southwest.longitude)); // In iOS, the region property is updated in the // 'regionDidChangeAnimated' method. // This allows a user to call getRegion and receive the current map // bounds proxy.setProperty(TiC.PROPERTY_REGION, d); proxy.fireEvent(TiC.EVENT_REGION_CHANGED, d); } } // Intercept the touch event to find out the correct clicksource if clicking // on the info window. @Override protected boolean interceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_UP && selectedAnnotation != null) { TiMapInfoWindow infoWindow = selectedAnnotation.getMapInfoWindow(); TiMarker timarker = selectedAnnotation.getTiMarker(); if (infoWindow != null && timarker != null) { Marker marker = timarker.getMarker(); if (marker != null && marker.isInfoWindowShown()) { Point markerPoint = map.getProjection().toScreenLocation(marker.getPosition()); infoWindow.analyzeTouchEvent(ev, markerPoint, selectedAnnotation.getIconImageHeight()); } } } return false; } public void snapshot() { map.snapshot(new GoogleMap.SnapshotReadyCallback() { @Override public void onSnapshotReady(Bitmap snapshot) { TiBlob sblob = TiBlob.blobFromImage(snapshot); KrollDict data = new KrollDict(); data.put("snapshot", sblob); data.put("source", proxy); proxy.fireEvent(MapModule.EVENT_ON_SNAPSHOT_READY, data); } }); } @Override public void onMapLoaded() { proxy.fireEvent(TiC.EVENT_COMPLETE, null); } protected void onViewCreated() { // keep around for backward compatibility } }