I wonder if it is be possible to animate Google Maps markers rotations along x- and y-axis like how we'd rotate an ImageView using ObjectAnimator around x-axis and/or y-axis. Apparently, one can rotate (change) the orientation of a marker clockwise, which is along z-axis (in X-Y plane), but I seem to be unable to find something similar for even rotating a marker (bitmap) around x- or y-axis. I have found few discussions like this which might be somehow related to what I'm looking for but I am rather confused on how to go about this. Any help is greatly appreciated!
UPDATE I I did further research and came up with a proposal on how to tackle this problem:
Google Map
Marker
has a setter method for setting its icon, referred to assetIcon
. Not only through theMarkerOption
but also as an standalone method to reset theMarker
icon. This method expects aBitmapDescriptor
to be passed in in order to update the icon. UsingBitmapDescriptorFactory
one can easily get aBitmapDescriptor
from a givenBitmap
object.Since Google Maps
Marker
doesn't support 3D rotations, we need to somehow rotate theBitmap
which goes in place of theMarker
icon outside of theMarker
itself. One way to do this, as far as my findings go, to create aCanvas
and aCamera
objects, while former is linked to theDrawable
to be 3D rotated, the latter is used to actually perform the 3D rotations.Using
Camera
helper methods likerotateX
,rotateY
, androtateZ
, in addition to any necessary translations, one can obtain a customizedMatrix
instance. By applying thisMatrix
toCanvas
using, for example,concat
orsetMatrix
method, we enforce the the rotations.The drawable can be linked to
Canvas
, that is, we may useDrawable.draw(Canvas canvas)
method to actually draw into theBitmap
while 3D transformations are applied. Assuming that theCanvas
object is linked to theBitmap
. This way the transformed version of the drawable should now be held by theBitmap
instance.Using
Marker
setter methodsetIcon
, we first recycle the olderBitmapDescriptor
and then create a new one, and pass that object tosetIcon
.
Questions: I wonder if this is the best way to accomplish what I'm looking for. Moreover, how to actually accomplish an animation. I am certain an approach like the one using Animation
and overriding it applyTransformation(float interpolatedTime, Transformation t)
won't work as it is only applicable to View
objects. I further believe I'm better off using ValueAnimator
which provides the necessary timing engine for running animations, that is calculating the animated values and set them on target object, in this case the rotation value.
UPDATE II
I have come up with the following snippet which is pretty much self-explanatory. Unfortunately, once the animation starts, the icon is removed and nothing else. I captured the logs to make sure the ValueAnimator
actually works and it turns out that it does indeed. I also removed all transformations and made sure the Matrix
is identity but that didn't help. Getting the Drawable
and attempting to draw that into Bitmap
instance via Canvas
still doesn't work. In fact, when the animation begins, the icon is simply removed. To verify if bitmap file is really created to be replaced, I tried to sample and save the bitmap into SDCARD as PNG format. It's confirmed that the saved PNGs are all blank and that's why the icon is seen to be removed. Any thought?
private void animateMarker() {
if (mCamera == null) {
mCamera = new Camera();
}
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(300);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// float interpolatedTime = ((Float) (animation.getAnimatedValue())).floatValue();
// final double radians = Math.PI * interpolatedTime;
// float degrees = (float) (180.0 * radians / Math.PI);
final Matrix matrix = new Matrix();
// mCamera.translate(0.0f, 0.0f, (float) (150.0 * Math.sin(radians)));
// mCamera.rotateX(degrees);
// mCamera.rotateY(degrees);
// mCamera.rotateZ(degrees);
// mCamera.getMatrix(matrix);
Resources resources = mContext.getResources();
Drawable drawable = resources.getDrawable(R.drawable.custom_pin);
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// mCamera.applyToCanvas(canvas);
// canvas.setMatrix(matrix);
// drawable.draw(canvas);
canvas.drawBitmap(bitmap, matrix, null);
mMarkerSetLocation.setIcon(mBitmapDescriptorFactory.fromBitmap(bitmap));
}
});
animator.start();
}