Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android.support.v4.view.ViewPager 如何動態更換顯示內容

android.support.v4.view.ViewPager 如何動態更換顯示內容

編輯:關於Android編程

看一段簡單的代碼,在一個pager裡面顯示兩個TextView

 

List items = new ArrayList();
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(),那麼看不到任何變化。


 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved