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


98

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

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

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

回答:


221

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


2
冗談じゃない?このコードはもうありません。それ以外の場合はテストします。おそらく、この答えは誰かを助けるでしょう。
howettl

10
なんてやつだ!私はこのソリューションを何日も探していました!トンマンのおかげで、魅力のように機能します。しかし、私の開発者は、その変更がどのような影響を与えるかを尋ねていますか?つまり、以前は機能しなかった理由と、StatePagerAdapterの理由
Anand Sainath 2013年

1
@Override public int getItemPosition(Object object){return POSITION_NONE;も必要です。}
Helin Wang 2013

1
私も働いた。こちらがリンクです。それはすべての違いを生むフラグメントの状態を保存するようです。developer.android.com/reference/android/support/v4/app/...
Tjaart

1
これは偶然ですが、正しい答えは@Daniel Fの答えです。とにかく、ここでのコメンターの便宜のために、との違いFragmentPagerAdapterとは、FragmentStatePagerAdapter前者がでより多くのいくつかのページに適している、それは後者がより多くのに適している間にこのように、ページスイッチで最高のパフォーマンスを持つメモリ内のフラグメントの全てを保持しますページ、フラグメントのみを破棄し、状態のみを維持します。メモリ効率は向上しますが、ページ切り替えが少し遅くなります。
クリスティーナ

87

これを親フラグメントで置き換えることでなんとか解決getFragmentManager()getChildFragmentManager()ました。この親フラグメントは、ページング可能な(スライド可能な)フラグメントを含めるためにandroid.support.v4.app.FragmentPagerAdapterをインスタンス化していました。これには、コンストラクターにフラグメントマネージャーが必要です。このコンストラクタにの戻り値を渡しましたgetChildFragmentManager()

hackbodのリンクがキーでした(https://developer.android.com/about/versions/android-4.2.html#NestedFragments)、これはこの投稿で見つかりましたFragments内のFragments

フラグメントをネストするには、フラグメントgetChildFragmentManager()を追加するフラグメントを呼び出すだけです。これにより、フラグメントトランザクションを作成するためにトップレベルのアクティビティから通常行うように使用できるFragmentManagerが返されます。


ありがとう...フラグメントページラダプターを含むonresume()の後にスライディングタブビューを再インスタンス化しようとして同様の問題がありました...私が使用したチュートリアルは2016年のものであり、それをフラグメントステートページラダプターに変更してそれを取得する必要がありました作業。なぜか知りたい。
Nerdy Bunz、2016年

この答えは私の時間の多くを節約しました。使用FragmentStatePagerAdapterするだけではここで尋ねられた質問を解決しないからです。と一緒FragmentStatePagerAdapterに親フラグメントYourAdapter adapter = new YourAdapter (getChildFragmentManager()); を追加する必要があります
MMK

17

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

myViewPager.setSaveFromParentEnabled(false);

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


1
なぜ世界でこれが機能したのですか?これで問題は解決しましたが、理由はわかりません。
ClayHerendeen 2017年

コードから削除しました。フラグメントマネージャーが問題の原因でした。getchildfragmentmanagerとgetfragmentmanagerを切り替えてみてください
j2emanue

私はすでにそれを試しました。タブを入れ子にして、スワイプを無効にしたViewPagersを使用しています。私はこれが貧弱なデザインであることを知っていますが、クライアントは私のものではありません。最上位のタブバーにchildFragmentManagerを使用しています。下位レベルのタブバー/ビューページャーを切り替えても問題は解決しなかったようです。それが機能しているので、今のところはsetSaveFromParentEnabled(false)を使い続けると思います。
ClayHerendeen 2017年

あなたは、最新のサポートライブラリを使用している
j2emanue

2
私は過去2日間から同じ問題に直面していました。あなたの解決策は私のために働きました。ありがとう!
brijexecon

11

AppBarLayoutとViewPagerでCoordinatorLayoutを使用していた非常に特殊なケースでは、AppBarLayout xmlプロパティからandroid:fitsSystemWindows = "true"を削除することで解決しました。

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


3
ああ、私はこの問題で降伏するところだった。あなたは私のすごい日を作りました!Geez Google、WTFはAppBarLayoutに問題がありますか?私はほぼ100ページを調べ、何時間もかけてこの問題を解決するために運が悪ければデバッグに費やしました。私は最終的にあなたのコメントで問題を解決することができて本当に感謝しています。どうもありがとう!PS:私は、私もAOSPで問題を作成したように必死だった:code.google.com/p/android/issues/...の XD
ギエムロカ

ヒントをありがとう。少なくともそれは私たちが問題を解決するのに役立ちました。今私たちはそれをフルスクリーンにするためのオプションを見つけようとしています
Paresh Mayani

あなたは命の恩人です!なぜこの問題が発生したのか、そしてそれが機能した理由がまったくわかりませんでした。
ナンドゥ

10

私はからアダプタを変更した同じ問題だったFragmentPagerAdapterFragmentStatePagerAdaptergetFragmentManager()、親断片中をgetChildFragmentManager()

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


4

親ViewPagerを配置setOffscreenPageLimit (int limit)してみてください

mViewPager.setOffscreenPageLimit(totalPages-1);

これは魅力のように私のために働いた。

私の場合、内部TabLayoutにフラグメントがありましたViewPager.

そしてViewPager、その断片の中にもう一つ。最初はすべて正常に機能していましたが、タブを変更して戻ると、フラグメントの一部が空白になりました。


1
いい答えだ。それは私を助けてくれます。
Thirumalvalavan


1

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


isViewFromObject(View view、Object object)関数を削除してみてください
Mina Samy

より良い方法があるはずです....:/私がAndroidを掘り下げるほど、成熟していないことに気づきます。
StackOverflowed

1
ネストされたフラグメントはサポートされていないため、標準ビューで再実装することをお勧めします。
Sylphe、2012

私は同様の問題で苦労しています。FragmentAdapterの代わりにPagerAdapterを使用してみましたが、それでも同じ問題が発生します。私を助けてください !
Gaurav Arora 2013年

:あなたは、ネストされた断片を使用したい場合は、私はこの答えで提供アダプターを使用することができますstackoverflow.com/questions/7700226/...
Slickelito

1

Xamarin Androidで2回目に空白の画面で同じ問題が発生しました。次の設定で解決しました。

viewPager.SaveFromParentEnabled = false;

0

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

@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

同じことがありましたが、2回目にポケットベルアダプターを呼び出すと、子ビューがNullPointerExceptionを返します。また、FragmentStatePagerAdapterのアダプターを変更すると、私の問題も解決します。


0

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

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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.