如何在viewPager页面之间自动切换

问题描述 投票:18回答:8

我有一个Android应用程序,它使用带有两个页面的ViewPager当活动首次显示时,我想依次向用户呈现每个页面,以便他们知道他们可以在两个视图之间滑动。我没有找到任何描述如何执行此操作的文档。我发现PageTransformations听起来很有希望,但用户必须先刷卡。只要ViewPager中的第一页显示,我就需要自动滚动两页。怎样才能达到预期的效果?

android android-viewpager uiviewanimation
8个回答
61
投票

你可以使用Timer来达到这个目的。以下代码是自解释的:

// ---------------------------------------------------------------------------

Timer timer;
int page = 1;

public void pageSwitcher(int seconds) {
    timer = new Timer(); // At this line a new Thread will be created
    timer.scheduleAtFixedRate(new RemindTask(), 0, seconds * 1000); // delay
                                                                    // in
    // milliseconds
}

    // this is an inner class...
class RemindTask extends TimerTask {

    @Override
    public void run() {

        // As the TimerTask run on a seprate thread from UI thread we have
        // to call runOnUiThread to do work on UI thread.
        runOnUiThread(new Runnable() {
            public void run() {

                if (page > 4) { // In my case the number of pages are 5
                    timer.cancel();
                    // Showing a toast for just testing purpose
                    Toast.makeText(getApplicationContext(), "Timer stoped",
                            Toast.LENGTH_LONG).show();
                } else {
                    mViewPager.setCurrentItem(page++);
                }
            }
        });

    }
}

// ---------------------------------------------------------------------------

注1:确保在活动的pageSwitcher方法中正确设置adapterviewPager之后调用onCreate方法。

注2:每次启动时,viewPager都会滑动。你必须处理它,以便它只浏览所有页面一次(当用户第一次查看viewPager时)

注3:如果你想进一步减慢viewPager的滚动速度,你可以follow this answer on StackOverflow.


如果那对你有帮助,请在评论中告诉我......


28
投票

问题是陈旧但我希望它可以帮助某人使用Runnable我的解决方案

简短的回答

Runnable runnable = new Runnable() {
    public void run() {
        if (myAdapter.getCount() == page) {
            page = 0;
        } else {
            page++;
        }
        viewPager.setCurrentItem(page, true);
        handler.postDelayed(this, delay);
    }
};

长答案在活动中使用

public class activity extends AppCompatActivity {

    private Handler handler;
    private int delay = 5000; //milliseconds
    private ViewPager viewPager;
    private int page = 0;
    private MyAdapter myAdapter;
    Runnable runnable = new Runnable() {
        public void run() {
            if (myAdapter.getCount() == page) {
                page = 0;
            } else {
                page++;
            }
            viewPager.setCurrentItem(page, true);
            handler.postDelayed(this, delay);
        }
    };

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

        handler = new Handler();
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        myAdapter = new MyAdapter(getSupportFragmentManager());
        viewPager.setAdapter(myAdapter);
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                page = position;
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        handler.postDelayed(runnable, delay);
    }

    @Override
    protected void onPause() {
        super.onPause();
        handler.removeCallbacks(runnable);
    }
}

13
投票

我创建了a open source project on github,它实现了一个自动滚动ViewPager,示例图如下:

使用

<cn.trinea.android.view.autoscrollviewpager.AutoScrollViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

更换

<android.support.v4.view.ViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

调用startAutoScroll()开始自动滚动。

stopAutoScroll()停止自动滚动。

更多:https://github.com/Trinea/android-auto-scroll-view-pager


2
投票

以下方法用于在一段时间后自动切换页面(您可以根据需要修改时间)

 private void timer() {
                timer = new Timer();
                timer.scheduleAtFixedRate(new TimerTask() {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (currentPage == NUM_PAGES - 1) {
                                    currentPage = 0;
                                }
                                view.setCurrentItem(currentPage++, true);
                            }
                        });
                    }
                }, 500, 5000);
            }

如果想在viewpager中无限滚动使用来自下面提供的链接的无限滚动viewpager类,并在Runnable接口中进行微小更改(删除条件)。

runOnUiThread(new Runnable() {
                                @Override
                                public void run() {

                                    view.setCurrentItem(currentPage++, true);
                                }
                            });

另外,别忘了在Destroy视图上取消计时器。


1
投票

这是autoscroll view pager

package com.otapp.net.view;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
import android.widget.Scroller;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;

