Viewflipper 动画在第一次滑动时不起作用

Viewflipper animation doesn't work on first swipe

在我的主 activity 上,我有一个带有三个子视图的取景器。应用程序首次启动后,当我第一次从右向左滑动时,视图发生变化,但没有幻灯片动画。第一次滑动后,向任一方向滑动时动画都按预期工作。我正在关注 this 教程。我使用的代码是:

 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;
}

当我调试代码时,我没有发现动画工作和不工作之间有任何区别。此外,我在实际设备和模拟器上看到了这种行为。我错过了什么?如果需要,我可以 post 动画 xml 文件和视图 xml。

编辑:

我能够让它按预期工作的唯一方法是在 onCreate 方法中设置以下内容:

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

然后我在第一次滑动时调用 stopFlipping()。对我来说有趣的是,即使没有发生第一次自动翻转,动画也会在第一次滑动时使用这些更改。但是,如果我只是在 onCreate 方法中设置动画而不调用 startFlipping() 方法,它在第一次滑动时仍然没有动画。有人可以解释为什么会出现这种行为吗?

起初,您没有 onTouchEvent 的真正算法。现在你会得到类似动画顺序设置不正确的反转。

尝试使用我的 onTouchEvent,这对我来说很有魅力:

   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;
    }
Try to use this gesture for swipe with animation just get animation swipe left to right and right to left and put inside this:

   final GestureDetector gesture = new GestureDetector(getActivity(),
                new GestureDetector.SimpleOnGestureListener() {

                    @Override
                    public boolean onDown(MotionEvent e) {
                        return true;
                    }

                    @Override
                    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                            float velocityY) {
                        Log.i("null", "onFling has been called!");
                        final int SWIPE_MIN_DISTANCE = 80;
                        final int SWIPE_MAX_OFF_PATH = 150;
                        final int SWIPE_THRESHOLD_VELOCITY = 100;
                        try {
                            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
                                return false;
                            if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
                                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                                try {

                                  //your swipe code 
                                } catch (Exception e) {
                                    n = -1;
                                }

                            } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                                try {

//your swipe code 
                         } catch (Exception e) {

                                }

                            }
                        } catch (Exception e) {
                        }
                        return super.onFling(e1, e2, velocityX, velocityY);
                    }
                });
        yourFullRelativeLayout.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return gesture.onTouchEvent(event);
            }
        });
        yourView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return gesture.onTouchEvent(event);
            }
        });

查看 ViewFlipper class 的源代码,ViewFlipper.showNext() 内部调用 ViewAnimator.showOnly(int position) 方法。

这是在该方法中执行的验证:

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

因此,为了实现您想要的效果,您需要告诉 ViewFlipper 为您的 Activity.onCreate:

中的第一个翻转设置动画
    @Override
    void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

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

注意:

我能够在不使用 API 级别 22 调用 mViewFlipper.setAnimateFirstView(true) 的情况下实现这一点。但它在以前的版本中似乎并不相同。