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{@Overridepublic Object instantiateItem(ViewGroup container, int position) {View layout = items.get(position);container.addView(layout);return layout;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {View layout = items.get(position);container.removeView(layout);}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}@Overridepublic int getCount() {return items.size();}@Overridepublic int getItemPosition(Object object) {// TODO Auto-generated method stubreturn 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 rangenewCurrItem = 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每次数据发生变化,都会引起视图的重建,比较消耗内存,所以不需要变化内部视图时,避免使用。

@Overridepublic int getItemPosition(Object object) {// TODO Auto-generated method stubreturn POSITION_NONE;}小插曲

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

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

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

地球仍然转重,世间依旧善变,而我永远爱你。

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

相关文章:

你感兴趣的文章:

标签云: