公式ブログandroid-developers.blogspot.com/2011/08/horizontal-view-swiping-with-viewpager.htmlへの投稿に触発されて、試し始めました。 タスクの本質は、メールアプリケーションのフラグメントをページの1つとして、インスタントメッセンジャーアプリケーションのフラグメントを他のページとして持つことでした。
メールアプリケーションにはいくつかのフラグメントがありますが、それらを表示するページは1つだけです。 簡単にするために、選択したフォルダー内のフォルダーと文字のリストという2つのメールフラグメントを考えます。 最初に表示されるユーザーは、フォルダーリストのフラグメントです。 特定のフォルダーを選択すると、フォルダーフラグメントは同じページ内の対応するレターフラグメントに置き換えられます。
しかし、多くのように(「アンドロイドビューページャーの置換フラグメント」をインターネットで検索する価値があります)、問題が発生しました。ViewPagerを使用すると、あるフラグメントが別のフラグメントに置き換えられませんでした。
ソリューションは次のとおりです。ViewPager、PagerAdapter、およびFragmentStatePagerAdapterのコードを互換機能パックのソースコードからプロジェクトに転送し、次の関数をViewPagerに追加します。
public void notifyItemChanged(Object oldItem, Object newItem) { if (mItems != null) { for (ItemInfo itemInfo : mItems) { if (itemInfo.object.equals(oldItem)) { itemInfo.object = newItem; } } } invalidate(); }
そして、FragmentStatePagerAdapterに以下を追加します。
public void replaceFragmetns(ViewPager container, Fragment oldFragment, Fragment newFragment) { // ensure getItem returns newFragemtn after calling handleGetItemInbalidated() handleGetItemInbalidated(container, oldFragment, newFragment); startUpdate(container); // remove old fragment if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } int position = getFragmentPosition(oldFragment); while (mSavedState.size() <= position) { mSavedState.add(null); } mSavedState.set(position, null); mFragments.set(position, null); mCurTransaction.remove(oldFragment); // add new fragment while (mFragments.size() <= position) { mFragments.add(null); } mFragments.set(position, newFragment); mCurTransaction.add(container.getId(), newFragment); finishUpdate(container); container.notifyItemChanged(oldFragment, newFragment); } protected abstract void handleGetItemInbalidated(View container, Fragment oldFragment, Fragment newFragment); protected abstract int getFragmentPosition(Fragment fragment);
handleGetItemInbalidated()関数は、FragmentStatePagerAdapterから継承したクラスに実装されます。 これを呼び出した後、FragmentStatePagerAdapter .getItem()関数はnewFragmentを返す必要があります。 getFragmentPosition()も継承クラスに実装され、ページのリスト内のフラグメントのインデックスを返します。
フラグメントの置換は次のように行われます。
mAdapter.replaceFragmetns(mViewPager, oldFragment, newFragment);
FragmentStatePagerAdapterが現在のページから1つ以上の位置にある(「fragmentTransaction.remove())」ページを「アンロード」するという事実に注目します。 私のアプリケーションでは、スクロール時にメールフラグメントのあるページをアンロードしないでください。
これを行うには、FragmentStatePagerAdapterクラスの2つの関数をオーバーライドします。
@Override public Object instantiateItem(View container, int position) { if (position == getCount() - 1) { if (mMailCahcedFragment == null) { return super.instantiateItem(container, position); } else { return mMailCahcedFragment; } } else { return super.instantiateItem(container, position); } } @Override public void destroyItem(View container, int position, Object object) { if (position == getCount() - 1) { } else { super.destroyItem(container, position, object); } }
条件(位置== getCount()-1)は、メールフラグメントのあるページが常に最後であるためです。
Eclipseでテストプロジェクトをダウンロードします: files.mail.ru/I72IP7