Animate markers on Google MapView - android

I am working on an Android app that displays multiple markers on a Google MapView. Everything works perfectly but I would like the markers to have an animation when they appear on the map.
Here's an example of something similar on iPhone. See 1'20".
Here is how I add them to my MapView.
for(int i=0; i<myMarkerList.length(); i++){
GeoPoint x = new GeoPoint(
(int)(lat*1E6),
(int)(lng*1E6));
oItem = new OverlayItem(x, title, String.valueOf(nb_marker));
pin.setAlpha(255);
oItem.setMarker(pin);
if (oItem != null)
mapOverlay.addOverlay(oItem); // add the overlay item to the overlay
}
mapOverlays.add(mapOverlay); // add the overlay to the list of overlays
mapView.invalidate(); // update the map shown
It is so pretty on iPhone, and someone must have already done something similar on Android but I can't seem to find any useful info.
EDIT: Okay so I recon I either have to override the draw method which will be long and not that pretty, or just give up with OverlayItems.
Thank you for your time.
Best regards,
Tom

You can use this tutorial for a reference, it uses animations, so I think that suits your solution.
Code from the tutorial :
//Reference to our MapView
MapView mapView = (MapView) activity.findViewById(R.id.mapview);
//Get a LayoutInflater and load up the view we want to display.
//The false in inflater.inflate prevents the bubble View being added to the MapView straight away
LayoutInflater inflater = activity.getLayoutInflater();
LinearLayout bubble = (LinearLayout) inflater.inflate(R.layout.bubble, mapView, false);
//Set up the bubble's close button
ImageButton bubbleClose = (ImageButton) bubble.findViewById(R.id.bubbleclose);
bubbleClose.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Animation fadeOut = AnimationUtils.loadAnimation(ResultsMapResultsDisplayer.this.activity, R.anim.fadeout);
bubble.startAnimation(fadeOut);
bubble.setVisibility(View.GONE);
}
});
private void displaySearchResultBubble(final SearchResult result) {
//Hide the bubble if it's already showing for another result
map.removeView(bubble);
bubble.setVisibility(View.GONE);
//Set some view content
TextView venueName = (TextView) bubble.findViewById(R.id.venuename);
venueName.setText(result.getName());
//This is the important bit - set up a LayoutParams object for positioning of the bubble.
//This will keep the bubble floating over the GeoPoint result.getPoint() as you move the MapView around,
//but you can also keep the view in the same place on the map using a different LayoutParams constructor
MapView.LayoutParams params = new MapView.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
result.getPoint(), MapView.LayoutParams.BOTTOM_CENTER);
bubble.setLayoutParams(params);
map.addView(bubble);
//Measure the bubble so it can be placed on the map
map.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
//Runnable to fade the bubble in when we've finished animatingTo our OverlayItem (below)
Runnable r = new Runnable() {
public void run() {
Animation fadeIn = AnimationUtils.loadAnimation(activity, R.anim.fadein);
bubble.setVisibility(View.VISIBLE);
bubble.startAnimation(fadeIn);
}
};
//This projection and offset finds us a new GeoPoint slightly below the actual OverlayItem,
//which means the bubble will end up being centered nicely when we tap on an Item.
Projection projection = map.getProjection();
Point p = new Point();
projection.toPixels(result.getPoint(), p);
p.offset(0, -(bubble.getMeasuredHeight() / 2));
GeoPoint target = projection.fromPixels(p.x, p.y);
//Move the MapView to our point, and then call the Runnable that fades in the bubble.
mapController.animateTo(target, r);
}

I seen your example app. From that i think you need only Glow in your markers, right? If yes then its possible through the styles and its having glow property also.

So I got it to work using a simple ArrayList of ImageViews and animation on them, no MapOverlay.

Related

Maps is rendering a bit too slow when zoom in/out

