/************************************************************************* * Copyright (c) 2015 Lemberg Solutions * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **************************************************************************/ package com.ls.demo.demo2; import java.util.ArrayList; import android.app.Activity; import android.graphics.Color; import android.graphics.Point; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.location.Location; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.RelativeLayout; import com.ls.demo.demo2.model.MapObjectContainer; import com.ls.demo.demo2.model.MapObjectModel; import com.ls.demo.demo2.popup.TextPopup; import com.ls.widgets.map.MapWidget; import com.ls.widgets.map.config.GPSConfig; import com.ls.widgets.map.config.MapGraphicsConfig; import com.ls.widgets.map.config.OfflineMapConfig; import com.ls.widgets.map.events.MapScrolledEvent; import com.ls.widgets.map.events.MapTouchedEvent; import com.ls.widgets.map.events.ObjectTouchEvent; import com.ls.widgets.map.interfaces.Layer; import com.ls.widgets.map.interfaces.MapEventsListener; import com.ls.widgets.map.interfaces.OnLocationChangedListener; import com.ls.widgets.map.interfaces.OnMapScrollListener; import com.ls.widgets.map.interfaces.OnMapTouchListener; import com.ls.widgets.map.location.PositionMarker; import com.ls.widgets.map.model.MapObject; import com.ls.widgets.map.utils.PivotFactory; import com.ls.widgets.map.utils.PivotFactory.PivotPosition; public class BrowseMapActivity extends Activity implements MapEventsListener, OnMapTouchListener { private static final String TAG = "BrowseMapActivity"; private static final Integer LAYER1_ID = 0; private static final Integer LAYER2_ID = 1; private static final int MAP_ID = 23; private int nextObjectId; private int pinHeight; private MapObjectContainer model; private MapWidget map; private TextPopup mapObjectInfoPopup; private Location points[]; private int currentPoint; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); nextObjectId = 0; model = new MapObjectContainer(); initTestLocationPoints(); initMap(savedInstanceState); initModel(); initMapObjects(); initMapListeners(); // Will show the position of the user on a map. // Do not forget to enable ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permission int the manifest. // Uncomment this if you are at Filitheyo island :) // map.setShowMyPosition(true); map.centerMap(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); map.saveState(outState); } private void initTestLocationPoints() { points = new Location[5]; for (int i=0; i<points.length; ++i) { points[i] = new Location("test"); } points[0].setLatitude(3.2127012756213316); points[0].setLongitude(73.03406774997711); points[1].setLatitude(3.2122245926560167); points[1].setLongitude(73.03744733333588); points[2].setLatitude(3.2112819380469135); points[2].setLongitude(73.03983449935913); points[3].setLatitude(3.2130494147249915); points[3].setLongitude(73.03946435451508); points[4].setLatitude(3.2148276002942713); points[4].setLongitude(73.03796768188477); currentPoint = 0; } private Location getNextLocationPoint() { if (currentPoint < points.length-1) { currentPoint += 1; } else { currentPoint = 0; } return points[currentPoint]; } private void initMap(Bundle savedInstanceState) { // In order to display the map on the screen you will need // to initialize widget and place it into layout. map = new MapWidget(savedInstanceState, this, "map", // root name of the map under assets folder. 10); // initial zoom level map.setId(MAP_ID); OfflineMapConfig config = map.getConfig(); config.setPinchZoomEnabled(true); // Sets pinch gesture to zoom config.setFlingEnabled(true); // Sets inertial scrolling of the map config.setMaxZoomLevelLimit(20); config.setZoomBtnsVisible(true); // Sets embedded zoom buttons visible // Configuration of GPS receiver GPSConfig gpsConfig = config.getGpsConfig(); gpsConfig.setPassiveMode(false); gpsConfig.setGPSUpdateInterval(500, 5); // Configuration of position marker MapGraphicsConfig graphicsConfig = config.getGraphicsConfig(); graphicsConfig.setAccuracyAreaColor(0x550000FF); // Blue with transparency graphicsConfig.setAccuracyAreaBorderColor(Color.BLUE); // Blue without transparency RelativeLayout layout = (RelativeLayout) findViewById(R.id.rootLayout); // Adding the map to the layout layout.addView(map, 0); layout.setBackgroundColor(Color.parseColor("#0049FF")); // Adding layers in order to put there some map objects map.createLayer(LAYER1_ID); // you will need layer id's in order to access particular layer map.createLayer(LAYER2_ID); } private void initModel() { // Adding objects to the model // You may want to implement your own model MapObjectModel objectModel = new MapObjectModel(0, 100, 100, "Shows above the image 1"); model.addObject(objectModel); objectModel = new MapObjectModel(1, 600, 350, "Shows above the image 2"); model.addObject(objectModel); int id = 2; for (Location point:points) { objectModel = new MapObjectModel(id, point, "Point " + id); model.addObject(objectModel); id += 1; } } private void initMapObjects() { mapObjectInfoPopup = new TextPopup(this, (RelativeLayout)findViewById(R.id.rootLayout)); Layer layer1 = map.getLayerById(LAYER1_ID); Layer layer2 = map.getLayerById(LAYER2_ID); for (int i=0; i<model.size(); ++i) { addNotScalableMapObject(model.getObject(i), layer1); } // Adding two map objects to the second layer addScalableMapObject(800, 300, layer2); addNotScalableMapObject(900, 350, layer2); } private void addNotScalableMapObject(int x, int y, Layer layer) { // Getting the drawable of the map object Drawable drawable = getResources().getDrawable(R.drawable.map_object); pinHeight = drawable.getIntrinsicHeight(); // Creating the map object MapObject object1 = new MapObject(Integer.valueOf(nextObjectId), // id, will be passed to the listener when user clicks on it drawable, new Point(x, y), // coordinates in original map coordinate system. // Pivot point of center of the drawable in the drawable's coordinate system. PivotFactory.createPivotPoint(drawable, PivotPosition.PIVOT_CENTER), true, // This object will be passed to the listener false); // is not scalable. It will have the same size on each zoom level // Adding object to layer layer.addMapObject(object1); nextObjectId += 1; } private void addNotScalableMapObject(MapObjectModel objectModel, Layer layer) { if (objectModel.getLocation() != null) { addNotScalableMapObject(objectModel.getLocation(), layer); } else { addNotScalableMapObject(objectModel.getX(), objectModel.getY(), layer); } } private void addNotScalableMapObject(Location location, Layer layer) { if (location == null) return; // Getting the drawable of the map object Drawable drawable = getResources().getDrawable(R.drawable.map_object); // Creating the map object MapObject object1 = new MapObject(Integer.valueOf(nextObjectId), // id, will be passed to the listener when user clicks on it drawable, new Point(0, 0), // coordinates in original map coordinate system. // Pivot point of center of the drawable in the drawable's coordinate system. PivotFactory.createPivotPoint(drawable, PivotPosition.PIVOT_CENTER), true, // This object will be passed to the listener true); // is not scalable. It will have the same size on each zoom level layer.addMapObject(object1); // Will crash if you try to move before adding to the layer. object1.moveTo(location); nextObjectId += 1; } private void addScalableMapObject(int x, int y, Layer layer) { Drawable drawable = getResources().getDrawable(R.drawable.map_object); MapObject object1 = new MapObject(Integer.valueOf(nextObjectId), drawable, x, y, true, true); layer.addMapObject(object1); nextObjectId += 1; } private void initMapListeners() { // In order to receive MapObject touch events we need to set listener map.setOnMapTouchListener(this); // In order to receive pre and post zoom events we need to set MapEventsListener map.addMapEventsListener(this); // In order to receive map scroll events we set OnMapScrollListener map.setOnMapScrolledListener(new OnMapScrollListener() { public void onScrolledEvent(MapWidget v, MapScrolledEvent event) { handleOnMapScroll(v, event); } }); map.setOnLocationChangedListener(new OnLocationChangedListener() { @Override public void onLocationChanged(MapWidget v, Location location) { // You can handle location change here. // For example you can scroll to new location by using v.scrollMapTo(location) } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = new MenuInflater(this); inflater.inflate(R.menu.menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.zoomIn: map.zoomIn(); return true; case R.id.zoomOut: map.zoomOut(); return true; case R.id.hideLayer2: { Layer layer = map.getLayerById(LAYER2_ID); if (layer != null) { layer.setVisible(false); map.invalidate(); // Need to repaint the layer. This is a bug and will be fixed in next version. } return true; } case R.id.showLayer2: { Layer layer = map.getLayerById(LAYER2_ID); if (layer != null) { layer.setVisible(true); map.invalidate(); // Need to repaint the layer. This is a bug and will be fixed in next version. } return true; } case R.id.scroll_next: map.scrollMapTo(getNextLocationPoint()); break; } return super.onOptionsItemSelected(item); } private void handleOnMapScroll(MapWidget v, MapScrolledEvent event) { // When user scrolls the map we receive scroll events // This is useful when need to move some object together with the map int dx = event.getDX(); // Number of pixels that user has scrolled horizontally int dy = event.getDY(); // Number of pixels that user has scrolled vertically if (mapObjectInfoPopup.isVisible()) { mapObjectInfoPopup.moveBy(dx, dy); } } @Override public void onPostZoomIn() { Log.i(TAG, "onPostZoomIn()"); } @Override public void onPostZoomOut() { Log.i(TAG, "onPostZoomOut()"); } @Override public void onPreZoomIn() { Log.i(TAG, "onPreZoomIn()"); if (mapObjectInfoPopup != null) { mapObjectInfoPopup.hide(); } } @Override public void onPreZoomOut() { Log.i(TAG, "onPreZoomOut()"); if (mapObjectInfoPopup != null) { mapObjectInfoPopup.hide(); } } //* On map touch listener implemetnation *// @Override public void onTouch(MapWidget v, MapTouchedEvent event) { // Get touched object events from the MapTouchEvent ArrayList<ObjectTouchEvent> touchedObjs = event.getTouchedObjectIds(); if (touchedObjs.size() > 0) { int xInMapCoords = event.getMapX(); int yInMapCoords = event.getMapY(); int xInScreenCoords = event.getScreenX(); int yInScreenCoords = event.getScreenY(); ObjectTouchEvent objectTouchEvent = event.getTouchedObjectIds().get(0); // Due to a bug this is not actually the layer id, but index of the layer in layers array. // Will be fixed in the next release. long layerId = objectTouchEvent.getLayerId(); Integer objectId = (Integer)objectTouchEvent.getObjectId(); // User has touched one or more map object // We will take the first one to show in the toast message. String message = "You touched the object with id: " + objectId + " on layer: " + layerId + " mapX: " + xInMapCoords + " mapY: " + yInMapCoords + " screenX: " + xInScreenCoords + " screenY: " + yInScreenCoords; Log.d(TAG, message); MapObjectModel objectModel = model.getObjectById(objectId.intValue()); if (objectModel != null) { // This is a case when we want to show popup info exactly above the pin image float density = getResources().getDisplayMetrics().density; int imgHeight = (int) (pinHeight / density / 2); // Calculating position of popup on the screen int x = xToScreenCoords(objectModel.getX()); int y = yToScreenCoords(objectModel.getY()) - imgHeight; // Show it showLocationsPopup(x, y, objectModel.getCaption()); } else { // This is a case when we want to show popup where the user has touched. showLocationsPopup(xInScreenCoords, yInScreenCoords, "Shows where user touched"); } // Hint: If user touched more than one object you can show the dialog in which ask // the user to select concrete object } else { if (mapObjectInfoPopup != null) { mapObjectInfoPopup.hide(); } } } private void showLocationsPopup(int x, int y, String text) { RelativeLayout mapLayout = (RelativeLayout) findViewById(R.id.rootLayout); if (mapObjectInfoPopup != null) { mapObjectInfoPopup.hide(); } ((TextPopup) mapObjectInfoPopup).setIcon((BitmapDrawable) getResources().getDrawable(R.drawable.map_popup_arrow)); ((TextPopup) mapObjectInfoPopup).setText(text); mapObjectInfoPopup.setOnClickListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { if (mapObjectInfoPopup != null) { mapObjectInfoPopup.hide(); } } return false; } }); ((TextPopup) mapObjectInfoPopup).show(mapLayout, x, y); } /*** * Transforms coordinate in map coordinate system to screen coordinate system * @param mapCoord - X in map coordinate in pixels. * @return X coordinate in screen coordinates. You can use this value to display any object on the screen. */ private int xToScreenCoords(int mapCoord) { return (int)(mapCoord * map.getScale() - map.getScrollX()); } private int yToScreenCoords(int mapCoord) { return (int)(mapCoord * map.getScale() - map.getScrollY()); } }