您的位置:首页 > 其它

viewpager2左右滑动--钱进

2015-07-13 15:55 288 查看


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

2014-8-12阅读191 评论0

来自: 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,
int
duration)
{
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的滑动速度:

view
source

print?

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(),
new
AccelerateInterpolator());
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一下,就像下面这样:

view
source

print?

1
viewPager.setCurrentItem(intoPosition)
我还做了个简单的DEMO放在Github上,超级简单,其实就是跟平常用adapter一样:地址 .
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: