Изменение скорости перехода ViewPager и setCurrentItem

У меня есть ViewPager, который я хочу автоматически поворачивать каждые 5 секунд, а также позволять пользователю проводить пальцем. Однако, когда я устанавливаю автоматическое изменение, анимация перехода между страницами происходит очень быстро, и я хочу, чтобы это было медленнее.

Я видел ответы на этот вопрос здесь:

Замедление скорости контроллера Viewpager в Android

... но все они используют отражение. Кто-нибудь знает способ замедлить автоматическую скорость ViewPager без использования отражения?

Я думал об использовании PageTransformer, но не уверен, что это сработает, а также, вероятно, повлияет на скорость, если пользователь пролистнет так же, как и автоматический? Разве я могу как-то обнаружить разницу, а потом сделать то или иное PageTransformation?


person Russ Wheeler    schedule 15.05.2014    source источник


Ответы (3)


Используйте этот пользовательский View

public class ViewPagerCustomDuration extends ViewPager {
    private FixedSpeedScroller mScroller = null;

    public ViewPagerCustomDuration(Context context) {
        super(context);
        init();
    }

    public ViewPagerCustomDuration(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /*
     * Override the Scroller instance with our own class so we can change the
     * duration
     */
    private void init() {
        try {
            Class<?> viewpager = ViewPager.class;
            Field scroller = viewpager.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            mScroller = new FixedSpeedScroller(getContext(),
                    new DecelerateInterpolator());
            scroller.set(this, mScroller);
        } catch (Exception ignored) {
        }
    }

    /*
     * Set the factor by which the duration will change
     */
    public void setScrollDuration(int duration) {
        mScroller.setScrollDuration(duration);
    }

    private class FixedSpeedScroller extends Scroller {

        private int mDuration = 500;

        public FixedSpeedScroller(Context context) {
            super(context);
        }

        public FixedSpeedScroller(Context context, Interpolator interpolator) {
            super(context, interpolator);
        }

        public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) {
            super(context, interpolator, flywheel);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }

        public void setScrollDuration(int duration) {
            mDuration = duration;
        }
    }
}
person Alexandr Larin    schedule 03.02.2015
comment
На самом деле я не помню, почему я спросил об этом или как я это решил, но в этом ответе достаточно галочек, поэтому я готов принять его как правильный ответ. Кроме того, @Ezio, кажется, думает, что это работает :D - person Russ Wheeler; 09.10.2017
comment
Отличное решение. - person marius; 15.06.2018
comment
Почему бы его не настроить хотя бы для компонента в библиотеке Compat? На дворе 2018 год, я думаю, мы заслужили возможность настраивать скорость анимации... - person Den Drobiazko; 16.10.2018
comment
@DenRimus Так верно .. невероятно. - person idish; 18.11.2018
comment
Обратите внимание, что этот класс использует отражение для доступа к внутренним полям ViewPager. Следовательно, он может перестать работать при любом обновлении Android! - person Lii; 08.11.2019
comment
@RussWheeler: В тексте вашего вопроса вы явно запрашиваете решение без отражения, и это решение использует отражение для доступа к частному полю. Что еще хуже, постер даже не удосужился указать на это. Я не думаю, что вы должны принять этот ответ. Вопрос по-прежнему актуален и без ответа. - person Lii; 08.11.2019

Вы создаете настраиваемый пейджер просмотра

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.Scroller;

import java.lang.reflect.Field;

public class CustomViewPager extends ViewPager {

    private FixedSpeedScroller mScroller = null;
    private boolean enabled;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = true;
        init();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onTouchEvent(event);
        }
        init();
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onInterceptTouchEvent(event);
        }
        return false;
    }

    public void setPagingEnabled(boolean enabled) {
        this.enabled = enabled;
    }


    /*
     * Override the Scroller instance with our own class so we can change the
     * duration
     */
    private void init() {
        try {
            Class<?> viewpager = ViewPager.class;
            Field scroller = viewpager.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            mScroller = new FixedSpeedScroller(getContext(),
                    new DecelerateInterpolator());
            scroller.set(this, mScroller);
        } catch (Exception ignored) {
        }
    }

    /*
     * Set the factor by which the duration will change
     */
    public void setScrollDuration(int duration) {
        mScroller.setScrollDuration(duration);
    }

    private class FixedSpeedScroller extends Scroller {

        private int mDuration = 500;

        public FixedSpeedScroller(Context context) {
            super(context);
        }

        public FixedSpeedScroller(Context context, Interpolator interpolator) {
            super(context, interpolator);
        }

        public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) {
            super(context, interpolator, flywheel);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }

        public void setScrollDuration(int duration) {
            mDuration = duration;
        }
    }

}

вы можете установить продолжительность просмотра пейджера в соответствии с вами

person Prabh deep    schedule 18.09.2018

используйте опцию таймера расписания для автоматического поворота страниц.

int i = 0;
static Timer timer = new Timer();

//Scroller scroll = new Scroller(this);

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.simple_circles);

    mAdapter = new TestFragmentAdapter(getSupportFragmentManager());

    mPager = (ViewPager) findViewById(R.id.pager);

    mPager.setAdapter(mAdapter);

     mIndicator = (CirclePageIndicator) findViewById(R.id.indicator);

    mIndicator.setViewPager(mPager);

    mPager.setCurrentItem(i);

    SwitchPage(3);


  }

public void SwitchPage(int seconds) 

{

if(timer != null)
{
    timer.cancel();
}

timer = new Timer(); // At this line a new Thread will be created

timer.schedule(new SwitchPageTask(), 
2000, seconds * 2000);               
 // delay in milliseconds
 }


class SwitchPageTask extends TimerTask 
{

@Override
public void run() {

    runOnUiThread(new Runnable() {

        public void run() {

            if(i < mAdapter.getCount())

            {

                i++;

                mPager.setCurrentItem(i, true);

            }
            else
            {

                i=0;

                mPager.setCurrentItem(i, true);
            }
        }
    });
}
}

just cancel the timer like.. timer.cancel().. or
cancel timer from another activity or fragment activity..

    textView1_page3.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                if (SampleCirclesDefault.timer != null) {
                    SampleCirclesDefault.timer.cancel();
                    Toast.makeText(getActivity(), "timer
                  cancled", 1).show();
                }

            }
        });
person harikrishnan    schedule 29.01.2015
comment
harikrishnan просматривая ваш код, похоже, что вы меняете задержку между изменениями. У меня проблема не в этом. Я думаю, что фактическая анимация автоматического перехода слишком быстрая, она почти мгновенная, я хочу, чтобы она прокручивалась от одного изображения к другому медленнее, а не с переменной разницей во времени. Я обновлю свой первоначальный вопрос, чтобы сделать это более ясным. - person Russ Wheeler; 30.01.2015