Animated Drawable MyLocationOverlay() - android

Is it possible to over-ride MyLocationOverlay()'s onDraw method and replace the standard flashing blue icon with something else. What are the ways I could implement this?

Really good answer to your question here:
myLocationOverlay change the marker
Draw an animated GIF image within the drawMyLocation(..) function. Display Animated GIF
public class CurrentLocationOverlay extends MyLocationOverlay {
// TODO: use dynamic calculation?
private final static int PADDING_ACTIVE_ZOOM = 50;
private MapController mc;
private Bitmap marker;
private Point currentPoint = new Point();
private boolean centerOnCurrentLocation = true;
private int height;
private int width;
/**
* By default this CurrentLocationOverlay will center on the current location, if the currentLocation is near the
* edge, or off the screen. To dynamically enable/disable this, use {#link #setCenterOnCurrentLocation(boolean)}.
*
* #param context
* #param mapView
*/
public CurrentLocationOverlay(Context context, MapView mapView) {
super(context, mapView);
this.mc = mapView.getController();
this.marker = BitmapFactory.decodeResource(context.getResources(), R.drawable.position);
}
#Override
protected void drawMyLocation(Canvas canvas, MapView mapView, Location lastFix, GeoPoint myLocation, long when) {
// TODO: find a better way to get height/width once the mapView is layed out correctly
if (this.height == 0) {
this.height = mapView.getHeight();
this.width = mapView.getWidth();
}
mapView.getProjection().toPixels(myLocation, currentPoint);
canvas.drawBitmap(marker, currentPoint.x, currentPoint.y - 40, null);
}
#Override
public synchronized void onLocationChanged(Location location) {
super.onLocationChanged(location);
// only move to new position if enabled and we are in an border-area
if (mc != null && centerOnCurrentLocation && inZoomActiveArea(currentPoint)) {
mc.animateTo(getMyLocation());
}
}
private boolean inZoomActiveArea(Point currentPoint) {
if ((currentPoint.x > PADDING_ACTIVE_ZOOM && currentPoint.x < width - PADDING_ACTIVE_ZOOM)
&& (currentPoint.y > PADDING_ACTIVE_ZOOM && currentPoint.y < height - PADDING_ACTIVE_ZOOM)) {
return false;
}
return true;
}
public void setCenterOnCurrentLocation(boolean centerOnCurrentLocation) {
this.centerOnCurrentLocation = centerOnCurrentLocation;
}
}

Related

Two finger rotation for OSMdroid mapview

