ViewPager的使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
public
class
MainActivity
extends
Activity
{
/*
* XML添加viewpager方法:
* <android.support.v4.view.ViewPager
* android:id="@+id/viewPager"
* android:layout_width="match_parent"
* android:layout_height="match_parent"/>
*/
int
[] ImageIds =
new
int
[]
{ R.drawable.guide_daily_brand, R.drawable.guide_item_detail_1, R.drawable.guide_item_detail_2, R.drawable.guide_multi_shop_detail,
R.drawable.guide_pic_mode, R.drawable.guide_timeline_filter };
private
ArrayList<View> mViewList =
new
ArrayList<View>();
@Override
protected
void
onCreate(Bundle savedInstanceState)
{
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(
new
PagerAdapter()
{
@Override
public
Object instantiateItem(View container,
int
position)
{
//第一页和最后一页只创建保留两个view来复用,中间则保留三个view
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.pager_item,
null
);
//将View加入到容器和container里面,不加判断会造成泄漏
if
(mViewList.size() < ImageIds.length)
{
mViewList.add(layout);
}
((ViewPager) container).addView(layout,
0
);
layout.setBackgroundResource(ImageIds[position]);
return
layout;
}
@Override
public
void
destroyItem(View container,
int
position, Object object)
{
//此处的position与上面的并不相等,会自动销毁不在当前页左右的view
((ViewPager) container).removeView(mViewList.get(position));
}
@Override
public
boolean
isViewFromObject(View arg0, Object arg1)
{
return
arg0 == arg1;
//判断对象与类型
}
@Override
public
int
getCount()
{
return
ImageIds.length;
}
});
}
@Override
public
boolean
onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return
true
;
}
}
|
其他笔记:
1.viewpager切换时容易造成oom问题
1
2
3
4
5
6
|
mViewPager = (ViewPager) findViewById(R.id.photogallery_viewpager);
mAdapter =
new
PhotoGalleryAdapter();
//限制view的数量,减少view缓存,在setAdapter之前使用
mViewPager.setOffscreenPageLimit(
3
);
mViewPager.setAdapter(mAdapter);
mViewPager.setCurrentItem(mPagerSelected);
|
2.两种removeview方法
1
2
3
4
5
6
|
@Override
public
void
destroyItem(View container,
int
position, Object object)
{
// ((ViewPager) container).removeView((View) object);
((ViewPager) container).removeView(mViewList.get(position));
}
|
3.关于notifyDataSetChanged()方法无法及时更新的问题解决方法
(1)销毁ViewItem时要使用以下方法:
1
2
3
4
5
6
|
@Override
public
void
destroyItem(View container,
int
position, Object object)
{
// ((ViewPager) container).removeView(mViewList.get(position));
((ViewPager) container).removeView((View)object);
}
|
参考资料:http://www.myexception.cn/android/417891.html
(2)重写notifyDataSetChanged()和getItemPosition(Object object)方法,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private
int
mChildCount =
0
;
@Override
public
void
notifyDataSetChanged()
{
mChildCount = getCount();
super
.notifyDataSetChanged();
}
@Override
public
int
getItemPosition(Object object)
{
if
(mChildCount >
0
)
{
mChildCount--;
return
POSITION_NONE;
}
return
super
.getItemPosition(object);
}
|
参考资料:http://www.cnblogs.com/maoyu417/p/3740209.html
附相关注释:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
进入viewpager,我们终于找到了viewpager中控制数据变更的重点方法dataSetChanged ,这个方法如下:
void
dataSetChanged () {
// This method only gets called if our observer is attached, so mAdapter is non-null.
boolean
needPopulate = mItems .size() < mOffscreenPageLimit *
2
+
1
&&
mItems.size() < mAdapter.getCount();
int
newCurrItem = mCurItem ;
boolean
isUpdating =
false
;
for
(
int
i =
0
; i < mItems.size(); i++) {
final
ItemInfo ii = mItems .get(i);
final
int
newPos = mAdapter.getItemPosition(ii.object );
if
(newPos == PagerAdapter.POSITION_UNCHANGED ) {
continue
;
}
if
(newPos == PagerAdapter.POSITION_NONE) {
mItems.remove(i);
i--;
if
(!isUpdating) {
mAdapter.startUpdate(
this
);
isUpdating =
true
;
}
mAdapter.destroyItem(
this
, ii.position , ii.object);
needPopulate =
true
;
if
(mCurItem == ii.position ) {
// Keep the current item in the valid range
newCurrItem = Math. max(
0
, Math.min(mCurItem, mAdapter.getCount() -
1
));
needPopulate =
true
;
}
continue
;
}
if
(ii.position != newPos) {
if
(ii.position == mCurItem ) {
// Our current item changed position. Follow it.
newCurrItem = newPos;
}
ii. position = newPos;
needPopulate =
true
;
}
}
if
(isUpdating) {
mAdapter.finishUpdate(
this
);
}
Collections. sort(mItems, COMPARATOR);
if
(needPopulate) {
// Reset our known page widths; populate will recompute them.
final
int
childCount = getChildCount();
for
(
int
i =
0
; i < childCount; i++) {
final
View child = getChildAt(i);
final
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if
(!lp.isDecor ) {
lp. widthFactor =
0
.f;
}
}
setCurrentItemInternal(newCurrItem,
false
,
true
);
requestLayout();
}
}
重点看这样一行代码:
final
int
newPos = mAdapter.getItemPosition(ii.object );
if
(newPos == PagerAdapter.POSITION_UNCHANGED ) {
continue
;
}
官方对getItemPosition()的解释是:
Called when the host view is attempting to determine
if
an item’s position has changed. Returns POSITION_UNCHANGED
if
the position of the given item has not changed orPOSITION_NONE
if
the item is no longer present in the adapter.
The
default
implementation assumes that items will never change position and always returns POSITION_UNCHANGED.
意思是如果item的位置如果没有发生变化,则返回POSITION_UNCHANGED。如果返回了POSITION_NONE,表示该位置的item已经不存在了。默认的实现是假设item的位置永远不会发生变化,而返回POSITION_UNCHANGED
解决方案:
所以我们可以尝试着修改适配器的写法,覆盖getItemPosition()方法,当调用notifyDataSetChanged时,让getItemPosition方法人为的返回POSITION_NONE,从而达到强迫viewpager重绘所有item的目的。
|
本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1224648,如需转载请自行联系原作者