3

Simple task: by pressing button, it scales X value to 0, and when animation finished starts another animation on the second view which scales X from 0 to 1. After 1 second reverse animation should be played and that's all. Running code below I've got infinite animation loop of the first part of animation.

Used nineoldandroids lib, but I don't think this is something really different from native animations framework at least on jelly bean devices.

public class MainActivity extends Activity
{

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final View mybutton = findViewById(R.id.mybutton);
    final View myprogress = findViewById(R.id.myprogress);

    mybutton.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            animate(mybutton).scaleX(0).setListener(new AnimatorListenerAdapter()
            {
                @Override
                public void onAnimationEnd(Animator animation)
                {
                    mybutton.setVisibility(View.INVISIBLE);
                    myprogress.setVisibility(View.VISIBLE);
                    ViewHelper.setScaleX(myprogress, 0f);

                    animate(myprogress).scaleX(1).setListener(new AnimatorListenerAdapter()
                    {
                        @SuppressWarnings("ConstantConditions")
                        @Override
                        public void onAnimationEnd(Animator animation)
                        {
                            mybutton.getHandler().postDelayed(new Runnable()
                            {
                                @Override
                                public void run()
                                {
                                    animate(myprogress).scaleX(0).setListener(new AnimatorListenerAdapter()
                                    {
                                        @Override
                                        public void onAnimationEnd(Animator animation)
                                        {
                                            myprogress.setVisibility(View.INVISIBLE);
                                            mybutton.setVisibility(View.VISIBLE);

                                            ViewHelper.setScaleX(mybutton, 0);
                                            animate(mybutton).scaleX(1);
                                        }
                                    });
                                }
                            }, 1000);
                        }
                    });
                }
            });
        }
    });
}

}

Layout is simple:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
>

    <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/mycontainer">


            <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="string text"
                    android:id="@+id/mybutton"
                    />

            <ProgressBar
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignLeft="@id/mybutton"
                    android:layout_alignTop="@id/mybutton"
                    android:layout_alignRight="@id/mybutton"
                    android:layout_alignBottom="@id/mybutton"
                    android:visibility="invisible"
                    android:id="@+id/myprogress"
                    />


            </RelativeLayout>
</RelativeLayout>

Where I was wrong?

curioushikhov
  • 2,461
  • 2
  • 30
  • 44
  • Do you clear animation from your button? I think that `mybutton.setVisibility(View.VISIBLE)` starts animation. On animation and you can set `mybutton.clearAnimation()` before change visibility. – nfirex Apr 08 '14 at 07:43
  • Oh my god. Please look into `AnimatorSet` and `playSequentially()`. Anything indented that far should be a red flag. – Kevin Coppock Apr 08 '14 at 07:53
  • playsequentially will not work because second view is invisible while first view is animated. – curioushikhov Apr 08 '14 at 07:57
  • Add a listener on one of the animations to set it to visible. – Kevin Coppock Apr 08 '14 at 08:03
  • And then animatorset approach will be almost the same as code above. So it is just a matter of taste. Note, this code just demonstrates issue and not something usual. I needed explanation why animations get cycled and not how i can do in another way. First comment seems to be helpful(clearAnimation) and I will try it a little bit later. – curioushikhov Apr 08 '14 at 08:09
  • clearAnimation did not help :( – curioushikhov Apr 08 '14 at 10:06

1 Answers1

22

Madness! After investigation found source of it: When animate() method called, it creates ViewPropertyAnimator and saves it to the map. When you try to animate this view again with animate() it takes already created viewpropertyanimator from the map and immediately calls onAnimationStart() even before you set new animation parameters, and because animationlistener was set on the first animation, it was triggered! and launched first animation(second part of it). This is creates infinite loop.

To stop it you MUST clear old listener when you try to animate view second time, so

animate(mybutton).setListener(null).scaleX(1);

stops infinite loop. Documentation should warn about it, definitely!

curioushikhov
  • 2,461
  • 2
  • 30
  • 44
  • 1
    Amazing, I tried animation.removeAllListeners(), but it didn't work as expected. This answer proves absolutely correct. – Drew Apr 24 '15 at 18:56