ViewPager的使用:
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问题
mViewPager = (ViewPager) findViewById(R.id.photogallery_viewpager);
mAdapter = new PhotoGalleryAdapter();
//限制view的数量,减少view缓存,在setAdapter之前使用
mViewPager.setOffscreenPageLimit(3);
mViewPager.setAdapter(mAdapter);
mViewPager.setCurrentItem(mPagerSelected);
2.两种removeview方法
@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时要使用以下方法:
@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)方法,代码如下:
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
附相关注释:
进入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的目的。
转载于:https://blog.51cto.com/glblong/1224648