android.support.v4.view.ViewPager 如何动态更换显示内容

看一段简单的代码,在一个pager里面显示两个TextView

List<View> items = new ArrayList<View>();
adapter = new MyPagerAdapter();

			TextView tv = new TextView(getActivity());
			tv.setText("第一页");
			items.add(tv);
			tv = new TextView(getActivity());
			tv.setText("第二页");
			items.add(tv);
			pager.setAdapter(adapter);	

Adapter代码

		class MyPagerAdapter extends PagerAdapter{

			@Override
			public Object instantiateItem(ViewGroup container, int position) {
				View layout = items.get(position);
				container.addView(layout);
				return layout;
			}

			@Override
			public void destroyItem(ViewGroup container, int position, Object object) {
				View layout = items.get(position);
				container.removeView(layout);
			}

			@Override
			public boolean isViewFromObject(View arg0, Object arg1) {
				return arg0 == arg1;

			}

			@Override
			public int getCount() {
				return items.size();
			}

			@Override
			public int getItemPosition(Object object) {
				// TODO Auto-generated method stub
				return super.getItemPosition(object);
			}
		}

代码运行正常,左右滑动都OK。

好,现在需求来了,我需要把“第一页”和“第二页”干掉,再重新添加两个TextView,分别是“第三页”和“第四页”,于是按常理写了如下代码

					items.clear();
					TextView tv = new TextView(getActivity());
					tv.setText("第三页");
					items.add(tv);
					tv = new TextView(getActivity());
					tv.setText("第四页");
					items.add(tv);
					adapter.notifyDataSetChanged();

我们在使用ListView的时候,改变数据源的数据,然后通知adpater去更新,就可以正常显示,可是在ViewPager这不好使,上面代码执行后,没有任何变化

那我们想是不是ViewPager需要清一下原有的试图呢,好,再加一句

pager.removeAllViews();

再次运行,可好,一片空白,啥也没了,真干净!

蒙了吧,到底什么原因,就是getItemPosition,让我看看当ViewPager的Adapter发生变化时,到底干了啥,Adapter执行notifyDataSetChanged时,会触发ViewPager的dataSetChanged方法,下面是源码,:

    void dataSetChanged() {
        // This method only gets called if our observer is attached, so mAdapter is non-null.

        final int adapterCount = mAdapter.getCount();
        mExpectedAdapterCount = adapterCount;
        boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 &&
                mItems.size() < adapterCount;
        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);
				//看这句话,如果是PagerAdapter.POSITION_UNCHANGED标志,直接返回,不做任何处理
            if (newPos == PagerAdapter.POSITION_UNCHANGED) {
                continue;
            }
				//只有返回PagerAdapter.POSITION_NONE标志时,才会对内部视图进行调整
            if (newPos == PagerAdapter.POSITION_NONE) {
				//先从数据源中清除
                mItems.remove(i);
                i--;

                if (!isUpdating) {
                    mAdapter.startUpdate(this);
                    isUpdating = true;
                }
				//在调用Adapter的destroyItem,去销毁视图
                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, adapterCount - 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();
        }
    }

PagerAdapter.POSITION_UNCHANGED,这个标记决定着视图是否被重新创建,Apdapter默认的代码如下

    public int getItemPosition(Object object) {
        return POSITION_UNCHANGED;
    }

默认返回POSITION_UNCHANGED,所以如果你不对Adapter的getItemPosition进行重写的画,就会出现无法更改内部视图效果的问题。下面对从PagerAdapter继承的代码进行改造,加上对getItemPosition的修改,让他直接返回POSITION_NONE,POSITION_NONE每次数据发生变化,都会引起视图的重建,比较消耗内存,所以不需要变化内部视图时,避免使用。

			@Override
			public int getItemPosition(Object object) {
				// TODO Auto-generated method stub
				return POSITION_NONE;
			}

小插曲


如果返回了POSITION_NONE,但是没有pager.removeAllViews(),那么“第一页”和“第二页”没有消失,“第三页”和“第四页”也上去了,分别和前两页重合了,看图

如果返回了POSITION_UNCHANGED,但是没有pager.removeAllViews(),那么看不到任何变化。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-29 00:45:51

android.support.v4.view.ViewPager 如何动态更换显示内容的相关文章

android新手关于左右滑动的问题,布局把&lt;android.support.v4.view.ViewPager/&gt;&lt;ImageView/&gt; 放在上面就不行了。

============问题描述============ main.xml代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:umadsdk="http://schemas.android.com/apk/res/com.Love

缺少android.support.v4.jar builder path 导入 v4.jar包 Error inflating class android.support.v4.view.ViewPager

04-10 18:57:54.656: E/AndroidRuntime(6346): FATAL EXCEPTION: main04-10 18:57:54.656: E/AndroidRuntime(6346): java.lang.RuntimeException: Unable to start activity ComponentInfo{cn.learn.tabhosttest/cn.learn.tabhosttest.ViewPagerActivity}: android.view

Could not find class &#39;android.support.v4.view.ViewPager&#39;问题处理

Could not find class 'android.support.v4.view.ViewPager', referenced from method*** 而且我有引入ViewPager包,编译是不报错的,但运行时报ViewPager不存在. 解决办法: 1.既然提示工程中没有导入jar包,那么我们就手动将其导入: 右击工程选择 Bulid Path->Add Libraries->User Library->User Libraries->new(随便取一个名字,比如

找不到android.support.v4.view.ViewPager

转自http://blog.csdn.net/nj_liuzl/article/details/8825855 在加载页面xml(setContentView(R.layout.activity_main);)的时候就报错,过不去了,程序上是activity加载不上报错,采取第三种方法. 因为support v4是新添加进来的,在java build path -->order and export把v4勾上.

java.lang.NoClassDefFoundError: android.support.v4.view.ViewConfigurationCompat

Recently I am trying to run the sliding menu examples which was given in this blog: http://www.curious-creature.org/2012/12/14/android-recipe-3-sliding-menu-layers-and-filters/; 1. download library prject from github; 2. Inside the main project, righ

Robotium导入被测源码遇到问题 had used a different Landroid/support/v4/view/ViewPager

记录一下,鼓捣两天终于找到原因了,右键单击Robotium project,选择Build path->Configure Build Path..,在Libraries中删除android-support-v4.jar,问题解决. 注:即使被测源码与Robotium具有相同的jar包 -- android-support-v4.jar,Robotium也会报错.

android.support.v4.widget.DrawerLayout 抽屉效果导航菜单

抽屉效果导航菜单图示 如图所示,抽屉效果的导航菜单不用切换到另一个页面,也不用去按菜单的硬件按钮,直接在界面左上角的一个按钮点击,菜单就滑出来,而且感觉能放很多东西 概况:实现上图所示的抽屉效果的导航菜单有以下两种方式 方式1.用SlidingDrawer: http://developer.android.com/reference/android/widget/SlidingDrawer.html 但是不知道为什么这个类官方不建议再继续用了: Deprecated since API lev

android.support.v4.widget.DrawerLayout使用

activity_main.xml布局如下: <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/drawerlayout"    android:layou

Android Support v4、v7、v13的区别和应用场景

google提供了Android Support Library package 系列的包来保证来高版本sdk开发的向下兼容性,即我们用4.x开发时,在1.6等版本上,可以使用高版本的有些特性,如fragement,ViewPager等,下面,简单说明下这几个版本间的区别: Android Support v4:  这个包是为了照顾1.6及更高版本而设计的,这个包是使用最广泛的,eclipse新建工程时,都默认带有了.     Android Support v7:  这个包是为了考虑照顾2.1