5
votes

I have been trying to code an activity method rotating an image to a specific angle. The rotation works but the problem is that the method is called every second or so, but rotates only on the first few times. At a certain point the image being animated just stands still, even though that the animation is being set up and started with different values! which suppose to move the image, as it did the first few times.

private void animateNeedle(final float sfAngle)
{
    final View viewNeedle = findViewById(R.id.needle);
    final RotateAnimation needleAnimation;

    RotateAnimation anim;

    anim = new RotateAnimation( 0,
        sfAngle,
        m_nNeedleWidth / 2,
        m_nNeedleHeight);
    anim.setDuration(200);
    anim.setFillAfter(true);
    viewNeedle.setAnimation(anim);
    anim.setAnimationListener(new AnimationListener()
    {

        @Override
        public void onAnimationEnd(final Animation animation)
        {
            viewNeedle.clearAnimation();
        }

        @Override
        public void onAnimationRepeat(final Animation animation)
        {
            // TODO Auto-generated method stub
        }

        @Override
        public void onAnimationStart(final Animation animation)
        {
            // TODO Auto-generated method stub
        }
    });

    anim.start();
    findViewById(android.R.id.content).postInvalidate();
}

What am I doing wrong? I made sure that the function won't be called twice during of the animation but it doesn't help.

2
Where are you calling the function from?LeeNeverGup
From an event, to be exact an Audio samples received but this is happening only once a second to check if it's a thread related issue.Nati Keidar
Are you sure that sfAngle passed is always non-zero?Sherif elKhatib
Do you start the animation from the UI thread ?yoah
Have you tried adding the synchronized keyword in the method signature in making sure it's not a multi-thread issue? (view needle sets new animation object, while another thread invokes the .clearAnimation())Ryhan

2 Answers

2
votes

The problem was that it was not running on the main thread, to fix it we used:

anim = new RotateAnimation( m_lastAngle,
                                sfAngle,
                                viewNeedle.getWidth() / 2,
                                viewNeedle.getHeight());
    anim.setDuration(1000);
    anim.setFillAfter(true);
    viewNeedle.setAnimation(anim);
    anim.setAnimationListener(new AnimationListener()
    {
        @Override
        public void onAnimationEnd(final Animation animation)
        {
            // viewNeedle.clearAnimation();
        }

        @Override
        public void onAnimationRepeat(final Animation animation)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationStart(final Animation animation)
        {
            m_lastAngle = sfAngle;
        }
    });

    runOnUiThread(new Runnable()
    {

        @Override
        public void run()
        {
            viewNeedle.startAnimation(anim);
            findViewById(android.R.id.content).invalidate();
        }
    });

Also we used:

    final View viewNeedle = findViewById(R.id.needle);
    viewNeedle.getViewTreeObserver().addOnGlobalLayoutListener(
            new OnGlobalLayoutListener()
            {
                @Override
                public void onGlobalLayout()
                {
                    scaleView(viewNeedle);
                }

                /**
                 * Scale a view.
                 * 
                 * @param viewToScale - View to scale.
                 */
                private void scaleView(final View viewToScale)
                {
                    int height = (int) (viewToScale.getHeight() / GraphicsPoint
                            .getScalePoint().y);
                    int width = (int) (viewToScale.getWidth() / GraphicsPoint
                            .getScalePoint().x);
                    final LayoutParams layoutParams = viewToScale
                            .getLayoutParams();
                    layoutParams.height = height;
                    layoutParams.width = width;
                    viewToScale.setLayoutParams(layoutParams);
                    viewToScale.getViewTreeObserver()
                            .removeOnGlobalLayoutListener(this);
                }
            });
2
votes

I tried to use your code and it works to call animation many times later .. I add this code to be called when rotation comes to end :

..
                viewNeedle.startAnimation(anim);
                anim.start();
..

so to make a repeated animation it will be just like this:

 @Override
            public void onAnimationEnd(final Animation animation)
            {
                viewNeedle.clearAnimation();
                viewNeedle.startAnimation(anim);
                anim.start();
            }

so I can call that animation more than one time ..

hope that will help you ..