メインビューでさまざまなフラグメントを開くタブが下部にあるフラグメントインターフェイスがあります。
アイテムのリストである特定のフラグメントがあります。ユーザーがこのリスト内のアイテムのいずれかを選択すると、別のフラグメントが開き、前のフラグメントのリスト内のすべてのアイテム間で水平にスクロールするビューページャーが含まれます。これはうまく機能します。
ビューページャーはFragmentPagerAdapterを使用してアイテムを表示します。
ユーザーがリスト内のアイテムを選択して表示し、タブバーのボタンを押してリストに戻り、別のアイテムを選択すると、問題が発生します。アイテムが2回選択されると、ビューページャーの代わりに空白の画面が表示されます。これが発生しても、LogCatでエラーは発生しません。
ビューページャーが初めて表示されるのはなぜですか?
FragmentPagerAdapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
Cursor mCursor;
public ViewPagerAdapter(FragmentManager fm, Cursor c) {
super(fm);
mCursor = c;
}
public void changeCursor(Cursor c) {
mCursor = c;
this.notifyDataSetChanged();
}
@Override
public int getCount() {
if (mCursor == null) return 0;
else return mCursor.getCount();
}
@Override
public Fragment getItem(int position) {
mCursor.moveToPosition(position);
return TeamCardFragment.newInstance(mCursor, position);
}
}
PagerFragment:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bundle = getArguments();
mCursorPosition = bundle.getInt(TeamCardCommon.BUNDLE_KEY_CURSOR_POSITION);
View mView = inflater.inflate(R.layout.team_card_master, container, false);
mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
mAdapter = new ViewPagerAdapter(getFragmentManager(), cursor);
new setAdapterTask().execute();
return mView;
}
private class setAdapterTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
return null;
}
@Override
protected void onPostExecute(Void result) {
mViewPager.setAdapter(mAdapter);
mViewPager.setCurrentItem(mCursorPosition);
}
}
ビューページャーアイテムをフラグメントではなく標準ビューとして再実装し、それに応じてアダプターを変更することで、これを回避しました。
同じ問題がありました。 PageAdapterの親クラスをAndroid.support.v4.app.FragmentPagerAdapter
からAndroid.support.v4.app.FragmentStatePagerAdapter
に変更すると、「2回目」のViewPager
表示の問題が解決します。
親フラグメントのgetFragmentManager()
をgetChildFragmentManager()
に置き換えることでこれを解決できました。この親フラグメントは、ページング可能な(スライド可能な)フラグメントを含めるためにAndroid.support.v4.app.FragmentPagerAdapterをインスタンス化していました。コンストラクタ。このコンストラクターには、getChildFragmentManager()
の戻り値を渡しました。
hackbodのリンクはキーでした( https://developer.Android.com/about/versions/Android-4.2.html#NestedFragments )。この投稿で見つかりました Fragments within Fragments =
フラグメントをネストするには、フラグメントを追加するフラグメントで
getChildFragmentManager()
を呼び出すだけです。これは、フラグメントトランザクションを作成するためにトップレベルアクティビティから通常行うように使用できるFragmentManagerを返します。
私にとっては、ビューページャーでこれを呼び出す必要がありました:
myViewPager.setSaveFromParentEnabled(false);
ビューページャーが更新されず、フラグメントがあるはずの空白の白い画面しか表示されないという問題がありました。 getChildFragmentManagerを渡していましたが、助けにはなりませんでした。
AppBarLayoutとViewPagerでCoordinatorLayoutを使用していた特定のケースでは、それを解決したのはAppBarLayout xmlプロパティからAndroid:fitsSystemWindows = "true"を削除するでした。
理由を聞かないでください。私はそれが少しばかげているように聞こえ、それが相関関係を持たないようになっていることを知っていますが、すでにアダプターでgetChildFragmentManager()を使用していたため、この単一行だけが問題を引き起こしていました。これを見つけるためだけにコードをデバッグするのに丸1日費やしたので、誰かの時間を節約できることを願っています。
親フラグメントのFragmentPagerAdapter
からFragmentStatePagerAdapter
およびgetFragmentManager()
にアダプタをgetChildFragmentManager()
に変更したのと同じ問題がありました
この背後にある理由は、FragmentStatePagerAdapter
が多数のページを格納するのに役立ち、ページが表示されていない間はフラグメントの保存状態のみを保持するため、訪問した各ページに関連付けられたメモリが少なくなるためです。これにより、フラグメントを切り替える際のオーバーヘッドが削減されます。
setOffscreenPageLimit (int limit)
on親ViewPagerを試してください。
mViewPager.setOffscreenPageLimit(totalPages-1);
これは私にとって魅力的でした。
私の場合、TabLayout
の中にViewPager.
そして、そのフラグメント内の別のViewPager
。最初はすべて正常に動作していましたが、タブを変更して戻ると、フラグメントの一部が空白になりました。
これはあなたを助けるでしょう。
viewPager.setOffscreenPageLimit(position);
私は同じことをしていましたが、2回目にPager Adapterを呼び出すと、子ビューはNullPointerExceptionを返します。 FragmentStatePagerAdapterのアダプタを変更すると、私の問題も解決します。
FragmentPagerAdapter
をFragmentStatePagerAdapter
に変更getChildFragmentManager()
の代わりにgetFragmentManager()
を使用
getChildFragmentManager()
-ドキュメントによると、このFragment内にFragmentを配置および管理するためのプライベートFragmentManagerを返すためです。一方、getFragmentManager()
は、このアクティビティに関連付けられたフラグメントと対話するためのFragmentManagerを返します
Xamarin Androidで2回目の空白画面で同じ問題が発生していました。
viewPager.SaveFromParentEnabled = false;
アプリが最小化され、後で呼び出されたときにこのエラーが発生した場合は、アダプターを初期化することもできます。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bundle = getArguments();
mCursorPosition = bundle.getInt(TeamCardCommon.BUNDLE_KEY_CURSOR_POSITION);
View mView = inflater.inflate(R.layout.team_card_master, container, false);
mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
initViewPagerAdapter();
return mView;
}
private void initViewPagerAdapter(){
mAdapter = new ViewPagerAdapter(getFragmentManager(), cursor);
new setAdapterTask().execute();
}
@Override
public void onResume(){
super.onResume();
initViewPagerAdapter();
}