public class AutoScrollViewPager extends ViewPager {

    public static final int DEFAULT_INTERVAL = 1500;

    public static final int LEFT = 0;
    public static final int RIGHT = 1;

    public static final int SLIDE_BORDER_MODE_NONE = 0;
    public static final int SLIDE_BORDER_MODE_CYCLE = 1;
    public static final int SLIDE_BORDER_MODE_TO_PARENT = 2;

    private long interval = DEFAULT_INTERVAL;
    private int direction = RIGHT;
    private boolean isCycle = true;
    private boolean stopScrollWhenTouch = true;
    private int slideBorderMode = SLIDE_BORDER_MODE_NONE;
    private boolean isBorderAnimation = true;
    private double autoScrollFactor = 1.0;
    private double swipeScrollFactor = 1.0;

    private Handler handler;
    private boolean isAutoScroll = false;
    private boolean isStopByTouch = false;
    private float touchX = 0f, downX = 0f;
    private float touchY = 0f;

    private CustomDurationScroller scroller = null;

    public static final int SCROLL_WHAT = 0;

    public AutoScrollViewPager(Context paramContext) {
        super(paramContext);
        init();
    }

    public AutoScrollViewPager(Context paramContext, AttributeSet paramAttributeSet) {
        super(paramContext, paramAttributeSet);
        init();
    }

    private void init() {
        handler = new MyHandler(this);
        setViewPagerScroller();
    }

    /**
     * start auto scroll, first scroll delay time is {@link #getInterval()}
     */
    public void startAutoScroll() {
        isAutoScroll = true;
        sendScrollMessage((long) (interval + scroller.getDuration() / autoScrollFactor * swipeScrollFactor));
    }

    /**
     * start auto scroll
     *
     * @param delayTimeInMills first scroll delay time
     */
    public void startAutoScroll(int delayTimeInMills) {
        isAutoScroll = true;
        sendScrollMessage(delayTimeInMills);
    }

    /**
     * stop auto scroll
     */
    public void stopAutoScroll() {
        isAutoScroll = false;
        handler.removeMessages(SCROLL_WHAT);
    }

    /**
     * set the factor by which the duration of sliding animation will change while swiping
     */
    public void setSwipeScrollDurationFactor(double scrollFactor) {
        swipeScrollFactor = scrollFactor;
    }

    /**
     * set the factor by which the duration of sliding animation will change while auto scrolling
     */
    public void setAutoScrollDurationFactor(double scrollFactor) {
        autoScrollFactor = scrollFactor;
    }

