I'm trying to animate the size of a marker as it is added to a map, basically I want the marker to grow. I can't see any way of getting to the actual view for the marker so I don't think I can use the standard Android animation techniques (e.g. ObjectAnimator).
The only way I can see to do this would be to implement my own animation and use the setIcon method to change the marker icon.
Is there any other and ideally better way of doing this?
I'm working in Xamarin but can port Java code if necessary.
You may try something like this
final Marker marker = map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_temperature_kelvin_black_48dp);
final Bitmap target = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(target);
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(500);
animator.setStartDelay(1000);
final Rect originalRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF scaledRect = new RectF();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float scale = (float) animation.getAnimatedValue();
scaledRect.set(0, 0, originalRect.right * scale, originalRect.bottom * scale);
canvas.drawBitmap(bitmap, originalRect, scaledRect, null);
marker.setIcon(BitmapDescriptorFactory.fromBitmap(target));
}
});
animator.start();
Yes you are right there is not direct method to do it. Instead, you can use handler that will get called after say every 500ms and in that you can setIcon of marker.
Use this link for reference; How to animate marker in android map api V2?
For vector drawables
fun Drawable.getBitmapFromVectorDrawable(): Bitmap {
val bitmap = Bitmap.createBitmap(
intrinsicWidth,
intrinsicHeight, Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
setBounds(0, 0, canvas.width, canvas.height)
draw(canvas)
return bitmap
}
Then do
val marker = map.addMarker(MarkerOptions().position(LatLng(latitude, longitude)))
val bitmap = requireContext().requireDrawable(R.drawable.marker)!!
.getBitmapFromVectorDrawable()
ValueAnimator.ofInt(1, bitmap.width).apply {
duration = resources.getInteger(R.integer.itr_normal_anim_time).toLong()
interpolator = OvershootInterpolator()
addUpdateListener { animation ->
val scale = animation.animatedValue as Int
val scaledBitmap = bitmap.scale(scale, scale)
marker!!.setIcon(BitmapDescriptorFactory.fromBitmap(scaledBitmap))
}
start()
}
Related
I want to use animatedVectorDrawable as the map marker in Android. Is there a way to do this.
What i tried is, I use BitmapDescriptorFactory class to convert VectorDrawable to bitmap and it work fine , but when i go to convert AnimatedVectorDrawable it show nothing on map
Below code what i tried so far
.
.
.
MarkerOptions marker1 = new MarkerOptions();
marker1.icon( getBitmapDescriptor(R.drawable.setpickuplocationdrawable));
marker1.position(pickuplatlng);
marker1.title("Marker at place1");
googleMap.addMarker(marker1);
}
private BitmapDescriptor getBitmapDescriptor(int id) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AnimatedVectorDrawable vectorDrawable = (AnimatedVectorDrawable) getDrawable(id);
int h = vectorDrawable.getIntrinsicHeight();
int w = vectorDrawable.getIntrinsicWidth();
vectorDrawable.setBounds(0, 0, w, h);
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bm);
} else {
return BitmapDescriptorFactory.fromResource(id);
}
}
You cannot do that. In order to add an image to map as marker, you will need a bitmap (png preferable).
What you can do is convert the vector to a bitmap and try again.
As one can see in the image above, the custom map markers from the Iconify library that I create on a SupportMapFragment are transparent. How can I make these markers opaque?
Here is how I draw the markers on the map:
IconDrawable icon = new IconDrawable(getActivity(), Iconify.IconValue.fa_map_marker)
.colorRes(R.color.birthEvent)
.sizeDp(40);
icon.setAlpha(255);
Canvas canvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
icon.draw(canvas);
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap);
MarkerOptions marker = new MarkerOptions()
.icon(bitmapDescriptor);
googleMap.addMarker(marker);
Here is how the color birthEvent is defined in res/values/colors.xml:
<resources>
<color name="birthEvent">#FD3C3C</color>
</resources>
The
markerOptions.alpha()
method should be specified as a float between 0.0 and 1.0, where 0 is
fully transparent and 1 is fully opaque. So try to change it as a
float between 0 to 1.
Or you can check this blog on how to set the Android iconify in MapFragment.
Here is the example code.
public BitmapDescriptor getCustomMarker(IconValue iconValue) {
IconDrawable id = new IconDrawable(getBaseContext(), iconValue) {
#Override
public void draw(Canvas canvas) {
// The TextPaint is defined in the constructor
// but we override it here
TextPaint paint = new TextPaint();
paint.setTypeface(Iconify.getTypeface(getBaseContext()));
paint.setStyle(Paint.Style.STROKE_AND_FILL);
paint.setTextAlign(Paint.Align.CENTER);
paint.setUnderlineText(false);
// If you need a custom color specify it here
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setTextSize(getBounds().height());
Rect textBounds = new Rect();
String textValue = String.valueOf(iconValue.character());
paint.getTextBounds(textValue, 0, 1, textBounds);
float textBottom = (getBounds().height() - textBounds.height()) / 2f + textBounds.height() - textBounds.bottom;
canvas.drawText(textValue, getBounds().width() / 2f, textBottom, paint);
}
}.actionBarSize();
Drawable d = id.getCurrent();
Bitmap bm = Bitmap.createBitmap(id.getIntrinsicWidth(), id.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
d.draw(c);
return BitmapDescriptorFactory.fromBitmap(bm);
}
In may app i use Map from Google Maps V2 and in this map i am trying to add markers each Marker with an icon, but the marker is taking the size of the icon which is making the icon looks flue.
How can i specify the size of the marker in dp so that i can control how it looks like on the map
Currently it's not possible to specify a marker size using MarkerOptions, so your only option is to rescale your Bitmap before setting it as your marker icon.
Creating the scaled Bitmap:
int height = 100;
int width = 100;
BitmapDrawable bitmapdraw = (BitmapDrawable)getResources().getDrawable(R.mipmap.marker);
Bitmap b = bitmapdraw.getBitmap();
Bitmap smallMarker = Bitmap.createScaledBitmap(b, width, height, false);
Using smallMarker as the marker icon:
map.addMarker(new MarkerOptions()
.position(POSITION)
.title("Your title")
.icon(BitmapDescriptorFactory.fromBitmap(smallMarker))
);
The accepted answer is outdated (Resources::getDrawable has been deprecated since API level 22). Here's an updated version:
int height = 100;
int width = 100;
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable. marker);
Bitmap smallMarker = Bitmap.createScaledBitmap(b, width, height, false);
BitmapDescriptor smallMarkerIcon = BitmapDescriptorFactory.fromBitmap(smallMarker);
and then apply it in MarkerOption
.icon(smallMarkerIcon)
Kotlin version
I used 0- 9 answer and used it with kotlin
fun generateHomeMarker(context: Context): MarkerOptions {
return MarkerOptions()
.icon(BitmapDescriptorFactory.fromBitmap(generateSmallIcon(context)))
}
fun generateSmallIcon(context: Context): Bitmap {
val height = 100
val width = 100
val bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.logo)
return Bitmap.createScaledBitmap(bitmap, width, height, false)
}
I think you can look for an answer on this question, where it already explained how to create a custom marker, with a given width and height by creating a dynamic bitmap.
Drawable circleDrawable = getResources().getDrawable(R.mipmap.primarysplitter);
bitmapDescriptor = getMarkerIconFromDrawable(circleDrawable);
private BitmapDescriptor getMarkerIconFromDrawable(Drawable drawable) {
Canvas canvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
drawable.setBounds(0, 0, (int)getResources().getDimension(R.dimen._30sdp), (int)getResources().getDimension(R.dimen._30sdp));
drawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
for an Android App I need a custom marker for my google maps activity. The standard option do not help me. what is the best way to achieve the right icon with a businesslogo that can be set for each marker?
UPDATE:
Sorry, either I wasn't clear enough or I don't see it. I can't find a lot helpful things in the docs or the hints you gave me. Now I constructed a default marker:
and I have lots of profile pics or logos wich need to be placed within the marker at runtime depending on certain conditions e.g.:
There is a documentation about adding custom markers on a position.
private static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
private Marker melbourne = mMap.addMarker(new MarkerOptions()
.position(MELBOURNE)
.title("Melbourne")
.snippet("Population: 4,137,400")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));
for making custom view you have to use MarkerDemoActivity class to use a custom marker.if you are using google map Api V2.0.
and other solution to make custom view for marker.
Add this code to add marker of map:
Marker myLocMarker = map.addMarker(new MarkerOptions()
.position(myLocation)
.icon(BitmapDescriptorFactory.fromBitmap(writeTextOnDrawable(R.drawable.bluebox, "your text goes here"))));
the writeTextOnDrawable() Method:
private Bitmap writeTextOnDrawable(int drawableId, String text) {
Bitmap bm = BitmapFactory.decodeResource(getResources(), drawableId)
.copy(Bitmap.Config.ARGB_8888, true);
Typeface tf = Typeface.create("Helvetica", Typeface.BOLD);
Paint paint = new Paint();
paint.setStyle(Style.FILL);
paint.setColor(Color.WHITE);
paint.setTypeface(tf);
paint.setTextAlign(Align.CENTER);
paint.setTextSize(convertToPixels(context, 11));
Rect textRect = new Rect();
paint.getTextBounds(text, 0, text.length(), textRect);
Canvas canvas = new Canvas(bm);
//If the text is bigger than the canvas , reduce the font size
if(textRect.width() >= (canvas.getWidth() - 4)) //the padding on either sides is considered as 4, so as to appropriately fit in the text
paint.setTextSize(convertToPixels(context, 7)); //Scaling needs to be used for different dpi's
//Calculate the positions
int xPos = (canvas.getWidth() / 2) - 2; //-2 is for regulating the x position offset
//"- ((paint.descent() + paint.ascent()) / 2)" is the distance from the baseline to the center.
int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2)) ;
canvas.drawText(text, xPos, yPos, paint);
return bm;
}
public static int convertToPixels(Context context, int nDP)
{
final float conversionScale = context.getResources().getDisplayMetrics().density;
return (int) ((nDP * conversionScale) + 0.5f) ;
}
and for more information see this link.
So this is how i did it firt i constructed two pics. the marker as shown above and the other one by the following function (all code is found soewhere on stackoverflow):
public static Bitmap getCircleBitmap(Bitmap bm) {
int sice = Math.min((bm.getWidth()), (bm.getHeight()));
Bitmap bitmap = ThumbnailUtils.extractThumbnail(bm, sice, sice);
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffff0000;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setFilterBitmap(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawOval(rectF, paint);
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth((float) 4);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
Then I pass them to the following function
public static Bitmap overlay(Bitmap bmp1, Bitmap bmp2) {
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, new Matrix(), null);
canvas.drawBitmap(bmp2, 5, 5, null);
return bmOverlay;
}
I know its probably not the best way of doing it, especially i dont like the hard coding of the position of the circle in the marker. but t works so far
I'm converting an old application from v1 to v2, and I'm having a problem with the color of my Marker icons. I have a basic, white icon, and It needs to be colorized.
In v1, I did it this way :
Drawable d = DrawableUtils.resizeImageToDrawable(
MapViewFragment.mapviewActivity,
Configuration.Display.getDrawableFix(i),
Configuration.MapView.getWaypointIconWidth(),
Configuration.MapView.getWaypointIconHeight());
d.setColorFilter(color, Mode.MULTIPLY);
overlay = new MyFplnFixListItimizedOverlay(d);
Since v2 Markers do not accept Drawables for their icons, I thought about converting the Drawable to a Bitmap, like this :
Drawable d = DrawableUtils.resizeImageToDrawable(
MapViewFragment.mapviewActivity,
Configuration.Display.getDrawableFix(i),
Configuration.MapView.getWaypointIconWidth(),
Configuration.MapView.getWaypointIconHeight());
d.setColorFilter(color, Mode.MULTIPLY);
Bitmap icon = ((BitmapDrawable) d).getBitmap();
Marker marker = MapViewFragment.map.addMarker(new MarkerOptions()
.position(point)
.title(Integer.toString(fplnType))
.visible(true)
.icon(BitmapDescriptorFactory.fromBitmap(icon)));
But for some reason, it's not working. The icons stay white. Anyone knows why ?
Thanks in advance.
OK, here's how I did it at the end of the day :
Drawable d = DrawableUtils.resizeImageToDrawable(
MapViewFragment.mapViewActivity,
Configuration.Display.getDrawableFix(i),
Configuration.MapView.getWaypointIconWidth(),
Configuration.MapView.getWaypointIconHeight());
d.setColorFilter(color, Mode.MULTIPLY);
Bitmap b = ((BitmapDrawable) d).getBitmap();
Canvas myCanvas = new Canvas(b);
int myColor = b.getPixel(0,0);
ColorFilter filter = new LightingColorFilter(myColor, color);
Paint pnt = new Paint();
pnt.setColorFilter(filter);
myCanvas.drawBitmap(b,0,0,pnt);
Marker marker = MapViewFragment.map.addMarker(new MarkerOptions()
.position(point)
.title(Integer.toString(fplnType))
.visible(true)
.icon(BitmapDescriptorFactory.fromBitmap(b)));
If your drawable is not defined in a XML, you can do it with this method:
protected Bitmap fromDrawable(final Drawable drawable, final int height, final int width) {
final int widthDip = (int) TypedValue.applyDimension(1, width, getResources()
.getDisplayMetrics());
final int heightDip = (int) TypedValue.applyDimension(1, width, getResources().getDisplayMetrics());
final Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
Note that if you need to do it from OUTSIDE an Activity, you'll also need to pass a Context (in order to call context.getResources().getDisplayMetrics()). You also pass the DisplayMetrics object instead.
I'm not sure what this DrawableUtils is doing, but you're casting it to a BitmapDrawable. Is it really a BitmapDrawable?
here's some code to extract a Bitmap out of any type of drawable:
Drawable d = // make sure it's not null
d.setBounds(0, 0, width, height);
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
d.draw(c);
the idea is that you create a canvas on a mutable bitmap and draw that drawable on the canvas
edit:
I've just seen the #Analizer answer and yeah, my answer is good if you don't have the Drawable as a resource. But if you do, user his answer instead.