web-dev-qa-db-ja.com

FragmentPagerAdapterを使用したViewPagerのフラグメントは、2回目に表示されるときに空白になります

メインビューでさまざまなフラグメントを開くタブが下部にあるフラグメントインターフェイスがあります。

アイテムのリストである特定のフラグメントがあります。ユーザーがこのリスト内のアイテムのいずれかを選択すると、別のフラグメントが開き、前のフラグメントのリスト内のすべてのアイテム間で水平にスクロールするビューページャーが含まれます。これはうまく機能します。

ビューページャーは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);
    }
}
96
howettl

ビューページャーアイテムをフラグメントではなく標準ビューとして再実装し、それに応じてアダプターを変更することで、これを回避しました。

1
howettl

同じ問題がありました。 PageAdapterの親クラスをAndroid.support.v4.app.FragmentPagerAdapterからAndroid.support.v4.app.FragmentStatePagerAdapterに変更すると、「2回目」のViewPager表示の問題が解決します。

215
Yann

親フラグメントの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を返します。

84
Daniel F

私にとっては、ビューページャーでこれを呼び出す必要がありました:

myViewPager.setSaveFromParentEnabled(false);

ビューページャーが更新されず、フラグメントがあるはずの空白の白い画面しか表示されないという問題がありました。 getChildFragmentManagerを渡していましたが、助けにはなりませんでした。

15
j2emanue

AppBarLayoutとViewPagerでCoordinatorLayoutを使用していた特定のケースでは、それを解決したのはAppBarLayout xmlプロパティからAndroid:fitsSystemWindows = "true"を削除するでした。

理由を聞かないでください。私はそれが少しばかげているように聞こえ、それが相関関係を持たないようになっていることを知っていますが、すでにアダプターでgetChildFragmentManager()を使用していたため、この単一行だけが問題を引き起こしていました。これを見つけるためだけにコードをデバッグするのに丸1日費やしたので、誰かの時間を節約できることを願っています。

10
emirua

親フラグメントのFragmentPagerAdapterからFragmentStatePagerAdapterおよびgetFragmentManager()にアダプタをgetChildFragmentManager()に変更したのと同じ問題がありました

この背後にある理由は、FragmentStatePagerAdapterが多数のページを格納するのに役立ち、ページが表示されていない間はフラグメントの保存状態のみを保持するため、訪問した各ページに関連付けられたメモリが少なくなるためです。これにより、フラグメントを切り替える際のオーバーヘッドが削減されます。

8
Yashaswi N P

setOffscreenPageLimit (int limit) on親ViewPagerを試してください。

mViewPager.setOffscreenPageLimit(totalPages-1);

これは私にとって魅力的でした。

私の場合、TabLayoutの中にViewPager.

そして、そのフラグメント内の別のViewPager。最初はすべて正常に動作していましたが、タブを変更して戻ると、フラグメントの一部が空白になりました。

2
Rumit Patel

これはあなたを助けるでしょう。

    viewPager.setOffscreenPageLimit(position);
2
Pardeep Singh

私は同じことをしていましたが、2回目にPager Adapterを呼び出すと、子ビューはNullPointerExceptionを返します。 FragmentStatePagerAdapterのアダプタを変更すると、私の問題も解決します。

0
Arka-57

FragmentPagerAdapterFragmentStatePagerAdapterに変更getChildFragmentManager()の代わりにgetFragmentManager()を使用

getChildFragmentManager()-ドキュメントによると、このFragment内にFragmentを配置および管理するためのプライベートFragmentManagerを返すためです。一方、getFragmentManager()は、このアクティビティに関連付けられたフラグメントと対話するためのFragmentManagerを返します

0
Mostafa Anter

Xamarin Androidで2回目の空白画面で同じ問題が発生していました。

viewPager.SaveFromParentEnabled = false;
0
Gerard

アプリが最小化され、後で呼び出されたときにこのエラーが発生した場合は、アダプターを初期化することもできます。

@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();
}
0
Patrick