Анимация Viewflipper не работает при первом прокрутке

В моей основной деятельности у меня есть viewflipper с тремя дочерними представлениями. После первого запуска приложения, когда я делаю первый щелчок правой кнопкой мыши, вид изменяется, но в нем нет анимации слайдов. После первого прокрутки анимация работает так, как ожидалось, при прохождении в любом направлении. Я следую этому учебнику. Код, который я использую:

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

Когда я отлаживаю код, я не вижу различий между тем, когда анимация работает, а когда нет. Кроме того, я вижу это поведение на реальном устройстве и эмуляторе. Что я упустил? Я могу опубликовать файлы xml анимации и представление xml, если они необходимы.

EDIT:

Единственный способ, которым я могу заставить это работать, как ожидается, - установить следующее в методе 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(), у нее по-прежнему нет анимации при первом прокрутке. Может ли кто-нибудь дать объяснение, почему это происходит?

Ответ 1

Просматривая исходный код класса ViewFlipper, 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);
   }

Примечание:

Мне удалось достичь этого, не вызвав mViewFlipper.setAnimateFirstView(true) с использованием уровня API 22. Но он, похоже, не работает в предыдущих версиях.

Ответ 2

Во-первых, у вас нет истинного алгоритма вашего 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;
    }

Ответ 3

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