I'm trying to make two finger rotation for my offline maps using osmdroid. I'm new to using maps for android. I have a geoTIFF, I'm planning to extract info using NDK and later send it to JAVA. I need to use the geoPoint to align with True North Up using compass as well. How can I proceed, any help?
I did try this:
Android Two finger rotation
example, but no luck, my app was not able to detect any two finger event.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
setContentView(R.layout.activity_main);
mapView = (MapView)findViewById(R.id.mapview);
//Mapview touch utilities
mapView.setClickable(true);
mapView.setBuiltInZoomControls(true);
mapView.setMultiTouchControls(true);
//set initial zoom-level, depends on your need
mapView.getController().setZoom(nMyZoom);
//Display Position Overlay
/* Itemized Overlay */
{
/* Create a static ItemizedOverlay showing a some Markers on some cities. */
final ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
items.add(new OverlayItem("Fruchthalle", "Kaiserslautern", new GeoPoint(nMyLat, nMyLong)));
/* OnTapListener for the Markers, shows a simple Toast. */
this.mMyLocationOverlay = new ItemizedIconOverlay<OverlayItem>(items,
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
#Override
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
Toast.makeText(
MainActivity.this,
"Place '" + item.getTitle()+ "' (index=" + index
+ ") got single tapped up", Toast.LENGTH_LONG).show();
return true; // We 'handled' this event.
}
#Override
public boolean onItemLongPress(final int index, final OverlayItem item) {
Toast.makeText(
MainActivity.this,
"Place '" + item.getTitle() + "' (index=" + index
+ ") got long pressed", Toast.LENGTH_LONG).show();
return false;
}
}, mResourceProxy);
this.mapView.getOverlays().add(this.mMyLocationOverlay);
}
Have you taken a look at the OpenStreetMapViewer sample app? There is the RotationGestureOverlay overlay in there that specifically shows how to do this. It isn't as smooth as I would like it, but it will do the job.
For simplicity, use the following classes:
public class RotationGestureDetector {
public interface RotationListener {
public void onRotate(float deltaAngle);
}
protected float mRotation;
private RotationListener mListener;
public RotationGestureDetector(RotationListener listener) {
mListener = listener;
}
private float rotation(MotionEvent event) {
double delta_x = (event.getX(0) - event.getX(1));
double delta_y = (event.getY(0) - event.getY(1));
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
public void onTouch(MotionEvent e) {
if (e.getPointerCount() != 2)
return;
if (e.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
mRotation = rotation(e);
}
float rotation = rotation(e);
float delta = rotation - mRotation;
mRotation += delta;
mListener.onRotate(delta);
}
}
And
public class RotationGestureOverlay extends Overlay implements RotationGestureDetector.RotationListener
{
private final RotationGestureDetector mRotationDetector;
private RotationGestureDetector.RotationListener rotationListener;
public RotationGestureOverlay(Context context, RotationGestureDetector.RotationListener rotationListener)
{
super(context);
this.rotationListener = rotationListener;
mRotationDetector = new RotationGestureDetector(this);
}
#Override
public boolean onTouchEvent(MotionEvent event, MapView mapView)
{
if (this.isEnabled()) {
mRotationDetector.onTouch(event);
}
return super.onTouchEvent(event, mapView);
}
#Override
public void onRotate(float deltaAngle)
{
rotationListener.onRotate(deltaAngle);
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean b) {
}
}
Add the overlay:
mapView.getOverlays().add(new RotationGestureOverlay(context,this);

Detect if the OSM Mapview is still loading or not in android

I have included Open Street Maps in my android application. In the mapview, user should be able to capture the screen after the map is fully loaded. But currently user can capture the image even when the mapview is still loading. Can someone tell me how to detect when the mapview is fully loaded?
Below is my code to load the mapview:
public class MainActivity extends Activity {
MapView mapView;
MyLocationOverlay myLocationOverlay = null;
ArrayList<OverlayItem> anotherOverlayItemArray;
protected ItemizedOverlayWithBubble<ExtendedOverlayItem> itineraryMarkers;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mapView = (MapView) findViewById(R.id.mapview);
final ArrayList<ExtendedOverlayItem> waypointsItems = new ArrayList<ExtendedOverlayItem>();
itineraryMarkers = new ItemizedOverlayWithBubble<ExtendedOverlayItem>(this, waypointsItems, mapView, new ViaPointInfoWindow(R.layout.itinerary_bubble, mapView));
mapView.getOverlays().add(itineraryMarkers);
mapView.setTileSource(TileSourceFactory.MAPNIK);
mapView.setBuiltInZoomControls(true);
MapController mapController = mapView.getController();
mapController.setZoom(1);
GeoPoint point2 = new GeoPoint(51496994, -134733);
mapController.setCenter(point2);
Drawable marker=getResources().getDrawable(android.R.drawable.star_big_on);
GeoPoint myPoint1 = new GeoPoint(0*1000000, 0*1000000);
ExtendedOverlayItem overlayItem = new ExtendedOverlayItem("Title Test Loc", "Desc", myPoint1, this);
overlayItem.setMarkerHotspot(OverlayItem.HotspotPlace.BOTTOM_CENTER);
overlayItem.setMarker(marker);
overlayItem.setRelatedObject(0);
itineraryMarkers.addItem(overlayItem);
mapView.invalidate();
myLocationOverlay = new MyLocationOverlay(this, mapView);
mapView.getOverlays().add(myLocationOverlay);
myLocationOverlay.enableMyLocation();
myLocationOverlay.runOnFirstFix(new Runnable() {
public void run() {
mapView.getController().animateTo(myLocationOverlay.getMyLocation());
}
});
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
myLocationOverlay.enableMyLocation();
myLocationOverlay.enableCompass();
myLocationOverlay.enableFollowLocation();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
myLocationOverlay.disableMyLocation();
myLocationOverlay.disableCompass();
myLocationOverlay.disableFollowLocation();
}
Take a look at TilesOverlay and the TileLooper implementation. This is what we use to load and then draw each tile on the screen. In handleTile(...) we attempt to get the tile from the tile provider mTileProvider.getMapTile(pTile). If that returns a Drawable then the tile is loaded, if not it will return null.
A simple way to do this is to extend TilesOverlay, override drawTiles(...) and call your own TileLooper before calling super.drawTiles(...) that will check to see if all the tiles that get passed to handleTile(...) are not null. To use your TilesOverlay call mMapView.getOverlayManager().setTilesOverlay(myTilesOverlay).
Since osmdroid API 6.1.0, it's quite easy:
// check completeness of map tiles
TileStates tileStates = mapView.getOverlayManager().getTilesOverlay().getTileStates();
// evaluate the tile states
if (tileStates.getTotal() == tileStates.getUpToDate())
{
// map is loaded completely
}
else
{
// loading is still in progress
}
/* meaning of TileStates
.getUpToDate() not expired yet
.getExpired() expired
.getScaled() computed during zoom
.getNotFound() default grey tile
---------------------------------------
.getTotal() sum of all above
*/
I created a class named "MyTileOverlay" by extending TilesOverlay and it contins this class:
https://code.google.com/p/osmdroid/source/browse/trunk/osmdroid-android/src/main/java/org/osmdroid/views/overlay/TilesOverlay.java?r=1086
Then when setting up the mapview, I do this:
this.mTilesOverlay = new MyTileOverlay(mProvider, this.getBaseContext());
As instructed by kurtzmarc, I used handleTile() to check whether all tiles are being loaded or not:
#Override
public void handleTile(final Canvas pCanvas, final int pTileSizePx,
final MapTile pTile, final int pX, final int pY) {
Drawable currentMapTile = mTileProvider.getMapTile(pTile);
if (currentMapTile == null) {
currentMapTile = getLoadingTile();
Log.d("Tile Null", "Null");
} else {
Log.d("Tile Not Null", "Not Null");
}
if (currentMapTile != null) {
mTileRect.set(pX * pTileSizePx, pY * pTileSizePx, pX
* pTileSizePx + pTileSizePx, pY * pTileSizePx
+ pTileSizePx);
onTileReadyToDraw(pCanvas, currentMapTile, mTileRect);
}
if (DEBUGMODE) {
mTileRect.set(pX * pTileSizePx, pY * pTileSizePx, pX
* pTileSizePx + pTileSizePx, pY * pTileSizePx
+ pTileSizePx);
mTileRect.offset(-mWorldSize_2, -mWorldSize_2);
pCanvas.drawText(pTile.toString(), mTileRect.left + 1,
mTileRect.top + mDebugPaint.getTextSize(),
mDebugPaint);
pCanvas.drawLine(mTileRect.left, mTileRect.top,
mTileRect.right, mTileRect.top, mDebugPaint);
pCanvas.drawLine(mTileRect.left, mTileRect.top,
mTileRect.left, mTileRect.bottom, mDebugPaint);
}
}
This method ensures whether the loading procedure is finalized or not:
#Override
public void finaliseLoop() {
Log.d("Loop Finalized", "Finalized");
}
I can also use this method to identify whether all tiles have been loaded or not:
public int getLoadingBackgroundColor() {
return mLoadingBackgroundColor;
}
Hope this help someone!
You can pass a runnable callback to the TileStates class of the tile overlay:
overlayManager.tilesOverlay.tileStates.runAfters.add(Runnable {
// Tile loading completed
})
Works quite well.

android, customized ItemizedOverlay

There is already an overlay, drawing something on a map view. I want to add another overlay and a customized item to the map view. Nothing shows. What's wrong with my code? Thanks heaps.
My sub-class of ItemizedOverlay
public class PinItemizedOverlay extends ItemizedOverlay {
private static int MAX_PIN = 3;
private OverlayItem overlays[] = new OverlayItem[MAX_PIN];
private int index = 0;
private boolean full = false;
private Context context;
public PinItemizedOverlay(Context context, Drawable defaultMarker) {
//super(boundCenterBottom(defaultMarker));
super(boundCenterBottom(defaultMarker));
this.context = context;
}
#Override
public OverlayItem createItem(int index) {
return overlays[index];
}
public int size(){
if (full) {
return overlays.length;
} else {
return index;
}
}
public void addOverlay(OverlayItem overlay) {
if (index < MAX_PIN) {
overlays[index] = overlay;
} else {
return;
}
index++;
populate();
}
}
My customized overlay item
public class LocationPinItem extends OverlayItem{
public LocationEntity location;
public LocationPinItem(GeoPoint point, int iconRes, LocationEntity location){
//super(point,null,null);
super(point, null, null);
Drawable marker = getApplicationContext().getResources().getDrawable(iconRes);
super.setMarker(marker );
this.location = location;
}
}
And the function where I add the customized item (it's a drop pin):
private void createMarkerAt(LocationEntity location, String extra, int iconRes, boolean clear, boolean animate) {
if(location == null) {
return;
}
GeoPoint point = new GeoPoint((int) (location.latitude * 1E6), (int) (location.longitude * 1E6));
LocationPinItem pinItem = new LocationPinItem(point,R.drawable.ic_swap,location);
PinItemizedOverlay pinOverlay = new PinItemizedOverlay(getApplicationContext(),mMapDrawable) ;
pinOverlay.addOverlay(pinItem);
mMapView.removeAllViews();
mMapView.postInvalidate();
mMapView.getOverlays().add(pinOverlay);
if(animate) {
mMapView.getController().animateTo(location.toGeoPoint());
}
}
never mind, I figured it out: the newly-added overlay occludes the previous overlay

How to display bottom of an image on the top of a marker when we tap on a marker in google maps android

i have written a google maps mulitple markers application.When i tap on a marker i have written a code to display a nine patch image on the top of marker.But here when i taps the nine patch image is not displaying on the top of a marker in a google map.It is displaying just after the marker and at the same time the bottom edge of the nine patch image is touching the surface of the map.How can i display the nine patch image bottom exactly on the top the marker when i tap on that marker.My code is as follows.
public class MarkerMapActivity extends BaseMapActivity {
public static String name;
public static String completeAddress;
public static String address;
private MyItemizedOverlay funPlaces;
public MapView mapView;
public List<Overlay> mapOverlays;
List<Overlay> markersList;
Drawable marker;
public String nameAddressStr;
public ImageView blueArrowIdValue;
public LinearLayout layout;
//Displays Markers on GoogleMap.
public void displayMarkersOnMap(){
mapView = (MapView)findViewById(R.id.mapView);
new GoogleMapAsyncTask().execute();
}
#Override
protected boolean isLocationDisplayed() {
return false;
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
public class MyItemizedOverlay extends BalloonItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> m_overlays = new ArrayList<OverlayItem>();
#SuppressWarnings("unused")
private Context c;
private GeoPoint center = null;
public MyItemizedOverlay(GeoPoint point, Drawable marker,String hmtostring,String nameaddress,MapView mapView) {
super(boundCenter(marker), mapView);
c = mapView.getContext();
m_overlays.add(new OverlayItem(point,hmtostring,nameaddress));
populate();
}
public GeoPoint getCenterPt() {
if (center == null) {
int northEdge = -90000000;
int southEdge = 90000000;
int eastEdge = -180000000;
int westEdge = 180000000;
Iterator<OverlayItem> iter = m_overlays.iterator();
while (iter.hasNext()) {
GeoPoint pt = iter.next().getPoint();
if (pt.getLatitudeE6() > northEdge)
northEdge = pt.getLatitudeE6();
if (pt.getLatitudeE6() < southEdge)
southEdge = pt.getLatitudeE6();
if (pt.getLongitudeE6() > eastEdge)
eastEdge = pt.getLongitudeE6();
if (pt.getLongitudeE6() < westEdge)
westEdge = pt.getLongitudeE6();
}
center = new GeoPoint((int) ((northEdge + southEdge) / 2),
(int) ((westEdge + eastEdge) / 2));
}
return center;
}
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
if (!shadow) {
super.draw(canvas, mapView, shadow);
}
return false;
}
public void addOverlay(OverlayItem overlay) {
m_overlays.add(overlay);
populate();
}
#Override
protected OverlayItem createItem(int i) {
return m_overlays.get(i);
}
#Override
public int size() {
return m_overlays.size();
}
#Override
protected boolean onBalloonTap(int index) {
return true;
}
}
public abstract class BalloonItemizedOverlay<Item> extends ItemizedOverlay<OverlayItem>{
private MapView mapView;
private BalloonOverlayView balloonView;
private View clickRegion;
private int viewOffset;
final MapController mc;
/**
* Create a new BalloonItemizedOverlay
*
* #param defaultMarker - A bounded Drawable to be drawn on the map for each item in the overlay.
* #param mapView - The view upon which the overlay items are to be drawn.
*/
public BalloonItemizedOverlay(Drawable defaultMarker, MapView mapView) {
super(defaultMarker);
this.mapView = mapView;
viewOffset = 0;
mc = mapView.getController();
}
/**
* Set the horizontal distance between the marker and the bottom of the information
* balloon. The default is 0 which works well for center bounded markers. If your
* marker is center-bottom bounded, this before adding overlay items to ensure
* the balloon hovers exactly above the marker.
*
* #param pixels - The padding between the center point and the bottom of the
* information balloon.
*/
public void setBalloonBottomOffset(int pixels) {
viewOffset = pixels;
}
/**
* Override this method to handle a "tap" on a balloon. By default, does nothing
* and returns false.
*
* #param index - The index of the item whose balloon is tapped.
* #return true if you handled the tap, otherwise false.
*/
protected boolean onBalloonTap(int index) {
return false;
}
/* (non-Javadoc)
* #see com.google.android.maps.ItemizedOverlay#onTap(int)
*/
#Override
protected final boolean onTap(int index) {
boolean isRecycled;
final int thisIndex;
GeoPoint point;
thisIndex = index;
point = createItem(index).getPoint();
if (balloonView == null) {
balloonView = new BalloonOverlayView(mapView.getContext(), viewOffset);
clickRegion = (View) balloonView.findViewById(R.id.balloon_inner_layout);
isRecycled = false;
} else {
isRecycled = true;
}
balloonView.setVisibility(View.GONE);
List<Overlay> mapOverlays = mapView.getOverlays();
if (mapOverlays.size() > 1) {
hideOtherBalloons(mapOverlays);
}
balloonView.setData(createItem(index));
MapView.LayoutParams params = new MapView.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, point,
MapView.LayoutParams.BOTTOM_CENTER);
params.mode = MapView.LayoutParams.MODE_MAP;
setBalloonTouchListener(thisIndex);
balloonView.setVisibility(View.VISIBLE);
if (isRecycled) {
balloonView.setLayoutParams(params);
} else {
mapView.addView(balloonView, params);
}
mc.animateTo(point);
//balloonView.setOnClickListener(this);
return true;
}
/*public void onClick(View v){
switch(v.getId()){
case R.id.balloon_inner_layout:
balloonView.setVisibility(View.GONE);
break;
}
}*/
/**
* Sets the visibility of this overlay's balloon view to GONE.
*/
private void hideBalloon() {
if (balloonView != null) {
balloonView.setVisibility(View.GONE);
}
}
/**
* Hides the balloon view for any other BalloonItemizedOverlay instances
* that might be present on the MapView.
*
* #param overlays - list of overlays (including this) on the MapView.
*/
private void hideOtherBalloons(List<Overlay> overlays) {
for (Overlay overlay : overlays) {
if (overlay instanceof BalloonItemizedOverlay<?> && overlay != this) {
((BalloonItemizedOverlay<?>) overlay).hideBalloon();
}
}
}
/**
* Sets the onTouchListener for the balloon being displayed, calling the
* overridden onBalloonTap if implemented.
*
* #param thisIndex - The index of the item whose balloon is tapped.
*/
private void setBalloonTouchListener(final int thisIndex) {
try {
#SuppressWarnings("unused")
Method m = this.getClass().getDeclaredMethod("onBalloonTap", int.class);
clickRegion.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
View l = ((View) v.getParent()).findViewById(R.id.balloon_main_layout);
Drawable d = l.getBackground();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int[] states = {android.R.attr.state_pressed};
if (d.setState(states)) {
d.invalidateSelf();
}
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
int newStates[] = {};
if (d.setState(newStates)) {
d.invalidateSelf();
}
// call overridden method
onBalloonTap(thisIndex);
return true;
} else {
return false;
}
}
});
} catch (SecurityException e) {
Log.e("BalloonItemizedOverlay", "setBalloonTouchListener reflection SecurityException");
return;
} catch (NoSuchMethodException e) {
// method not overridden - do nothing
return;
}
}
}
public class BalloonOverlayView extends FrameLayout {
//private LinearLayout layout;
private TextView pinAddressIdValue;
#SuppressWarnings("unused")
private String nameAddress;
#SuppressWarnings("unused")
private LinearLayout mainLinLayout;
/**
* Create a new BalloonOverlayView.
*
* #param context - The activity context.
* #param balloonBottomOffset - The bottom padding (in pixels) to be applied
* when rendering this view.
*/
public BalloonOverlayView(Context context, int balloonBottomOffset) {
super(context);
setPadding(10, 0, 10, balloonBottomOffset);
layout = new LinearLayout(context);
layout.setVisibility(VISIBLE);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.pinclick, layout);
pinAddressIdValue = (TextView) v.findViewById(R.id.pinAddressId);
mainLinLayout=(LinearLayout)v.findViewById(R.id.balloon_main_layout);
blueArrowIdValue = (ImageView) v.findViewById(R.id.blueArrowId);
ImageView blueArrowIdValue = (ImageView) v.findViewById(R.id.blueArrowId);
blueArrowIdValue.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
layout.setVisibility(GONE);
DetailsPinScreen.nameAddress=nameAddressStr;
TabsScreen parentDetailsPin = (TabsScreen)MarkerMapActivity.this.getParent();
parentDetailsPin.detailsPinScreenEmployees(true);
DetailsPinScreen.dpses.setValues();
DetailsPinScreen.dpses.loadStaticGoogleMap();
DetailsPinScreen.dpses.currenLocLatLong();
}
});
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.NO_GRAVITY;
addView(layout, params);
}
/**
* Sets the view data from a given overlay item.
*
* #param item - The overlay item containing the relevant view data
* (title and snippet).
*/
public void setData(OverlayItem item) {
layout.setVisibility(VISIBLE);
if (item.getTitle() != null) {
nameAddress=item.getTitle();
}else {
}
if (item.getSnippet() != null) {
pinAddressIdValue.setVisibility(VISIBLE);
String nameaddress=item.getSnippet();
pinAddressIdValue.setText(nameaddress);
}else {
pinAddressIdValue.setVisibility(GONE);
}
}
}
private class GoogleMapAsyncTask extends AsyncTask<Void,Void,Void>{
public Void doInBackground(Void...voids ){
Drawable marker;
try{
StringBuffer strBuffer=new StringBuffer();
strBuffer.append("name=");
strBuffer.append(name);
strBuffer.append("\n");
strBuffer.append("address=");
strBuffer.append(completeAddress);
nameAddressStr=strBuffer.toString();
marker = getResources().getDrawable(R.drawable.pin_green);
marker.setBounds((int) (-marker.getIntrinsicWidth() / 2),-marker.getIntrinsicHeight(),(int) (marker.getIntrinsicWidth() / 2), 0);
Geocoder geoCoder = new Geocoder(MarkerMapActivity.this, Locale.getDefault());
List<Address> addresses = geoCoder.getFromLocationName(completeAddress,5);
if (addresses.size() > 0) {
GeoPoint point =new GeoPoint((int) (addresses.get(0).getLatitude() * 1E6),(int) (addresses.get(0).getLongitude() * 1E6));
funPlaces = new MyItemizedOverlay(point,marker,nameAddressStr,completeAddress,mapView);
markersList=mapView.getOverlays();
markersList.clear();
markersList.add(funPlaces);
}
}catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
for(int i=0;i<mapView.getOverlays().size();i++){
GeoPoint pt = funPlaces.getCenterPt();
MapController mc = mapView.getController();
mc.setCenter(pt);
}
}
}
}
Actually map is displaying but here i have not shown.