    private void sendScrollMessage(long delayTimeInMills) {
        /** remove messages before, keeps one message is running at most **/
        handler.removeMessages(SCROLL_WHAT);
        handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);
    }

    /**
     * set ViewPager scroller to change animation duration when sliding
     */
    private void setViewPagerScroller() {
        try {
            Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
            scrollerField.setAccessible(true);
            Field interpolatorField = ViewPager.class.getDeclaredField("sInterpolator");
            interpolatorField.setAccessible(true);

            scroller = new CustomDurationScroller(getContext(), (Interpolator) interpolatorField.get(null));
            scrollerField.set(this, scroller);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * scroll only once
     */
    public void scrollOnce() {
        PagerAdapter adapter = getAdapter();
        int currentItem = getCurrentItem();
        int totalCount;
        if (adapter == null || (totalCount = adapter.getCount()) <= 1) {
            return;
        }

        int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
        if (nextItem < 0) {
            if (isCycle) {
                setCurrentItem(totalCount - 1, isBorderAnimation);
            }
        } else if (nextItem == totalCount) {
            if (isCycle) {
                setCurrentItem(0, isBorderAnimation);
            }
        } else {
            setCurrentItem(nextItem, true);
        }
    }

    /**
     * <ul>
     * if stopScrollWhenTouch is true
     * <li>if event is down, stop auto scroll.</li>
     * <li>if event is up, start auto scroll again.</li>
     * </ul>
     */

    boolean consumeTouch = false;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = MotionEventCompat.getActionMasked(ev);

        if (stopScrollWhenTouch) {
            if ((action == MotionEvent.ACTION_DOWN) && isAutoScroll) {
                isStopByTouch = true;
                stopAutoScroll();
            } else if (ev.getAction() == MotionEvent.ACTION_UP && isStopByTouch) {
                startAutoScroll();
            }
        }

        if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT || slideBorderMode == SLIDE_BORDER_MODE_CYCLE) {
            touchX = ev.getX();
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                downX = touchX;
                touchY = ev.getY();
            } else if (action == MotionEvent.ACTION_UP) {
                consumeTouch = Math.abs(touchY - ev.getY()) > 0;
            }

            int currentItem = getCurrentItem();
            PagerAdapter adapter = getAdapter();
            int pageCount = adapter == null ? 0 : adapter.getCount();
            /**
             * current index is first one and slide to right or current index is last one and slide to left.<br/>
             * if slide border mode is to parent, then requestDisallowInterceptTouchEvent false.<br/>
             * else scroll to last one when current item is first one, scroll to first one when current item is last
             * one.
             */
            if ((currentItem == 0 && downX <= touchX) || (currentItem == pageCount - 1 && downX >= touchX)) {
                if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT) {
                    getParent().requestDisallowInterceptTouchEvent(false);
                } else {
                    if (pageCount > 1) {
                        setCurrentItem(pageCount - currentItem - 1, isBorderAnimation);
                    }
                    getParent().requestDisallowInterceptTouchEvent(true);
                }
                return super.dispatchTouchEvent(ev);
            }
        }
        if (consumeTouch) {
            getParent().requestDisallowInterceptTouchEvent(true);
        } else {
            getParent().requestDisallowInterceptTouchEvent(false);
            if (stopScrollWhenTouch)
                startAutoScroll();
        }

        return super.dispatchTouchEvent(ev);
    }

    private static class MyHandler extends Handler {

        private final WeakReference<AutoScrollViewPager> autoScrollViewPager;

        public MyHandler(AutoScrollViewPager autoScrollViewPager) {
            this.autoScrollViewPager = new WeakReference<AutoScrollViewPager>(autoScrollViewPager);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case SCROLL_WHAT:
                    AutoScrollViewPager pager = this.autoScrollViewPager.get();
                    if (pager != null) {
                        pager.scroller.setScrollDurationFactor(pager.autoScrollFactor);
                        pager.scrollOnce();
                        pager.scroller.setScrollDurationFactor(pager.swipeScrollFactor);
                        pager.sendScrollMessage(pager.interval + pager.scroller.getDuration());
                    }
                default:
                    break;
            }
        }
    }

    public long getInterval() {
        return interval;
    }

    public void setInterval(long interval) {
        this.interval = interval;
    }

    public int getDirection() {
        return (direction == LEFT) ? LEFT : RIGHT;
    }

    public void setDirection(int direction) {
        this.direction = direction;
    }

    public boolean isCycle() {
        return isCycle;
    }

    public void setCycle(boolean isCycle) {
        this.isCycle = isCycle;
    }

    public boolean isStopScrollWhenTouch() {
        return stopScrollWhenTouch;
    }

    public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) {
        this.stopScrollWhenTouch = stopScrollWhenTouch;
    }

    public int getSlideBorderMode() {
        return slideBorderMode;
    }

    public void setSlideBorderMode(int slideBorderMode) {
        this.slideBorderMode = slideBorderMode;
    }

    public boolean isBorderAnimation() {
        return isBorderAnimation;
    }

    public void setBorderAnimation(boolean isBorderAnimation) {
        this.isBorderAnimation = isBorderAnimation;
    }

    public class CustomDurationScroller extends Scroller {

        private double scrollFactor = 1;

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

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

        // @SuppressLint("NewApi")
        // public CustomDurationScroller(Context context, Interpolator interpolator, boolean flywheel){
        // super(context, interpolator, flywheel);
        // }

        public void setScrollDurationFactor(double scrollFactor) {
            this.scrollFactor = scrollFactor;
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, (int) (duration * scrollFactor));
        }
    }

}

这是xml实现

这是类文件实现

 MovieFeaturedAdapter mMovieFeaturedAdapter = new MovieFeaturedAdapter(getActivity(), mCurrentMovies);
                    vpFeatured.setAdapter(mMovieFeaturedAdapter);

0
投票

您可以使用setCurrentItem更改页面


0
投票

如果你想自动播放viewpager页面,但最重要的是解决方案是正确的但是在自动播放后第一个项目消耗延迟时间但是在自动播放当前项目快速切换后它是错误的。我在下面添加我的代码它正常工作自动播放/暂停。

        @Override
        public void onClick(View v) {

            if (!isAutoPlay) {              
                img_autoplay.setImageResource(R.drawable.pause);
                int currentcount = getModel().getCurrentIndex();
                currentcount++;
                getMainImage().setCurrentItem(currentcount);
                autoPlay(getMainImage());
                isAutoPlay = true;
            } else {
                img_autoplay.setImageResource(R.drawable.auto_play);
                isAutoPlay = false;
            }
        }
    });