I need some help to improve the performance of my algorithm, I'm struggling for days and can't find a good solution.
Goal: My app need to show a marker for each airport in the world (~1k markers), and each marker must show the airport name.
What I did: For the marker, I created an RelativeLayout with the Icon and a TextView to populate the name of aiport.
Also, I wrote a class "AirportCluster" extending DefaultClusterRenderer and inside the overrode method onBeforeClusterItemRendered I just cast the layout to Bitmap so it can be rendered on the map
#Override
protected void onBeforeClusterItemRendered(AirportItem airportItem, MarkerOptions markerOptions) {
RelativeLayout customLayoutMarker = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.custom_airport_marker,null);
String tAirportName = airportItem.getAirport().getAirportName().toLowerCase();
tAirportName = Character.toUpperCase(tAirportName.charAt(0)) + tAirportName.substring(1);
TextView textLabelAirportMarker = (TextView) customLayoutMarker.findViewById(R.id.label_text_airport_marker);
textLabelAirportMarker.setText(tAirportName);
customLayoutMarker.setDrawingCacheEnabled(true);
customLayoutMarker.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
customLayoutMarker.layout(0,0, customLayoutMarker.getMeasuredWidth(), customLayoutMarker.getMeasuredHeight());
customLayoutMarker.buildDrawingCache(true);
Bitmap flagBitmap;
if ( mMemoryCache.get(tAirportName) == null){
flagBitmap = Bitmap.createBitmap(customLayoutMarker.getDrawingCache());
mMemoryCache.put(tAirportName,flagBitmap);
}else{
flagBitmap = mMemoryCache.get(tAirportName);
}
BitmapDescriptor markerAirportWithText = BitmapDescriptorFactory.fromBitmap(flagBitmap);
markerOptions.icon(markerAirportWithText);
//markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.airport_marker));
}
As we can see in the code, I'm trying to cache it on the memory as well, but this is not working that good.
All the markers are being added on the method onMapReady inside a loop for each airport in the list
for (Airport temp : fixedAirports) {
LatLng latLng = new LatLng(temp.getCityLat(), temp.getCityLng());
// create marker
MarkerOptions markerOptions = new MarkerOptions().position(latLng).title("Marker in" + temp.getCityName());
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.airport_marker));
AirportItem offsetItem = new AirportItem(temp.getCityLat(), temp.getCityLng());
offsetItem.setAirport(temp);
mClusterManager.addItem(offsetItem);
}
Issue: I also have a custom image for clustered airports, and when i try to zoom in/out sometimes it take to much to the clustered icon dismiss and show the marker item for an airport, sometimes the icon of the item even overlaps the clustered one, just like on the images below.
What I have to do to these animations (changing from clustered icon from single markers) be more fast and smooth??
Prepare BitmapDescriptors first in background (i.e. Coroutines viewModelScope or another thread or asynctask or Rxjava), then load them to ui. Dont draw anything inside your ClusterRenderer class. Doing so helped me a bit.

why MapView.LayoutParams MODE_VIEW does not work if you add x and y coordinates?

when i added x and y coordinates to MapView.LayoutParams constructor. its MODE_VIEW behaviour disappears. I want this behaviour along with x and y coordinates. I am not getting the problem why this is happening.
public void addMarkerToMAp(GeoPoint geoPoint) {
mapView.removeAllViews();
final ImageView view = new ImageView(mapView.getContext());
view.setImageResource(R.drawable.map_marker_anim);
view.post(new Runnable() {
#Override
public void run() {
AnimationDrawable animationDrawable = (AnimationDrawable) view.getDrawable();
animationDrawable.start();
}
});
mapView.addView(view);
MapView.LayoutParams layoutParams = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT,
MapView.LayoutParams.WRAP_CONTENT,
geoPoint,
MapView.LayoutParams.MODE_VIEW);
view.setLayoutParams(layoutParams);
}
So, I got the geoPoint as
geoPoint = mapView.getProjection().fromPixels((int)event.getX(), (int)event.getY());
where event is click event.
Also I want to show marker pin at (event.getX(), event.getY()), but it shows below the click.
If you code in eclipse, press ctrl+shift+f. That will make your code more readable.
That being said, When you show a marker, which points do you use?
If im not wrong then the point you will insert, will be the bottom left if its an overlay drawable.
topleft if its a view(i think thats what you are doing) and therefor it will appear under your click.
You can add an offsetx and offsety to it being -view.getWidth()/2 and -view.getHeight/2. which should then make your view directly centered under your pressed point.
You might have trouble getting view.getWidth/Height though, so make sure it doesnt return 0.

