最近的项目有个需求是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 = false;
break;
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;
}
}
}