需求:
通过左右滑动刷新ViewPager的内容,要求往右前进,往左后退,除非遇到数据两个端点否则不会间断。
记录一下我的处理过程,前后一共试用了4种方法:
方法一:ViewPager(10个page)
左右滑动处理:ViewPager中添加10个page,都是一个Fragment的复用,当滑动到最后一个界面时,跳转到第一个page。实现循环滑动。
数据处理:
内存常驻10组数据。
第一次加载:初次加载10条数据,分别布局到10个page上。
更新数据:每当向右滑动滑动到第10个page时,自动加载新的一组数据。每当向左滑动到第1个page时,加载一组新的数据。
当然,加载的数据可以从网上下载或者从本地数据表或文件加载。
思路介绍:
1.10张page的ViewPage只用在首尾加载数据,中间可以保证流畅滑动加载。
2.使用setCurrentItem();进行跳转,实现循环滑动的效果。即只要有数据,向左向右可以无限拖动。
3,ViewPager滑动时的默认动画是可以看到下一张的缩影的,而我们的数据已经布局到每一个page上了,因此缩影上有数据。
出现的bug:
1.使用setCurrentItem();从最后一张跳到第一张时,不是一下跳到的,而是遍历了从0-9张,可以使用下面的代码来遮盖这个效果,优化动画:
//控制跳转速度
public class FixedSpeedScroller extends Scroller {
private int mDuration = 0;
public FixedSpeedScroller(Context context) {
super(context);
}
public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
@SuppressLint("NewApi")
public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) {
super(context, interpolator, flywheel);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, mDuration);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
super.startScroll(startX, startY, dx, dy, mDuration);
}
}
//* 设置ViewPager的滑动速度
// *
// * */
private void setViewPagerScrollSpeed( ){
try {
Field mScroller = null;
mScroller = ViewPager.class.getDeclaredField("mScroller");
mScroller.setAccessible(true);
FixedSpeedScroller scroller = new FixedSpeedScroller( vp.getContext( ) );
mScroller.set( vp, scroller);
}catch(NoSuchFieldException e){
}catch (IllegalArgumentException e){
}catch (IllegalAccessException e){
}
}
但是如果你是index+1 到达最后一张,更新了下一组的数据(第2组 10-19),但是这时又往回拖动,希望还是显示的第一组(0-9),就会发现显示的是内存中刚加载的第二组(10-19)。同样,在后退时也存在这样一个bug。
3.10个page太多,占用缓存。
方法二:ViewPager(3个page)
这时请教了群里的少年们得到的方法,谢谢。
使用了3个page的ViewPager,复用同一个Fragment。
左右滑动:
虽然使用了3个page的ViewPager,用户看到的始终是第2个即中间的那个page。
当向左滑动,本来会跳到第3个page,使用setCurrentItem(1);跳回去。当向右滑动,本来会转到第1个page,使用setCurrentItem(1);跳回去。
数据处理:
在使用了setCurrentItem(1);方法后更新数据。
思路:
1.是用户看到的始终是第2个page,这样解决了循环滑动的问题。
bug:
1.滑动page时看到的下一张的缩影是空白的。
2,内存中如果放置一组数据,还是无法预判加载一组新数据后用户的操作。
方法三:ViewPager + GestureDetector
这时我想利用Gesture是否可以通过用户的手势事先预判用户的滑动方向呢?这样根据手势来决定加载哪一组数据进入内存。
我在方法二的基础上使用了GestureDetector,这时候出现了手势事件处理的冲突问题
Viewpager是子控件, GestureDetector是绑定在父控件上的,改来改去,有时候只有ViewPager拿到手势事件,有时候只有父控件拿到手势事件。
突然我想到,既然能通过手势来判断左右动作,为什么不跳过ViewPager这个梗呢?只使用一个布局,每次通过手势判断更新数据?
方法四: GestureDetector
只使用一个GestureDetector,通过手势判断前进或者后退。
但是数据处理上,一次加载10组数据进内存的办法我放弃了。因为即使使用手势判断,还是有bug,比如说现在显示的10个数据中的组后一组,手势判断知道要前进,那么会加载新的10个数据进内存,这时候如果再后退,会又加载10条旧的数据进内存。
因此我在数据处理上将数据放在SQLite表中,每次手势判断到向左或向右,就去数据表中加载对应的一条数据出来更新布局。实验证明,从数据表中select一条数据,然后即使根据数据再去sd卡上读一张图片,然后将文字和图片布局到界面上,效果还是不错的。现在的手机cpu完全可以应对。
在程序中记录当前的信息编号index以及本地表中最大的信息编号maxindex,然后在合适的时机下载若干组数据到本地存入SQLite数据表,这样的话,每次滑动后台执行的
动作就是读表然后布局。
四种方法中方法四是我现在采用的,当然不一定是最好的处理办法。
写的比较乱,希望对大家有所启发,看不清楚可以在评论中指出,当然如果你有更好的办法请分享给我!