Google Map Marker Clickable Area

I am using this example: https://github.com/galex/android-mapviewballoons
My problem is that the clickable area is wider than the marker itself. For example, my Google Map marker is 25x25 then the clickable area would extend up to 70x70. This is a big problem for overlapping markers.
When I clicked on the tip of that arrow, onTap is activated, even though the tap area is far from the marker.
Please help me. Thanks.
This is the default behaivior of ItemizedOverlay. 25x25 px is generally not an adquate touchable area for most human fingers.
You should override the hitTest() method if you want to modify the way an overlay item hit is tested.
For debugging :
Try using a TouchDelegate for the View, you can specify the Touch rect for a give View
An example showing how to use the TouchDelegate :
public class TouchDelegateSample extends Activity {
Button mButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.touch_delegate_view);
mButton = (Button)findViewById(R.id.delegated_button);
View parent = findViewById(R.id.touch_delegate_root);
// post a runnable to the parent view's message queue so its run
after
// the view is drawn
parent.post(new Runnable() {
#Override
public void run() {
Rect delegateArea = new Rect();
Button delegate = TouchDelegateSample.this.mButton;
delegate.getHitRect(delegateArea);
delegateArea.top -= 200;
TouchDelegate expandedArea = new TouchDelegate(delegateArea,
delegate);
// give the delegate to an ancestor of the view we're
delegating the
// area to
if (View.class.isInstance(delegate.getParent())) {
((View)delegate.getParent()).setTouchDelegate(expandedArea);
}
}
});
}
}
hitTest()
See if a given hit point is within the bounds of an item's marker. Override to modify the way an item is hit tested. The hit point is relative to the marker's bounds. The default implementation just checks to see if the hit point is within the touchable bounds of the marker.

How to animate to other position that center map

I have an activity that extends MapActivity, and inside onCreate() I have this code
GeoPoint point = new GeoPoint((int)(1.3*1E6),(int)(34.45*1E6));
final MapController mc;
mc.animateTo(point);
that animates, to that point, however, when it animates, the point is in the center of the screen, and I want it to be in a fixed (X,Y) position on the screen. Is there an mc.animatetoLeftBottom(point) function?
Edit :
I used the
Projection p = mapView.getProjection();
point = p.fromPixels(50, 60);
mc.animateTo(point);
pictures:
When I start the app, it looks like this :
After I tap once on the pin, it looks like this
And, if I tap again on the pin, it will look like this:
This is how it should look like, no matter where I tap it from, or if I scroll, zoom and then tap again:
What I want is for it to automatically move to that position(see last picture) when I tap the pin
Can't you just change the GeoPoint to account for the fact, and animate to a different point?
Try this:
MapView mv = getMapView(); // fetch your map view
Projection p = mv.getProjection();
GeoPoint point = p.fromPixels(X, Y);
mc.animateTo(point);

Draw an ImageView at specific GeoPoint on a MapView (Android)

Trying to solve my current problem of drawing an image on an Android MapView and then animate it to represent a moving object, I decided to try to just draw a raw ImageView at a GeoPoint on the map and then try and animate it from there.
This is the code I put in my map activity (extends MapActivity)'s onCreate method:
GeoPoint point = new GeoPoint(19240000, -99120000);
ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.icon);
LayoutParams lp = new LayoutParams(iv.getWidth(), iv.getHeight(), point, LayoutParams.BOTTOM);
mapView.addView(iv, lp);
Again, I'm just trying to draw the static icon and animate it from there. I can already do this with an ItemizedOverlay, but as far as I can tell, I can't animate the elements of an AnimatedOverlay the way that I can animate a view. Thus, using ImageView.
But the icon doesn't show up. Any thoughts or suggestions?
MapView.LayoutParams screenLP = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT,
MapView.LayoutParams.WRAP_CONTENT, point, width/2,
0, MapView.LayoutParams.LEFT | MapView.LayoutParams.BOTTOM)
Have you tried with the WRAP_CONTENT tags?

Categories

Resources