Problem with drawing location using a custom Drawable in an Android OverlayItem

This code is using
the Google APIs (level 8).
When I update the OverlayItem to use a custom drawable the Canvas
object seems to draw the pixels in the wrong location. In this
example I'm trying to draw a circle in Louisiana. When viewing the
entire map the circle is drawn off the map. As you zoom into New
Orleans you'll see the circle approach the appropriate latitude and
longitude. The hot spot seems to be in the correct location, no
matter where the circle is being drawn.
If, in the draw method, the canvas restore method is called the circle
draws in the correct location.
Also If the custom drawable is not used, the icon is drawn in the
correct location (without using Canvas "restore").
Below is the code showing this behavior. I tried adding "setBounds"
and "boundCenterBottom", since other people seemed to indicate that
resolved their "wrong location" problems. Though
to be honest I'm not sure why those calls are needed.
=======================================================================
public class MapsActivity extends MapActivity
{
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MapView mapView = (MapView) findViewById(R.id.mapView);
mapView.setBuiltInZoomControls(true);
// Itemized Overlay
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable defaultIcon =
this.getResources().getDrawable(R.drawable.icon);
MyItemizedOverlay itemizedoverlay = new
MyItemizedOverlay(defaultIcon, this);
// Overlay Item
GeoPoint pt = new GeoPoint(30000000, -90000000);
OverlayItem item = new OverlayItem(pt,"New Orleans",
"Louisiana");
// Custom Drawable
CustomDrawable customDrawable = new CustomDrawable(pt,
mapView);
boolean showProblem = true;
if (showProblem)
{
item.setMarker(customDrawable);
}
else
{
item.setMarker(defaultIcon);
}
// Add item we want to overlay
itemizedoverlay.addOverlay(item);
// Add overlay
mapOverlays.add(itemizedoverlay);
}
protected boolean isRouteDisplayed()
{
return false;
}
}
=======================================================================
public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem>
{
private ArrayList<OverlayItem> mOverlays = new
ArrayList<OverlayItem>();
private Context mContext;
public MyItemizedOverlay(Drawable defaultMarker, Context context)
{
super(boundCenterBottom(defaultMarker));
mContext = context;
}
public void addOverlay(OverlayItem item)
{
mOverlays.add(item);
populate();
}
public void removeOverlay(OverlayItem item)
{
mOverlays.remove(item);
}
public void removeOverlay(int item)
{
mOverlays.remove(item);
}
protected OverlayItem createItem(int i)
{
OverlayItem item = mOverlays.get(i);
Drawable drawable = item.getMarker(0);
if (drawable != null)
{
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, w, h);
item.setMarker(boundCenterBottom(drawable));
}
return item;
}
public void draw(android.graphics.Canvas canvas, MapView mapView,
boolean shadow)
{
if (shadow)
return;
super.draw(canvas, mapView, shadow);
}
public int size()
{
return mOverlays.size();
}
protected boolean onTap(int index)
{
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new
AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
}
=======================================================================
public class CustomDrawable extends ShapeDrawable
{
private int radius = 10;
private GeoPoint point = null;
private MapView mapView = null;
public CustomDrawable(GeoPoint point, MapView mapView)
{
this.point = point;
this.mapView = mapView;
}
public void draw(Canvas canvas)
{
// TODO This (somewhat) fixes projection problem?
//canvas.restore();
Projection projection = mapView.getProjection();
Point pt = projection.toPixels(point, null);
canvas.drawCircle(pt.x, pt.y, radius,
getPaint());
}
public int getIntrinsicHeight()
{
return 2 * radius;
}
public int getIntrinsicWidth()
{
return 2 * radius;
}
}
=======================================================================
Your CustomDrawable shouldn't be positioning itself with respect to the map. It should just draw itself within its bounds, and not reference the MapView or its Projection. ItemizedOverlay takes care of positioning the Drawable for your OverlayItem.

Categories

Resources