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.
Related
BitmapDescriptor bmpD = BitmapDescriptorFactory.fromResource(R.raw.podval);
Log.d("myLog", ":" + bmpD);
GroundOverlayOptions newarkMap = new GroundOverlayOptions()
.image(bmpD)
.position(sydney, 8600f, 6500f);
Log.d("myLog", ":" + newarkMap);
GroundOverlay imageOverlay = mMap.addGroundOverlay(newarkMap);
Failed to decode image. The provided image must be a Bitmap.
But in log I got :com.google.android.gms.maps.model.BitmapDescriptor#58e0ee6
:com.google.android.gms.maps.model.GroundOverlayOptions#1ea9c27
Also I converted jpg image to bmp, after failing to convert it here
Help please.
See https://stackoverflow.com/a/45564994/2914140 for vector drawables (SVG).
private BitmapDescriptor bitmapDescriptorFromVector(Context context, #DrawableRes int vectorResId) {
Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorResId);
vectorDrawable.setBounds(0, 0, vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight());
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
Place your image in the drawable folder, not in the raw folder. Also make sure the resource is a valid image file.
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);
}
I'm trying to add support to tablets in my app and run into IllegalArgumentException thrown by this line of code:
marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.arrow_green_10by19))
The method .fromResource works fine with the R.drawable.arrow_green_10by19 from an image file (png) but when the png is replaced with the vector file arrow_green_10by19.xml (which renders fine in the Android Studio IDE) it generates a runtime as mentioned.
Does anybody knows how to implement a vector resource in the BitmapDescriptorFactory and could help me out?
Thanks.
I had the same problem but I realized that on my device with API 16 it works fine but with API 21 it crashes. Finally it works in both devices using this solution. Here the code:
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static Bitmap getBitmap(VectorDrawable vectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
return bitmap;
}
and this:
private static Bitmap getBitmap(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (drawable instanceof BitmapDrawable) {
return BitmapFactory.decodeResource(context.getResources(), drawableId);
} else if (drawable instanceof VectorDrawable) {
return getBitmap((VectorDrawable) drawable);
} else {
throw new IllegalArgumentException("unsupported drawable type");
}
}
So I combined those 2 functions in this way:
private Marker addMark(LatLng latLng, String title) {
Bitmap bitmap = getBitmap(getContext(), R.drawable.ic_place_24dp);
Marker marker = googleMap.addMarker(new MarkerOptions().position(latLng)
.title(title)
.icon(BitmapDescriptorFactory.fromBitmap(bitmap))
.draggable(true));
return marker;
}
Where R.drawable.ic_place_24dp is a vector asset (.xml), not a .png
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()
}
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.