head
在工作中或多或少的会遇到使用ViewPager的自动循环功能,对于初学者来说,这个功能实现起来并不是十分简单,所以在这里对这个功能的实现和想法简述一下,希望能够帮到读者。
(很气,本来结尾的,突然间给我清空了,很气很气)
ViewPager简述
看到这篇文章,说明对于ViewPager的简单实用:布局,初始化,Adapter设置等都已经没有问题,在这里也不做多余描述。
需要知道的,ViewPager有提供了一个切换条目方法:setCurrentItem()
,并且提供两种形式:
setCurrentItem(int item)
setCurrentItem(int item , boolean smoothScroll)
我们知道,item是使用方法想要切换的目的位置,而smoothScroll,则是判断切换是否带有动画。
ViewPager循环设想
循环,即是能从头直接滑到尾,从尾直接滑到头,而中间的相互滑动,ViewPager已经做好了所有事情。所以我们需要考虑的事情,就是如何实现从头条目直接滑到尾条目。
如上图所示,ViewPager需要展示这四张图片,在条目0右滑的时候,我们需要显示条目3,同样的,条目3左滑时,条目0需要展示出来。
由于ViewPager的机制,我们没办法在条目0的左边没有数据的时候,实现条目0右滑的完整动画。同样条目3右面没有数据时,左滑也不能实现。
也就是说,在条目0的前面需要有数据,而且应该和条目3一模一样,同样在条目3的后面需要有一条和条目0一样的条目。
突然,我有个大胆的想法:
开始就创建非常非常多的数据,将ViewPager的开始显示的位置显示在中间,这样向左向右滑动,只要不到头,就会是循环的样子。
但是,万一真的有用户给你一只滑着玩呢?别说没有,我遇到过点一个按钮十多分钟的测试。作为有志程序猿,我也不会使用这种方法。
那么先简单实现前后添加数据的想法:
这张图中,所有的数据是条目1.2.3.4,在数据的开始条目1向右滑动时,条目0展示出来,这样就实现了从头部滑动到尾部的切换效果。
尾部切换亦然。
看到这里是不是已经有想法在脑子里,就是还差一点才通?
我们既然切换到条目0,然后让他自动切换到条目4,接下来的滑动不就没有问题了吗?同理,在切换到条目5的时候,我们用代码实现切换到条目1,天呐,逻辑上完全可行!
在一通操作之后,确实实现了循环滑动,但是好像头尾衔接的时候,动画效果很不合适。所以需要使用前面说到的setCurrentItem(item,smoothScrool)
,把切换动画去掉。
实现代码
//数据的头尾添加就不在这里贴代码
final int size = vp.getAdapter().getCount();
if (3 > size) {
//如果里面的数据不够三页,不参与轮询
return;
}
vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
int position;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
this.position = position;
}
@Override
public void onPageScrollStateChanged(int state) {
/**
* state是ViewPager的滚动状态
* 0是停止状态,1是滚动状态
* 当ViewPager停止滚动的时候,我们进行无动画切换,更加流畅
*/
if (state == 0) {
if (position == 0) {
vp.setCurrentItem(size - 2, false);
} else if (position == size - 1) {
vp.setCurrentItem(1, false);
}
}
}
});
自动切换
自动切换,说的高深一些,是全自动的视图切换。那是糊弄鬼的,说简单了,就是定时调用ViewPager的setCurrentItem
方法。
是不是突然觉得没啥难的了?
那也原谅我将代码贴出来,不贴不舒服:
//在上面循环代码中的`onPageSelected`方法中
@Override
public void onPageSelected(int position) {
this.position = position;
/**
*移除切换事件,避免在用户手动切换后,可能立刻切换
*/
handler.removeMessages(code);
//移除事件后,重新发送事件,使切换时间控制在设置的值(dTime)上
handler.sendEmptyMessageDelayed(code, dTime);
}
//使用handler接收并处理切换
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case KEY_LOOP_START:
if (vp != null) {
vp.setCurrentItem(vp.getCurrentItem() + 1);
}
break;
}
}
};
END
代码量不大,逻辑也相对简单些。
看完是不是觉得之前的苦恼有些钻牛角尖?
最后,我将ViewPager的自动循环滑动做了一下封装,放在github里面,欢迎借鉴,更欢迎提出意见。
目前比较不太靠谱的github
最后的最后,手打到这里,希望各位能够顶一下。留言提意见更是感激不尽!先谢过。