Android ViewPager动态向前向后加载数据,自定义viewPager滑动速度

来自: http://hiqianjin.com/blog/474


update 8/22 这个文章过时了,关于viewPager动态加载的请看我另一篇文章,这个文章中调整viewpager的滑动速度的代码还是可行的,关于动态加载,请看:http://hiqianjin.com/blog/516

最近用到一个效果,先有一个数据列表,然后,从这个列表中的任意一个位置进去,然后,点击“上一条”,“下一条”进行数据加载,我用了viewPager进行加载,为了使前后加载都有动画效果,且viewPager加载到一定数量的数据后就删除一些前后的数据(向前加载的时候就不断删后面的数据,向后反之)。

在viewPagerAdapter中,数据用了arrayList来封装,当向前的时候,我在arrayList的0位置,也就是最前面加载一条数据,然后再让adapter.notifyDataSetChange(),这样数据就加载到里面去了,关键是,当你处于viewPager index=0的时候,向前加载一条数据,然后,viewPager.setCurrentIndex(currenIndex – 1);目前,CurrenIndex = 0 ,-1后=-1,这样是可以移动到向前加载的那一页的,但是没有滑动的效果,为了让它用效果,用了以下方法,先把viewPager的页面移到加载后的第2页,也就是加载前的第一页,这次移动不要用动画,第二次移动,用上动画,在当前这个第二页向前移动:

1 //这儿是关键,要不没有跳转效果 这是一次加载两条数据的情况
2 vp.setCurrentItem(index+loadDataCount,false);
3 vp.setCurrentItem(index+loadDataCount - 1,true);

上面是向前加载的,麻烦一点,向后加载就简单了,直接在arrayList里加载一条数据,然后:

1 //index = vp.getCurrentItem();
2 vp.setCurrentItem(index+loadDataCount,false);

主要的思路就是:当viewPager向前加载到快要到index=0的时候就去加载几条数据,要么到index=0的时候再去加载也行,向后一样的道理,关键是移动的动画处理。

—————————————————————————————————————————————–

DEMO完成后,一次加载多页又不适用于我现有的项目,我又做成了viewPager中只会存在一条数据,当每次加载完,滑动到下一条数据后,就马上把上一条删掉,这下代码就简单了,大概如下:
向前加载:

01 //init your DataBean
02 list.add(0,yourDataBean)
03  
04 viewPagerAdapter.notifyDataSetChanged();
05 viewPager.setCurrentItem(index+1,false);
06 viewPager.setCurrentItem(index,true);
07 new Handler().postDelayed(new Runnable() {
08   @Override
09   public void run() {
10     pagerViews.remove(pagerViews.size()-1);
11     viewPagerAdapter.notifyDataSetChanged();
12   }
13 },500);

向后加载:

01 //init your DataBean
02 list.add(yourDataBean);
03 viewPagerAdapter.notifyDataSetChanged();
04 viewPager.setCurrentItem(index+1,true);
05 new Handler().postDelayed(new Runnable() {
06   @Override
07   public void run() {
08     pagerViews.remove(0);
09     viewPagerAdapter.notifyDataSetChanged();
10   }
11 },500);

这儿延迟500毫秒是因为我的viewPager的滑动时间我自定义为了400毫秒,如何自定义viewPager的滑动速度如下:
新建一个滑动处理类

01 import android.content.Context;
02 import android.view.animation.Interpolator;
03 import android.widget.Scroller;
04  
05 public class FixedSpeedScroller extends Scroller {
06  
07     private int mDuration = 2000;
08  
09     public FixedSpeedScroller(Context context) {
10         super(context);
11     }
12  
13     public FixedSpeedScroller(Context context, Interpolator interpolator) {
14         super(context, interpolator);
15     }
16  
17     @Override
18     public void startScroll(int startX, int startY, int dx, int dy, intduration) {
19         // Ignore received duration, use fixed one instead
20         super.startScroll(startX, startY, dx, dy, mDuration);
21     }
22  
23     @Override
24     public void startScroll(int startX, int startY, int dx, int dy) {
25         // Ignore received duration, use fixed one instead
26         super.startScroll(startX, startY, dx, dy, mDuration);
27     }
28  
29     public void setmDuration(int time) {
30         mDuration = time;
31     }
32  
33     public int getmDuration() {
34         return mDuration;
35     }
36 }

然后在你用到viewPager的地方用JAVA的反射来调整viewPager的滑动速度:

