ViewPager自动切换及手动滑动重新计时的问题

最近的项目有个需求是viewpager自动轮播,一开始采用的是ScheduledExecutorService+handler实现定时翻页功能,代码如下:

 private ScheduledExecutorService mSchedule;
  mSchedule = Executors.newSingleThreadScheduledExecutor();
        mSchedule.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                if (!isMoving && !isScroll) {
                    mCurrentItem = (mCurrentItem + 1) % banners.size();
                    handler.obtainMessage().sendToTarget();
                }
            }
        }, 2, 4, TimeUnit.SECONDS);
handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                mViewPager.setCurrentItem(mCurrentItem);
            }
        };

同时监听viewpager的onTouch事件来控制手动翻页时屏蔽掉定时翻页:

vp_news.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_UP:
                        isMoving = falsebreak;
                    case MotionEvent.ACTION_CANCEL:
                        isMoving = false;   
                        break;
                    case MotionEvent.ACTION_MOVE:
                        isMoving = true;
                        break;
                }
                return false;
            }
        });

但是这么做发现了一个问题,当用户手动翻页后计时器无法重新计时,造成用户在即将自动翻页的时候翻页,页面无法停留原来预计的时间,从而很快的自动翻到下一页(吐槽一下自己的表达能力/(ㄒoㄒ)/~~)。所以换了另一个思路:

1、在页面onCreate的时候,使用handler延时翻到下一页

 dHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mVpNews.setCurrentItem(mVpNews.getCurrentItem()+1);
            }
        },4000);

2、复写viewpager OnPageChangeListener的onPageSelected方法,加入handler延时翻页功能

@Override
    public void onPageSelected(int position) {
        mCurrentItem = position;
        dHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mCurrentItem = (mCurrentItem + 1) % banners.size();
                mVpNews.setCurrentItem(mCurrentItem);
            }
        }, 4000);



    }

3、复写viewpager OnPageChangeListener的onPageScrollStateChanged方法,在手指滑动的时候remove掉handler(ps:由于必然会调用onPageSelected方法,所以也必然会调用handler的延时翻页方法,因此不必担心remove掉handler后无法自动翻页的问题了)

 @Override
    public void onPageScrollStateChanged(int state) {
        switch (state) {
            case ViewPager.SCROLL_STATE_DRAGGING://手指滑动状态
             dHandler.removeCallbacksAndMessages(null);
                break;
            case ViewPager.SCROLL_STATE_IDLE://停止状态

                break;
            case ViewPager.SCROLL_STATE_SETTLING://自动滑动状态

                break;

            default:
                break;
        }

    }

到此就实现了viewpager自动翻页的功能,同时也避免了手动翻页无法重新计时的问题,如有问题请大神们指出:)


更新:以上代码没有考虑到一个问题,当用户滑动viewpager一页还没翻页又退回的当前页面时无法触发onPageSelected方法,因此就无法继续自动翻页了。解决方法是在onPageScrollStateChanged方法里监听手指滑动开始(state=ViewPager.SCROLL_STATE_DRAGGING时)记录下当前页面currentItem的值,在滑动结束(state = ViewPager.SCROLL_STATE_IDLE)比较当前的currentItem和开始记录的item是否一致,如果一致则调用handler.postDelayed自动翻页,修改后的代码如下:

@Override
    public void onPageScrollStateChanged(int state) {
        switch (state) {
            case ViewPager.SCROLL_STATE_DRAGGING://手指滑动状态
            //记录滑动开始时的当前页面
                item = mVpNews.getCurrentItem();

                dHandler.removeCallbacksAndMessages(null);
                break;
            case ViewPager.SCROLL_STATE_IDLE://停止状态
                //比较滑动结束后当前页面和开始滑动时的页面值
                if(item == mVpNews.getCurrentItem()){
                    dHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mCurrentItem = (mCurrentItem + 1) % banners.size();
                            mVpNews.setCurrentItem(mCurrentItem);
                        }
                    }, 4000);
                }
                item = -1;
                break;
            case ViewPager.SCROLL_STATE_SETTLING://自动滑动状态

                break;

            default:
                break;
        }

    }

贴下全部代码

package com.yjs.viewpagerautoscroll;

import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {

    ViewPager viewPager;
    List list;
    Handler handler;

    int item = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        list = new ArrayList<>();
        list.add("页面一");
        list.add("页面二");
        list.add("页面三");
        list.add("页面四");
        list.add("页面五");
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        viewPager.addOnPageChangeListener(this);
        viewPager.setAdapter(new ViewPagerAdapter());
        handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
            }
        }, 4000);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                viewPager.setCurrentItem((viewPager.getCurrentItem() + 1) % list.size());
            }
        }, 4000);

    }

    @Override
    public void onPageScrollStateChanged(int state) {
        switch (state){
            case ViewPager.SCROLL_STATE_DRAGGING:
                handler.removeCallbacksAndMessages(null);
                item = viewPager.getCurrentItem();
                break;
            case ViewPager.SCROLL_STATE_IDLE:
                if(item == viewPager.getCurrentItem()){
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            viewPager.setCurrentItem((viewPager.getCurrentItem() + 1) % list.size());
                        }
                    }, 4000);
                }

                item = -1;
                break;
            case ViewPager.SCROLL_STATE_SETTLING:
                break;

        }

    }

    private class ViewPagerAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = LayoutInflater.from(container.getContext()).inflate(R.layout.item_layout, null);
            TextView textView = (TextView) view.findViewById(R.id.textView);
            textView.setText(list.get(position));
            textView.setBackgroundColor(Color.BLUE);
            container.addView(view);
            return view;
        }
    }


}

你可能感兴趣的:(ViewPager自动切换及手动滑动重新计时的问题)