当Android中想呈现幻灯片效果时,会想到使用VIEWPAGER加载图片呈现出来,实际操作的过程中坑无数,这里记录一下。
首先是按键的区别。
在手机中是通过手势监听滑动时间,在电视中是通过遥控器进行。比如说我正在幻灯片播放的时候,按一下前进键,应该停止正在播放。
那么我就需要在ACTIVITY/FRAGMENT层监听按键,而不能将按键事件传递给VIEWPAGER,这样事件就才能被ACTIVITY监听。
两个方案:
1.设置VIEWPAGER取不到焦点。
2.设置dispatchTouchEvent.阻断按键下行。
我实际采取了方案1,因为代码简单~~
循环播放的解决
其实最终的结论是目前看没有完美的解决方案。
先说MAX_INT的解决方案,问题很多,如果需要比较好的执行,需要先预制所有VIEW。。。当你照片多的时候,你懂得。。。
这个方案也可以不预置VIEW,但是当setCurrentItem的时候,会出现ANR。所以该方案PASS。
来看下面的规避方案,也是我现在做的方案。
先来介绍一下借用的开源库:
https://github.com/imbryk/LoopingViewPager
基础原理:
If you want to use LoopViewPager
with FragmentPagerAdapter
or FragmentStatePagerAdapter
additional
changes in the adapter must be done.
The adapter must be prepared to create 2 extra items e.g.:
- The original adapter creates 4 items:
[0,1,2,3]
- The modified adapter will have to create 6 items
[0,1,2,3,4,5]
- with mapping
realPosition=(position-1)%count
[0->3, 1->0, 2->1, 3->2, 4->3, 5->0]
@Override public Object instantiateItem(ViewGroup container, int position) { int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter) ? position : toRealPosition(position); Log.e("LoopPagerAdapter", "init position=" + position + "realposition=" + realPosition); if (mBoundaryCaching) { ToDestroy toDestroy = mToDestroy.get(position); if (toDestroy != null) { mToDestroy.remove(position); return toDestroy.object; } } return mAdapter.instantiateItem(container, realPosition); } @Override public void destroyItem(ViewGroup container, int position, Object object) { int realFirst = getRealFirstPosition(); int realLast = getRealLastPosition(); int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter) ? position : toRealPosition(position); Log.e("LoopPagerAdapter", "destroy position=" + position + "realposition=" + realPosition); if (mBoundaryCaching && (position == realFirst || position == realLast)) { mToDestroy.put(position, new ToDestroy(container, realPosition, object)); } else { mAdapter.destroyItem(container, realPosition, object); } }
区别就在红色的字体处,边界会进行缓存。。。
实际使用的时候还是有坑的:
1.快速滑动的时候,过边界的时候,还是可能会跳变。(这个没有办法解决,按键比手划快多了,手划出现的概率应该更小)
2.如果加入滑动动画,开始的时候从第一个往前滚到最后一个,会出现空图,viewpager不会预加载最后一张图。
这个时候缓存也没有生成。想了个规避办法,那就是滑到最后一个,就直接切到最后1个去,不切到-1(对应LoopViewPager 0)位置上去。。。
现在的实现效果就是自动播放可以完美运行,手动左滑到边界会跳一下,右滑快速滑动可能跳变。
目前就这样了,如果还有更好的解决方案欢迎提建议。