Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Viewflipper animation doesn't work on first swipe

On my main activity, I have a viewflipper with three child views. After the app is first started, when I do the first right to left swipe, the view changes, but it does not have the slide animation. After the first swipe, the animation works as expected when swiping in either direction. I am following this tutorial. The code I use is:

 public boolean onTouchEvent(MotionEvent touchevent)
{
    switch (touchevent.getAction())
    {
        // when user first touches the screen
        case MotionEvent.ACTION_DOWN:
        {
            lastX = touchevent.getX();
            break;
        }
        case MotionEvent.ACTION_UP:
        {
            float currentX = touchevent.getX();

            // left to right swipe
            if (lastX < currentX)
            {
                if (mViewFlipper.getDisplayedChild() == 0)
                    break;

                mViewFlipper.setInAnimation(this, R.anim.in_from_left);
                mViewFlipper.setOutAnimation(this, R.anim.out_to_right);

                mViewFlipper.showPrevious();
            }

            // right to left swipe
            if (lastX > currentX)
            {
                if (mViewFlipper.getDisplayedChild() == mViewFlipper.getChildCount() - 1)
                    break;

                mViewFlipper.setInAnimation(this, R.anim.in_from_right);
                mViewFlipper.setOutAnimation(this, R.anim.out_to_left);

                mViewFlipper.showNext();
            }

            break;
        }
    }

    return false;
}

When I debug the code, I don't see any differences between when the animation is working and when it isn't. Also, I see this behavior on an actual device and the emulator. What did I miss? I can post the animation xml files and the view xml, if they are needed.

EDIT:

The only way I am able to get this to work as expected is to set the following in the onCreate method:

   mViewFlipper.setInAnimation(this, R.anim.in_from_right);
    mViewFlipper.setOutAnimation(this, R.anim.out_to_left);
    mViewFlipper.setFlipInterval(10000);
    mViewFlipper.startFlipping();

I then call stopFlipping() on the first swipe. The interesting thing to me is that the animation works on the first swipe with these changes, even if the first auto-flip hasn't occurred. However, if I simply set the animation in the onCreate method without calling the startFlipping() method, it still doesn't have the animation on the first swipe. Can someone offer an explanation as to why this behavior occurs?

like image 398
Matt M Avatar asked Jun 29 '15 12:06

Matt M


2 Answers

At first, you dont have true algorythm of your onTouchEvent. Now you get something like inversion with incorrect animation order setting.

Try to use my onTouchEvent, this is work for me like a charm:

   public boolean onTouchEvent(MotionEvent touchevent)
    {
        switch (touchevent.getAction())
        {
            // when user first touches the screen to swap
            case MotionEvent.ACTION_DOWN:
            {
                lastX = touchevent.getX();
                break;
            }
            case MotionEvent.ACTION_UP:
            {
                float currentX = touchevent.getX();

                // if left to right swipe on screen
                if (lastX < currentX)
                {
                    // If no more View/Child to flip
                    if (viewFlipper.getDisplayedChild() == 0)
                        break;

                    // set the required Animation type to ViewFlipper
                    // The Next screen will come in form Left and current Screen will go OUT from Right
                    viewFlipper.setInAnimation(this, R.anim.in_from_left);
                    viewFlipper.setOutAnimation(this, R.anim.out_to_right);
                    // Show the next Screen
                    viewFlipper.showNext();
                }

                // if right to left swipe on screen
                if (lastX > currentX)
                {
                    if (viewFlipper.getDisplayedChild() == 1)
                        break;
                    // set the required Animation type to ViewFlipper
                    // The Next screen will come in form Right and current Screen will go OUT from Left
                    viewFlipper.setInAnimation(this, R.anim.in_from_right);
                    viewFlipper.setOutAnimation(this, R.anim.out_to_left);
                    // Show The Previous Screen
                    viewFlipper.showPrevious();
                }
                break;
            }
        }
        return true;
    }
like image 157
GIGAMOLE Avatar answered Nov 13 '22 03:11

GIGAMOLE


Looking through the ViewFlipper class's source code, the ViewFlipper.showNext() internally calls the ViewAnimator.showOnly(int position) method.

This is the validation performed inside that method:

   void showOnly(int childIndex) {
        final boolean animate = (!mFirstTime || mAnimateFirstTime);
        showOnly(childIndex, animate);
   }

So, in order to achieve what you want, you'll need to tell the ViewFlipper to animate the first flip inside your Activity.onCreate:

    @Override
    void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.my_activity);
        mViewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);
        mViewFlipper.setAnimateFirstView(true);
   }

NOTE:

I was able to achieve this without calling mViewFlipper.setAnimateFirstView(true) using API level 22. But it doesn't seem to work the same on previous versions.

like image 1
mmark Avatar answered Nov 13 '22 03:11

mmark