I am building a car navigation application in Xamarin.Android (native not forms). I had read a lot, and follow instructions I found on how to add the map in the application and also how to use the location services, either with the FusedLocationProvider or the NavigationManager. I decided to use the NavigationManager since it looks more accurate because of the number of decimal digits (14) in the LatLng. All good up to now. I am testing my app and while the marker and the map are moving, in order to follow the car's direction, the map is blurred (see the attached pictures), it looks like it does not have the appropriate time to get refreshed.
What I am doing in order to move the camera and the marker?
1. OnLocationChanged from the LocationManager I am calling the UpdateCameraBearing function
internal static void UpdateCameraBearing(float bearing, Location newLocation)
{
if (Map == null)
return;
// Save current zoom
int originalZoom = (int)Map.CameraPosition.Zoom;
if (!startingZoom.HasValue)
{
startingZoom = originalZoom = MapZoomDef;
}
LastLocation = newLocation;
LatLng newPosition = new LatLng(newLocation.Latitude, newLocation.Longitude);
CameraPosition camPos = new CameraPosition(newPosition, originalZoom != MapZoomDef ? originalZoom : MapZoomDef, 0, bearing);
try
{
Map.AnimateCamera(CameraUpdateFactory.NewCameraPosition(camPos));
UpdateMarkerPosition(newPosition);
}
catch (Exception ex)
{
Log.Error(TAG, ex.Message);
}
}
This function animates the camera to the new position and also updates the marker position using the UpdateMarkerPosition function as follows
private static void UpdateMarkerPosition(LatLng newPosition)
{
if (null == MapMarker)
{
SetNewMarker(newPosition);
}
else
{
//positionMarker.Visible = true;
//positionMarker.Position = newPosition;
AnimateMarker(newPosition, new LatLngInterpolatorSpherical());
}
}
private static void SetNewMarker(LatLng myPosition)
{
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.SetPosition(myPosition);
markerOptions.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Mipmap.ic_car));
MapMarker = Map.AddMarker(markerOptions);
}
private static void AnimateMarker(LatLng finalPosition, LatLngInterpolatorSpherical latLngInterpolator)
{
Android.OS.Handler handler = new Android.OS.Handler();
long start = Android.OS.SystemClock.UptimeMillis();
LatLng startPosition = MapMarker.Position;
Android.Views.Animations.AccelerateDecelerateInterpolator interpolator = new Android.Views.Animations.AccelerateDecelerateInterpolator();
float durationInMs = 1000;
Java.Lang.Runnable mUpdateGeneration = null;
mUpdateGeneration = new Java.Lang.Runnable(() => {
long elapsed;
float t;
float v;
// Calculate progress using interpolator
elapsed = Android.OS.SystemClock.UptimeMillis() - start;
t = elapsed / durationInMs;
v = interpolator.GetInterpolation(t);
MapMarker.Position = latLngInterpolator.Interpolate(v, startPosition, finalPosition);
// Repeat till progress is complete.
if (t < 1)
{
// Post again 16ms later.
handler.PostDelayed(mUpdateGeneration, 16);
}
});
handler.Post(mUpdateGeneration);
}
The UpdateMarkerPosition function checks if the marker exists and if not (this is the first time) it creates it, otherwise it calls the AnimateMarker function where I am using an Interpolator in order to simulate a smooth marker movement.
Last but not least the LocationManager.RequestLocationUpdates is configured with 1-second minimum time and 1-meter minimum Distance.
I will appreciate any suggestions on how to solve the problem...
enter image description here
enter image description here
Related
I'm trying to show a ground overlay with markers on it to my users. I'm trying to restrain the view to only this image placed on the map. I want the user to only see the image as a ground overlay placed on the map and not be able to go to the surrounding map. And if they go over the edge, the gestures will be blocked.
I want something like this:
I don't want this:
show-only-ground-overlays-map-android or this:
I tried to set my map.setLatLngBoundsForCameraTarget() to my image bounds but the result is something like the previous image...
The next thing I tried is to set a bunch of LatLng objects all around the ground overlay and check with curScreen.contains(customMapDetectionPoints.get(LatLng Object)) to see if they appear on the viewport. It's does work but I can't stop the camera to go over the edge...
Here my test code so far :
private GroundOverlay groundOverlay;
private GoogleMap globalMap;
private final int DETECTION_POINTS_CUSTOM_MAP = 20;
private List<LatLng> customMapDetectionPoints = new ArrayList<>();
//Fully Working as suppose to
#Override
public void onMapReady(GoogleMap map) {
//Other Stuff...
LatLngBounds mapBounds = groundOverlay.getBounds();
map.setLatLngBoundsForCameraTarget(mapBounds);
globalMap = map;
LatLng northwest = new LatLng( mapBounds.northeast.latitude, mapBounds.southwest.longitude);
LatLng northeast = mapBounds.northeast;
LatLng southeast = new LatLng( mapBounds.southwest.latitude, mapBounds.northeast.longitude);
LatLng southwest = mapBounds.southwest;
//My ground overlay is rectangle so I don't need to follow a path or something like that
setDetectionPoints(northwest, southwest);
setDetectionPoints(northeast, southeast);
setDetectionPoints(northwest, northeast);
setDetectionPoints(southwest, southeast);
map.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
#Override
public void onCameraMoveStarted(int i) {
LatLngBounds curScreen = globalMap.getProjection().getVisibleRegion().latLngBounds;
CameraPosition cameraPosition = globalMap.getCameraPosition();
for (int x =0;x<customMapDetectionPoints.size();x++) {
if (curScreen.contains(customMapDetectionPoints.get(x))) {
cancelMapMovement(cameraPosition);
Log.d("OUT", "Ground Overlay is outside viewport");
return;
} else {
globalMap.getUiSettings().setAllGesturesEnabled(true);
Log.d("IN", "Ground Overlay is inside viewport");
}
}
}
});
//Add 20 new location between two location
//Fully Working as suppose to
public void setDetectionPoints(LatLng fromPos, LatLng toPos) {
double pointLatitude = fromPos.latitude;
double pointLongitude = fromPos.longitude;
double addingValue;
if (fromPos.latitude == toPos.latitude) {
addingValue = (toPos.longitude - fromPos.longitude)/DETECTION_POINTS_CUSTOM_MAP;
for (int i = 0; i < DETECTION_POINTS_CUSTOM_MAP; i++) {
pointLongitude += addingValue;
LatLng pointsPos = new LatLng(pointLatitude, pointLongitude);
customMapDetectionPoints.add(pointsPos);
}
} else if (fromPos.longitude == toPos.longitude) {
addingValue = (toPos.latitude - fromPos.latitude)/DETECTION_POINTS_CUSTOM_MAP;
for (int i = 0; i < DETECTION_POINTS_CUSTOM_MAP; i++) {
pointLatitude += addingValue;
LatLng pointsPos = new LatLng(pointLatitude, pointLongitude);
customMapDetectionPoints.add(pointsPos);
}
}
}
//The problem is here!
public void cancelMapMovement(CameraPosition camPos ) {
//HOW CAN I STOP THE MOVEMENT OVER THE GROUND OVERLAY EDGE
//And make sure that the user dosen't see over the edge
globalMap.getUiSettings().setAllGesturesEnabled(false);
globalMap.moveCamera(CameraUpdateFactory.newCameraPosition(camPos));
}
At this point I think I have two possible solutions:
1- Only use the setLatLngBoundsForCameraTarget() function and set a offset or margin to the camera. But is it possible and will it work for my use case ?
2- Solve my camera restriction problem with the code already written
Thanks for helping! Suggest other solution if you find one!
I will provide more info if wanted.
I am working on map base application to animate marker. There are one marker which is updated against 30 sec interval from server. Marker always move to center of the Map ,so i close moveCamera marker but when marker move outside the map then marker is not come in map view. so i want to camera move when marker goes from map view
Before setting new position of the marker, check it's new position and current bounds of map view.
LatLng newPosition = new LatLng(...);
boolean contains = mMap.getProjection()
.getVisibleRegion()
.latLngBounds
.contains(newPosition);
if(!contains){
// MOVE CAMERA
}
// UPDATE MARKER POSITION
During the marker's each new position inside map view, marker moves(not
center of map)
Just If next position goes out of view, camera and marker will be centered.
Edit
I created a sample route to simulate each point on map periodically. Route gist
public class SampleRoute {
public static List<LatLng> GetPoints() {
return new ArrayList<>(Arrays.asList(
new LatLng(38.4670419, 27.1647131),
new LatLng(38.4667244, 27.1648277),
new LatLng(38.4666633, 27.1649079),
new LatLng(38.4665983, 27.1648022),
new LatLng(38.4665958, 27.1647843),
new LatLng(38.4665958, 27.1647843),
new LatLng(38.4665809, 27.1646429),
new LatLng(38.4665704, 27.1645506),
new LatLng(38.4665529, 27.1644067),
...
}
}
}
Then i create a method in sample activity that calculates current region's bounds and marker's X, Y points on this region. Activity gist
private void moveCamera(LatLng destination){
Projection projection = mMap.getProjection();
LatLngBounds bounds = projection.getVisibleRegion().latLngBounds;
int boundsTopY = projection.toScreenLocation(bounds.northeast).y;
int boundsBottomY = projection.toScreenLocation(bounds.southwest).y;
int boundsTopX = projection.toScreenLocation(bounds.northeast).x;
int boundsBottomX = projection.toScreenLocation(bounds.southwest).x;
int offsetY = (boundsBottomY - boundsTopY) / 10;
int offsetX = (boundsTopX - boundsBottomX ) / 10;
Point destinationPoint = projection.toScreenLocation(destination);
int destinationX = destinationPoint.x;
int destinationY = destinationPoint.y;
int scrollX = 0;
int scrollY = 0;
if(destinationY <= (boundsTopY + offsetY)){
scrollY = -(Math.abs((boundsTopY + offsetY) - destinationY));
}
else if(destinationY >= (boundsBottomY - offsetY)){
scrollY = (Math.abs(destinationY - (boundsBottomY - offsetY)));
}
if(destinationX >= (boundsTopX - offsetX)){
scrollX = (Math.abs(destinationX - (boundsTopX - offsetX)));
}
else if(destinationX <= (boundsBottomX + offsetX)){
scrollX = -(Math.abs((boundsBottomX + offsetX) - destinationX));
}
mMap.animateCamera(CameraUpdateFactory.scrollBy(scrollX, scrollY));
mMarker.setPosition(destination);
}
And then started to simulate points
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
moveCamera(mPoints.get(mCurrentPos));
if(++mCurrentPos < mPoints.size()){
mHandler.postDelayed(this, 1500);
}
}
}, 1500);
I tried and it's working well on me
So, if i understand you correctly and it works for you too then i could explain.
When marker location is updated you can animate the camera to the marker position. Following sample code may help you
LatLng definedLoc = new LatLng(latitudeValue, longitudeValue);
CameraPosition cameraPosition = new CameraPosition.Builder().target(definedLoc).zoom(13.0F).build();
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
You can animate the camera to the Marker position if the map bounds does not contain the marker using a GoogleMap.OnCameraChangeListener:
private Marker marker;
// ...
#Override
public void onCameraChange(final CameraPosition cameraPosition) {
ensureMarkerOnBounds();
}
private void ensureMarkerOnBounds() {
if (marker != null) {
if (!mMap.getProjection().getVisibleRegion().latLngBounds.contains(marker.getPosition())) {
mMap.animateCamera(CameraUpdateFactory.newLatLng(marker.getPosition()));
}
}
}
// This is the function that you use to move your marker
private void moveMarker (Marker marker) {
// ... Your code to move your marker
ensureMarkerOnBounds();
}
I have to show real time/live user moving location in google map once user turn on the feature and up-to terminating it.
I have had used the method below to animate the marker.
private void animateMarker(final Marker marker, final LatLng toPosition,
final boolean hideMarker) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = mMap.getProjection();
Point startPoint = proj.toScreenLocation(marker.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 1000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
double lng = t * toPosition.longitude + (1 - t)
* startLatLng.longitude;
double lat = t * toPosition.latitude + (1 - t)
* startLatLng.latitude;
marker.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
marker.setVisible(false);
} else {
marker.setVisible(true);
}
}
}
});
}
And using the following code am moving the map too.
// Showing the current location in Google Map
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
// Zoom in the Google Map
mMap.animateCamera(CameraUpdateFactory.zoomTo(15));
What I had done so far isn't good enough to move the marker and map together. it's not looking that perfect. I have to move the map along with marker together.
Source Code
Thank you.
What I done in my similar project is like: Assume I have a list of point where user navigated one by one so, I want to display that trip in map with animation. Instead of moving both marker and camera same time you can move marker between two points and then animate camera to that second point, now again move marker to next point and then when marker reach out next point animate your camera.
To get this working you have to modify your code little bit.
Add this code:
private static final int ANIMATE_SPEEED_TURN = 1000;
private static final int BEARING_OFFSET = 20;
if (t < 1) {
mHandler.postDelayed(this, 16);
} else {
// your code
if (hideMarker) {
marker.setVisible(false);
} else {
marker.setVisible(true);
}
//my added code
LatLng begin = getBeginLatLng();// current point
LatLng end = getEndLatLng();// next point
float bearingL = bearingBetweenLatLngs(begin, end);
CameraPosition cameraPosition =
new CameraPosition.Builder()
.target(end)
.bearing(bearingL + BEARING_OFFSET)
.tilt(tilt)
.zoom(googleMap.getCameraPosition().zoom)
.build();
googleMap.animateCamera(
CameraUpdateFactory.newCameraPosition(cameraPosition),
ANIMATE_SPEEED_TURN,
null
);
mHandler.postDelayed(animator, 16);
}
Let me know If anything goes wrong!!!
For detailed step visit Animating the map
I'm displaying a Google Maps API v2 MapView in an Android app, but it's curiously not updating properly in a consistent fashion. I'm using the GPS to update the map position (tried both LocationManager and LocationClient) and although the map moves to the position, about fifty percent of the time either the street name layer fails to update or there's a fuzzy/blurry section that fails to update--until I do a manual drag (scroll) of the map. Then the entire map updates instantly. I've stripped out a lot of the processing in the app to see if I was somehow preventing a refresh, but it didn't make a difference.
I inserted a mapView.invalidate() call in onCameraChange but that oddly seemed to make the problem occur more readily (although still not 100% of the time).
I am implementing all of the Activity callbacks as required by MapView.
Has anyone encountered a problem like this with Google Map API v2 on Android? If so, did you identify the cause and how did you solve it?
You have to let the map breathe so to speak.
Use animateCamera with a CancelableCallback then when the animation is completed you'll get a call back to onFinish() start the next animation.
public class KmlReader extends ActionBarActivity implements
CancelableCallback {
#Override
public void onFinish() {
startAnimation(); // start next map movement
}
#Override
public void onCancel() {
//Called when user interacts with the map while it is moving.
}
public void startAnimation(){
cameraPosition = mMap.getCameraPosition();
LatLng ll = new LatLng(expectedLocation.getLatitude(),
expectedLocation.getLongitude());
cb.zoom(cameraPosition.zoom)
// previous camera tilt
.tilt(cameraPosition.tilt)
// new expected destination
.target(ll)
// north up or heading view
.bearing((isHeading) ? bearing : 0f);
cameraPosition = cb.build();
CameraUpdate update = CameraUpdateFactory
.newCameraPosition(cameraPosition);
mMap.animateCamera(update, working_interval, this);
}
* Edit this is the code I'm working on now.*
it uses an asynctask for the calcuations. I've given it a walking test but haven't tested it in a vehicle.
private static CameraPosition currentCameraPosition;
private static com.google.android.gms.maps.model.CameraPosition.Builder cameraPositionBuilder;
private volatile CameraUpdate nextCameraUpdate;
// updates
private static final long UPDATE_INTERVAL = 2500;
// fastest
private static final int FASTEST_INTERVAL = 2500;
private static int working_interval = 5000;
private volatile boolean isAnimating;
// Define the callback method that receives location updates
#SuppressLint("NewApi")
#Override
public void onLocationChanged(Location location) {
Log.d("test", Boolean.toString(isAnimating) +" onlocation");
currentCameraPosition = mMap.getCameraPosition();
NewCameraUpdateTask newCameraUpdateTask = new NewCameraUpdateTask();
// This task must run async
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
newCameraUpdateTask.executeOnExecutor(
AsyncTask.THREAD_POOL_EXECUTOR, location);
} else {
newCameraUpdateTask.execute(location);
}
// speed display
setMetersPerSecond(location.getSpeed());
}
// create a newCameraUpdate to move the map with
private class NewCameraUpdateTask extends
AsyncTask<Location, Void, CameraUpdate> {
#Override
protected CameraUpdate doInBackground(Location... params) {
Location workingLocation = null;
CameraUpdate newCameraUpdate = null;
float bearing = 0f;
float speed = 0f;
for (Location mlocation : params) {
speed = mlocation.getSpeed();
// camera position is saved before the start of each animation.
LatLng ll;
if (!mlocation.hasBearing() || speed == 0) {
workingLocation = mlocation;
// previous bearing
} else {
// current bearing
bearing = mlocation.getBearing();
// calculate the age of the location
// atempt for animation to end a little bit past when
// the
// next
// location arrives.
// (location.getSpeed()m/s)(1/1000 interval seconds)(
// 1/1000
// km/m)
// (1/6371 radians/km) = radians/6371000000.0
double expectedDistance = working_interval / 6371000000.0
* speed;
// latitude in Radians
double currentLatitude = Math.toRadians(mlocation
.getLatitude());
// longitude in Radians
double currentlongitude = Math.toRadians(mlocation
.getLongitude());
double calcBearing = Math.toRadians(bearing);
// the camera position is needed so I can put in the
// previous camera bearing when the location has no
// bearing. This should prevent the map from
// zooming to north when the device stops moving.
// calculate the expected latitude and longitude based
// on
// staring
// location
// , bearing, and distance
double sincurrentLatitude = Math.sin(currentLatitude);
double coscurrentLatitude = Math.cos(currentLatitude);
double cosexpectedDistance = Math.cos(expectedDistance);
double sinexpectedDistance = Math.sin(expectedDistance);
double expectedLatitude = Math.asin(sincurrentLatitude
* cosexpectedDistance + coscurrentLatitude
* sinexpectedDistance * Math.cos(calcBearing));
double a = Math.atan2(
Math.sin(calcBearing) * sinexpectedDistance
* coscurrentLatitude,
cosexpectedDistance - sincurrentLatitude
* Math.sin(expectedLatitude));
double expectedLongitude = currentlongitude + a;
expectedLongitude = (expectedLongitude + PI3) % PI2 - PI;
// convert to degrees for the expected destination
double expectedLongitudeDestination = Math
.toDegrees(expectedLongitude);
double expectedLatitudeDestination = Math
.toDegrees(expectedLatitude);
mlocation.setLatitude(expectedLatitudeDestination);
mlocation.setLongitude(expectedLongitudeDestination);
workingLocation = mlocation;
}
break;
}
if (workingLocation != null) {
if (workingLocation.hasBearing()) {
bearing = workingLocation.getBearing();
} else {
bearing = currentCameraPosition.bearing;
}
LatLng ll = new LatLng(workingLocation.getLatitude(),
workingLocation.getLongitude());
cameraPositionBuilder.zoom(currentCameraPosition.zoom)
// previous camera tilt
.tilt(currentCameraPosition.tilt)
// new expected destination
.target(ll)
// north up or heading view
.bearing((isHeading) ? bearing : 0f);
newCameraUpdate = CameraUpdateFactory
.newCameraPosition(cameraPositionBuilder.build());
}
return newCameraUpdate;
}
#Override
protected void onPostExecute(CameraUpdate result) {
Log.d("test", Boolean.toString(isAnimating) + " onPostExecute");
if (result != null) {
nextCameraUpdate = result;
// stop the currently playing animation
// there is a new one ready to start
if (isAnimating) {
if (mMap != null) {
mMap.stopAnimation();
}
}
// start the next animation
startAnimation();
Log.d("test", Boolean.toString(isAnimating) +" onPostExecuteComplete");
}
}
}
// called when map animation has been canceled
#Override
public void onCancel() {
Log.d("test", Boolean.toString(isAnimating) +" oncancel");
isAnimating = false;
}
#Override
public void onFinish() {
Log.d("test", Boolean.toString(isAnimating) +" onfinish");
isAnimating = false;
startAnimation();
// call to start saved animation.
}
private void startAnimation() {
Log.d("test", Boolean.toString(isAnimating) +" startAnimation");
if (action_track) {
if (isAnimating) {
return;
}
if (nextCameraUpdate == null) {
return;
}
// abort if animating
isAnimating = true;
CameraUpdate animateCameraUpdate = nextCameraUpdate;
nextCameraUpdate = null;
mMap.animateCamera(animateCameraUpdate, working_interval, this);
Log.d("test", Boolean.toString(isAnimating) +" startanimateCamera");
}
}
In case someone is having this issue, the key is to keep the animateCamera call's animation duration less than the frequency with which you are calling the animateCamera method.
For example if you call animateCamera every 1000ms set tha animate camera duration to be less than that.
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_LEVEL), 900, null)
If your animateCamera call is not being called at a constant time, then danny117's answer to use the callback to trigger the next camera update will work perfectly.
Inspired from danny117's solution, I found a simpler solution.
I set the location request update for each 5 millisecond and I set the animate camera duration to be 2.5 ms. Problem solved
I want to animate map markers when they are added to map.
User should see the map with markers around him. Each new marker should bounce.
You can implement the onMarkerClick() and make the marker bounce whenever user clicks on it.
Just try out below code implementation. I have tried it and it works totally fine.
private Marker mPerth;
private Marker mPerth = mMap.addMarker(new MarkerOptions()
.position(PERTH)
.title("Perth")
.snippet("Population: 1,738,800"));
#Override
public boolean onMarkerClick(final Marker marker)
{
// This causes the marker at Perth to bounce into position when it is clicked.
if (marker.equals(mPerth)) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = mMap.getProjection();
Point startPoint = proj.toScreenLocation(PERTH);
startPoint.offset(0, -100);
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 1500;
final Interpolator interpolator = new BounceInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
double lng = t * PERTH.longitude + (1 - t) * startLatLng.longitude;
double lat = t * PERTH.latitude + (1 - t) * startLatLng.latitude;
marker.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
}
// We return false to indicate that we have not consumed the event and that we wish
// for the default behavior to occur (which is for the camera to move such that the
// marker is centered and for the marker's info window to open, if it has one).
return false;
}
You can also use this at the time of adding the marker in your application besides onClick event.
I hope this what you want only.
Anchor the marker off screen or at your start position then start the animation.
Note the .setAnchor used in this method was added to the google map api v2 in May 2013
I've just now got this working for one marker by tweaking the extras samples maps demo and I don't like the performance of this implementation. The most important piece is to anchor the marker off screen or off at your start position. I'm using off screen above.
Anchor the marker off screen .setAnchor(.5f,(size of screen above marker / size of marker )) //for the map demo perth is about 6f for my test phone. Change the animation to bounce to the same value it was 6f for my test phone.
private void addMarkersToMap() {
// A few more markers for good measure.
mPerth = mMap.addMarker(new MarkerOptions().position(PERTH)
.title("Perth").snippet("Population: 1,738,800")
.anchor(.5f, 6f)
);
Change the animation so it bounces to (size of screen above marker/size of marker) (6f on my test phone). I'm just using the onclick handler because it's already setup to bounce with tweaks bounce to 6f and a longer duration. So after all the markers have been added to the map I fire off the click handler.
this.onMarkerClick(mPerth);
The changed onMarkerClick handler with the 6f and longer duration.
#Override
public boolean onMarkerClick(final Marker marker) {
if (marker.equals(mPerth)) {
// This causes the marker at Perth to bounce into position when it
// is clicked.
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final long duration = 2500;
final Interpolator interpolator = new BounceInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = Math.max(
1 - interpolator.getInterpolation((float) elapsed
/ duration), 0);
marker.setAnchor(0.5f, 1.0f + 6 * t);
if (t > 0.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
} else if (marker.equals(mAdelaide)) {
// This causes the marker at Adelaide to change color.
marker.setIcon(BitmapDescriptorFactory.defaultMarker(new Random()
.nextFloat() * 360));
}
// We return false to indicate that we have not consumed the event and
// that we wish
// for the default behavior to occur (which is for the camera to move
// such that the
// marker is centered and for the marker's info window to open, if it
// has one).
return false;
}
Good Luck
You can add any new layout to MapView as map marker:
public void AddAnimMarkerToMap(MapView map, GeoPoint geoPoint, int id, int animResId)
{
var layoutParams = new MapView.LayoutParams(ViewGroup.LayoutParams.WrapContent,
ViewGroup.LayoutParams.WrapContent,
geoPoint,
MapView.LayoutParams.Center);
var ll = new LinearLayout(map.Context) { Id = id, Orientation = Orientation.Vertical };
ll.SetGravity(GravityFlags.Center);
var iv = new ImageView(map.Context);
iv.SetImageResource(animResId);
ll.AddView(iv);
map.AddView(ll, layoutParams);
var markerAnimation = (AnimationDrawable)iv.Drawable;
markerAnimation.Start();
ll.LayoutParameters = layoutParams;
}
probably you can add ImageView directly without wraping layout.
animResId is the Frame animation drawable resource (similar as Android Mylocation marker).
http://developer.android.com/guide/topics/resources/animation-resource.html#Frame