web-dev-qa-db-ja.com

フラグメント内のViewPager、状態を保持する方法は?

私のアプリケーションでは、フラグメントアクティビティはフラグメントAとフラグメントBの2つのフラグメントを保持します。フラグメントBは、3つのフラグメントを含むビューページャーです。

enter image description here

私のアクティビティでは、構成の変更時にフラグメントが再作成されないようにするには、次のようにします。

if(getSupportFragmentManager().findFragmentByTag(MAIN_TAB_FRAGMENT) == null) {
    getSupportFragmentManager().beginTransaction().replace(R.id.container, new MainTabFragment(), MAIN_TAB_FRAGMENT).commit();
}

フラグメントBのコード:

public class MainTabFragment extends Fragment {

    private PagerSlidingTabStrip mSlidingTabLayout;
    private LfPagerAdapter adapter;
    private ViewPager mViewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {

        this.adapter = new LfPagerAdapter(getChildFragmentManager());

        this.mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
        this.mViewPager.setAdapter(adapter);

        this.mSlidingTabLayout = (PagerSlidingTabStrip) view.findViewById(R.id.sliding_tabs);
        this.mSlidingTabLayout.setViewPager(this.mViewPager);
    }
}

アダプターのコード:

public class LfPagerAdapter extends FragmentPagerAdapter {

    private static final int NUM_ITEMS = 3;

    private FragmentManager fragmentManager;

    public LfPagerAdapter(FragmentManager fm) {
        super(fm);
        this.fragmentManager = fm;
    }

    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    @Override
    public Fragment getItem(int position) {
        Log.d("TEST","TEST");
        switch (position) {
            case 1:
                return FragmentC.newInstance();
            case 2:
                return FragmentD.newInstance();
            default:
                return FragmentE.newInstance();
        }
    }
}

私の問題は、ビューページャーの状態を保持できず、方向の変更時にその子がフラグメント化することです。

明らかに、これはすべてのローテーションで呼び出されます。

this.adapter = new LfPagerAdapter(getChildFragmentManager());

ポケットベル全体が再作成されますよね?結果として

getItem(int position)

すべてのローテーションで呼び出され、フラグメントは最初から作成され、状態が失われます。

return FragmentC.newInstance();

私はこれを次のように解決してみました:

if(this.adapter == null)
    this.adapter = new LfPagerAdapter(getChildFragmentManager());

onViewCreatedにありますが、結果として、ローテーション時にページャー内のフラグメントが削除されました。

ページャー内の状態を正しく保持する方法はありますか?

12
Upvote

この問題を解決するには、次の2つのことを行う必要があります。

1)onCreateをインスタンス化するには、onViewCreatedの代わりにLfPagerAdapterメソッドを使用する必要があります。

つまり:

    public class MainTabFragment extends Fragment {

    private PagerSlidingTabStrip mSlidingTabLayout;
    private LfPagerAdapter adapter;
    private ViewPager mViewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        this.adapter = new LfPagerAdapter(getChildFragmentManager());
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {


        this.mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
        this.mViewPager.setAdapter(adapter);

        this.mSlidingTabLayout = (PagerSlidingTabStrip) view.findViewById(R.id.sliding_tabs);
        this.mSlidingTabLayout.setViewPager(this.mViewPager);
    }
}

2)FragmentStatePagerAdapterの代わりにFragmentPagerAdapterを拡張する必要があります

27
Mehul Joisar

Androidは、マニフェストにこの行_Android:configChanges="keyboardHidden|orientation|screenSize"_がない構成でアクティビティを自動的に再作成するため、onConfigurationの変更を自分で処理できます。

その場合の唯一の方法は、activityFragementを使用してviewPagerの状態(たとえば現在の位置)を保存することと、データを保存する必要があるフラグメントの両方でonSaveInstanceState()を使用することです。

ビューページャーの現在の位置を保存して復元する方法の例onConfiguration change

_    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
            int position = mViewPager.getCurrentItem();
            outState.Int("Key", position );
    }

    @Override //then restore in on onCreate();
    public void onCreated(Bundle savedInstanceState) {
        super.onCreated(savedInstanceState);
        // do stuff
        if (savedInstanceState != null) {
              int  position= savedInstanceState.getInt("Key");
            mViewPager.setCurrentItem(position)
        }
    }
_

もちろん、これは非常に基本的な例です。

PS:フラグメントで復元するには、onCreate()メソッドの代わりにonActivityCreated()を使用します。

状態を保持する方法の別の例を次に示します: クリックしてください!

1
murielK