这是方法:

    viewPager.postDelayed(new Runnable() {
        @Override
        public void run() {
            try {
                if (myAdapter != null
                        && viewPager.getAdapter().getCount() > 0
                        && isAutoPlay) {
                    getWindow().addFlags(
                            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                    int currentcount = getModel().getCurrentIndex();
                    currentcount++;
                    viewPager.setCurrentItem(currentcount);

                    if (getModel().isLastCard()) {
                        final Handler handler = new Handler();
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                isAutoPlay = false;
                                packFinished();
                                getWindow()
                                        .clearFlags(
                                                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                            }
                        }, 6000);
                    }
                    autoPlay(viewPager);
                }
            } catch (Exception e) {

            }
        }
    }, 6000);

0
投票

如果您要自动切换页面,那么您应该禁用ViewPager上的分页/滑动,因为如果您触摸页面并且该时间页面切换然后它看起来不好意味着您观察到页面被击中。

要在ViewPager上禁用分页/滑动,您需要在自定义视图分页器中添加以下代码段。

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

import java.lang.reflect.Field;

public class ViewPagerCustomDuration extends ViewPager {

    private boolean swipeable = false;

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

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

    public void setSwipeable(boolean swipeable) {
        this.swipeable = swipeable;
    }

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

        return false;
    }

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

        return false;
    }

    private ScrollerCustomDuration mScroller = null;

    /**
     * Override the Scroller instance with our own class so we can change the
     * duration
     */
    private void postInitViewPager() {
        try {
            Field scroller = ViewPager.class.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            Field interpolator = ViewPager.class.getDeclaredField("sInterpolator");
            interpolator.setAccessible(true);

            mScroller = new ScrollerCustomDuration(getContext(),
                    (Interpolator) interpolator.get(null));
            scroller.set(this, mScroller);
        } catch (Exception e) {
        }
    }

    /**
     * Set the factor by which the duration will change
     */
    public void setScrollDurationFactor(double scrollFactor) {
        mScroller.setScrollDurationFactor(scrollFactor);
    }

}

之后,从view pager对象调用方法。

import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

import java.util.Timer;
import java.util.TimerTask;



public class MainActivity extends AppCompatActivity {
    ViewPagerCustomDuration viewPager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_3);

        viewPager = (ViewPagerCustomDuration) findViewById(R.id.viewpager);
        viewPager.setScrollDurationFactor(2);
        viewPager.setAdapter(new CustomPagerAdapter(this));
        viewPager.setSwipeable(false);
        pageSwitcher(5);

        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

    }

    Timer timer;
    int page = 1;

    public void pageSwitcher(int seconds) {
        timer = new Timer(); // At this line a new Thread will be created
        timer.scheduleAtFixedRate(new RemindTask(), 0, seconds * 1000); // delay
        // in
        // milliseconds
    }

    // this is an inner class...
    class RemindTask extends TimerTask {

        @Override
        public void run() {

            // As the TimerTask run on a seprate thread from UI thread we have
            // to call runOnUiThread to do work on UI thread.
            runOnUiThread(new Runnable() {
                public void run() {

                    if (page > 4) { // In my case the number of pages are 5
//                        timer.cancel();
                        page = 0;
                        viewPager.setCurrentItem(page++);
                        // Showing a toast for just testing purpose
                        Toast.makeText(getApplicationContext(), "Timer stoped",
                                Toast.LENGTH_LONG).show();
                    } else {
                        viewPager.setCurrentItem(page++);
                    }
                }
            });

        }
    }

滚动页面的滚动类顺畅

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.animation.Interpolator;
import android.widget.Scroller;

public class ScrollerCustomDuration extends Scroller {

    private double mScrollFactor = 1;

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

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

    @SuppressLint("NewApi")
    public ScrollerCustomDuration(Context context, Interpolator interpolator, boolean flywheel) {
        super(context, interpolator, flywheel);
    }

    /**
     * Set the factor by which the duration will change
     */
    public void setScrollDurationFactor(double scrollFactor) {
        mScrollFactor = scrollFactor;
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        super.startScroll(startX, startY, dx, dy, (int) (duration * mScrollFactor));
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.