01 // use reflect change duration
02       try {
03         Field mField = ViewPager.class.getDeclaredField("mScroller");
04         mField.setAccessible(true);
05         FixedSpeedScroller mScroller =
06             new FixedSpeedScroller(viewPager.getContext(), newAccelerateInterpolator());
07         // 可以用setDuration的方式调整速率
08         mScroller.setmDuration(400);
09         mField.set(viewPager, mScroller);
10       catch (Exception e) {
11         e.printStackTrace();
12       }

主要是滑动效果的处理,折腾了好久,有还是不明白的同学可以email我。




以前写过一次这个文章,在这儿,直到上周末,做一个图片应用的时候,发现以前出现了方向性错误,导致可能误导了一些人,大家看到以前那篇文章的时候,估计没有几个人能看明白是怎么回事儿,在动态向前向后加载的时候,有不少的小逻辑判断,极容易出错,而且不断的设置setCurrentItem(),在临界的时候,其实用了一个先把viewPager设置为无动画,跳转一次位置,再设置viewPager有动画,再次跳转位置,模拟有动画的效果,其实在这个操作过程中仔细看,能看出来page的变化的,效果不好。

好了,扯了这么大一通,从上面一段就可以看出来以前写得不简单了,下面是新的思路,效果和逻辑都很简单:

再来回顾一下这个功能的应用场景:有一个装有很多条数据的一个list,这个list在listView中显示出来了,现在滑动listView随便到一个位置,点击一个item进入数据的详情页,在这个详情页,我们用到了viewPager,让它实现左右滑动的效果。

以前我也是在网上找的DEMO,大家通常的做法是,一进入详情页,就把每个页面的view初始化出来,然后把这些view放在list里面,传给自己定义的viewPagerAdapter,这样就出现滑动效果了。但是这样就会出现一个问题,就是我的list太大,初始化出来的view页面就会很多,比如说1000条数据,不可能全初始化出view来放list里再传给adapter吧,这样八成OOM的,于是我就照着这个思路,先初始化一部分view,再不断的滑动过程中,再初始化一部分,但是如果你是从数据列表的中间进入,向前滑动时不断的初始化view添加进list,这样viewPagerAdapter的大小就会发生变化,你的currentIndex就在不断的变化。超级不好控制。

再回想一下我们平时做一些常见的adapter的做法,没有在activity中把所有的item初始化出来,再传给adapter,让adapter做显示吧,常用的做法是,在adapter里再进行数据的封装什么的,在adapter中的getView()中进行操作,无论是自定义界面,还是填充数据。其实,viewPager的PagerAdapter也是同样的思路。回想一下,其实就是基本的adapter的操作了,以前刚学习这个控件的时候被网上别人的demo误导了。

01 public class DemoAdapter extends PagerAdapter {
02  
03   private Context context;
04   private ArrayList list;
05   private LayoutInflater inflater;
06  
07   public DemoAdapter (Context context, ArrayList list) {
08     this.list = list;
09     this.context = context;
10     inflater = LayoutInflater.from(context);
11  
12   }
13  
14   @Override
15   public void destroyItem(ViewGroup container, int position, Object object) {
16     ((ViewPager) container).removeView((View) object);
17   }
18  
19   @Override
20   public void finishUpdate(View container) {}
21  
22   @Override
23   public int getCount() {
24     return list != null ? list.size() : 0;
25   }
26  
27   @Override
28   public Object instantiateItem(ViewGroup view, int position) {
29  
30     UserBean bean = list.get(position);
31  
32     //自定义的view
33     View userLayout = inflater.inflate(R.layout.show_user_detail, view,false);
34     ImageView ivPhoto = (ImageView) userLayout.findViewById(R.id.user_photo);
35     TextView tvName = (TextView) userLayout.findViewById(R.id.user_name);
36  
37     //填充数据 
38     tvName.setText(bean.getUserName);
39  
40     ((ViewPager) view).addView(userLayout, 0);
41     return userLayout;
42   }
43  
44   @Override
45   public boolean isViewFromObject(View view, Object object) {
46     return view.equals(object);
47   }
48  
49   @Override
50   public void restoreState(Parcelable state, ClassLoader loader) {}
51  
52   @Override
53   public Parcelable saveState() {
54     return null;
55   }
56  
57   @Override
58   public void startUpdate(View container) {}
59 }

看完上面这段代码是不是很简单,还要注意一点就是,你在外面的listView从哪儿跳进viewPager的时候,要在viewPager设置完adapter的时候setCurretntIndex一下,就像下面这样:

1 viewPager.setCurrentItem(intoPosition)

我还做了个简单的DEMO放在Github上,超级简单,其实就是跟平常用adapter一样:地址 .


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值