1

I have a property animation, but it's not smooth, i.e I'm getting jumps in the animation. I tried to play with the parameters for the animator, such as the interpolator, the duration, and the frame delay, but can't get a smooth effect. Does anyone have some tricks / examples? Here's my current code for setting the animator:

rotationAnimator=new ObjectAnimator();
rotationAnimator.setTarget(rotationController);
rotationAnimator.setPropertyName("mapRotation");
rotationAnimator.setInterpolator(new LinearInterpolator());
ValueAnimator.setFrameDelay(24);
rotationAnimator.setDuration(ROTATION_DURATION);
rotationAnimator.setRepeatCount(ValueAnimator.INFINITE);
rotationAnimator.setRepeatMode(ValueAnimator.RESTART);

(There's also a call to setFloatValues, but it comes later in the code, before I start the animation)

EDIT: I was asked to show what I'm animating, so here it is:

That's the setter function that gets the value from the animation:

public void setMapRotation(float rotationDegrees)
{
    if ((rotationAnimator!=null)&&(rotationAnimator.isRunning()))
        rotationAnimator.cancel();
    rotationDegrees%=360;
    if (rotationDegrees<0) rotationDegrees+=360;
    rotationView.setRotationDegrees(rotationDegrees);
    if (rotationDegrees!=oldRotationDegrees)
    {
        notifyRotationListeners();
        oldRotationDegrees=rotationDegrees;
    }
}

If you look at the code, you'll see there's another function that gets called (setRotationDegrees), so here it is:

public void setRotationDegrees(float rotationDegrees)
{ 
    this.rotationDegrees=rotationDegrees%360;
    if (this.rotationDegrees<0) this.rotationDegrees+=360;
    Log.i("MapView","View degrees: " + this.rotationDegrees);
    invalidate();
}

And that's what happens after the invalidation:

@Override protected void dispatchDraw(Canvas canvas)
{
    Log.i("MapView","Redrawing");
    int saveCount=canvas.save(Canvas.MATRIX_SAVE_FLAG);
    canvas.rotate(rotationDegrees,getWidth()/2,getHeight()/2);
    canvas.setDrawFilter(drawFilter);
    canvas.getMatrix(rotationMatrix);
    super.dispatchDraw(canvas);
    canvas.restoreToCount(saveCount);
}

I don't know if there's something particularly heavy here, but I may be wrong...

user940016
  • 2,878
  • 7
  • 35
  • 56

3 Answers3

1

Defining an AnimatorSet and set the Interpolator on it may solve your issue:

rotationAnimator=new ObjectAnimator();
rotationAnimator.setTarget(rotationController);
rotationAnimator.setPropertyName("mapRotation");
ValueAnimator.setFrameDelay(24);
rotationAnimator.setDuration(ROTATION_DURATION);
rotationAnimator.setRepeatCount(ValueAnimator.INFINITE);
rotationAnimator.setRepeatMode(ValueAnimator.RESTART);

AnimatorSet animatorSet = new AnimatorSet();
animatorSet.getChildAnimations().add(rotationAnimator);
animatorSet.setInterpolator(new LinearInterpolator());
...
animatorSet.start();
ben75
  • 29,217
  • 10
  • 88
  • 134
  • 1
    Can you please explain me how an AnimatorSet makes the animation smoother? From what I know, it's just used for grouping and synchronizing several animations together, but I have only one animation... – user940016 Jan 12 '13 at 15:29
  • Indeed, you only have one animation, but I expect you will have improved performance with an AnimatorSet because you are repeating the animation forever. (did you try ? and do you have same results ?) – ben75 Jan 12 '13 at 15:45
1

I've resolved by adding HW acceleration directly to my animated view and view container (myViewContainer - in my case a RelativeLayout):

if(!myViewContainer.isHardwareAccelerated())
{
    myViewContainer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    myAnimatedView1.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    myAnimatedView2.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
Tunaki
  • 132,869
  • 46
  • 340
  • 423
christian mini
  • 1,662
  • 20
  • 39
0

Jumps in the middle of the animation are more likely to be caused by either something in your rotationController class, that is receiving the animated value "mapRotation". Or it could be something to do with your layout.

I would imagine that there is something quite intense, memory or cpu wise, that is causing the juttering.

If your animating something that has lots of layouts then that could be the cause. If in your code you have lots of findViewByID that is getting called as a result of your animation then that to can cause a slow down.

If your just animating a simple image, then im not entirely sure what the issue would be.

Personally i think your code looks fine, perhaps show/describe what your animating.

[edit] I have limited knowledge of animating with the canvas so i took a quick look at how you were using canvas.save() and canvas.restoreToCount() which i hadn't seen before.

It all looks good though i do find it odd that several tutorials rotate the canvas rather than the ball image to create the rotation. Still, the only reference i found to improving the animating was a comment in the following link that suggested using postInvalidateOnAnimation(). Not sure where though, perhaps instead of invalidate().

Community
  • 1
  • 1
Emile
  • 11,451
  • 5
  • 50
  • 63
  • Personally i don't like the rotation method, my gut says that its excessive. Not sure if it would work for you but i might look at using sprites in some way, here for example http://p-xr.com/android-tutorial-2d-canvas-graphics/ The difference is that you adjust the sprite and not the canvas to draw in the graphic. – Emile Jan 12 '13 at 16:01