0

私のアプリには SlidingMenu があり、メニューの各項目は新しい SherlockFragment です。ほとんどは単純な 1 ペインのフラグメントですが、2 ペインにする必要があるフラグメントで問題が発生しています。ActionBar Tabs を備えた ViewPager を使用して実装することにしました。

ViewPager には、CustomerFragment (顧客のリスト) と CartFragment (カート項目のグリッドで、選択した顧客の名前を表示する TextView が上部にある) の 2 つのページがあります。ユーザーが人の名前をクリックすると、ViewPager がページをめくって名前を表示します。すべてが親フラグメントに含まれているため、ViewPager を実装する最善の方法は、ChildFragmentManager を使用することであると判断しました。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mViewPager = new ViewPager(activity);
    mViewPager.setId(1);
    v = mViewPager;
    fm = getChildFragmentManager();

    custFrag = CashRegisterCustomerFragment.newInstance();
    cartFrag = CashRegisterCartFragment.newInstance();

    fm.beginTransaction().add(mViewPager.getId(), custFrag).commitAllowingStateLoss();
    fm.beginTransaction().add(mViewPager.getId(), cartFrag).commitAllowingStateLoss();

    mActionBar = activity.getSupportActionBar();
    mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    mTabsAdapter = new CashRegisterTabsAdapter(activity, mViewPager);
    mTabsAdapter.addTab(mActionBar.newTab().setText(activity.getResources().getString(R.string.customer_list)), 
        custFrag);
    mTabsAdapter.addTab(mActionBar.newTab().setText(activity.getResources().getString(R.string.items)), 
        cartFrag);

    if (savedInstanceState != null) {
        mActionBar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
    } else {
        mActionBar.setSelectedNavigationItem(0);
    }

    return v;
}

CashRegisterTabsAdapter の重要な部分:

public CashRegisterTabsAdapter(MyActivity act, ViewPager pager) {
    super(act.getSupportFragmentManager());
    activity = act;
    mActionBar = activity.getSupportActionBar();
    mActionBar.setTitle(R.string.cash_register);
    mViewPager = pager;
    mViewPager.setAdapter(this);
    mViewPager.setOnPageChangeListener(this);
}

public void addTab(ActionBar.Tab tab, BaseFragment frag) {
    tab.setTabListener(this);
    mTabs.add(frag);
    mActionBar.addTab(tab);
    notifyDataSetChanged();
}

@Override
public int getCount() {
    return mTabs.size();
}

@Override
public Fragment getItem(int position) {
    return mTabs.get(position);
}

@Override
public void onPageSelected(int position) {
    mActionBar.setSelectedNavigationItem(position);

    if (position == 1)
        activity.getSlidingMenu().setSlidingEnabled(false);
    else
        activity.getSlidingMenu().setSlidingEnabled(true);
}

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {        
    int pos = tab.getPosition();
    if (mViewPager != null) {
        mViewPager.setCurrentItem(pos);
    }
}

すべてがうまく機能します。ただし、 SlidingMenu を介してフラグメントを切り替えてからホームボタンを押して、アプリをバックグラウンドに送信すると、次のようになります。

07-02 18:04:31.170: E/AndroidRuntime(32619): FATAL EXCEPTION: main
07-02 18:04:31.170: E/AndroidRuntime(32619): java.lang.IllegalStateException: Failure saving state: active CashRegisterCustomerFragment{41a8f1a0} has cleared index: -1
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1700)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:527)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at com.actionbarsherlock.app.SherlockFragmentActivity.onSaveInstanceState(SherlockFragmentActivity.java:127)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity.onSaveInstanceState(SlidingFragmentActivity.java:50)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at com.mycom.myapp.MyActivity.onSaveInstanceState(MyActivity.java:128)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at com.mycom.myapp.MainFragmentContainer.onSaveInstanceState(MainFragmentContainer.java:124)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.app.Activity.performSaveInstanceState(Activity.java:1137)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1215)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3077)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3136)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.app.ActivityThread.access$900(ActivityThread.java:142)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1235)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.os.Handler.dispatchMessage(Handler.java:99)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.os.Looper.loop(Looper.java:137)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at android.app.ActivityThread.main(ActivityThread.java:4931)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at java.lang.reflect.Method.invokeNative(Native Method)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at java.lang.reflect.Method.invoke(Method.java:511)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
07-02 18:04:31.170: E/AndroidRuntime(32619):    at dalvik.system.NativeStart.main(Native Method)

奇妙なことに、CashRegister 親フラグメントのホーム ボタンを押してもクラッシュせず、最初に別の親フラグメントに移動したときにのみこの例外がスローされます。

このサイトでは、許可されていないときに FragmentManager がトランザクションを実行しようとしていると書かれていますが、それがどこにあるのかわかりません。onCreateView() で fm.beginTransaction.add() 呼び出しを削除すると、このエラーは発生しませんが、インターフェイス呼び出しで参照する親フラグメントがないため、フラグメント間で通信できません。

4

1 に答える 1

2

これは、これを行うべき方法ではありません。ViewPager を使用する場合は、ViewPager#setPagerAdapter(); を呼び出す必要があります。あなたの場合、このアダプターは getChildFragmentManager() の結果で構築された FragmentPagerAdapter から拡張されます。

このコードはあなたのために仕事をするはずです。

// Add this to a files in your res\values folder <item type="id" name="view_pager" />
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mViewPager = new ViewPager(activity);
    mViewPager.setId(R.id.view_pager);

    v = mViewPager;

    fm = getChildFragmentManager();

    custFrag = fm.findFragmentByTag(makeFragmentName(mViewPager.getId(), 0));
    if(custFrag == null) {
        custFrag = CashRegisterCustomerFragment.newInstance();
    }

    cartFrag = fm.findFragmentByTag(makeFragmentName(mViewPager.getId(), 1));
    if(cartFrag == null) {
        cartFrag = CashRegisterCartFragment.newInstance();
    }

    mViewPager.setPagerAdapter(new FragmentPagerAdapter(fm) {
        @Override
        public Fragment getItem(int position) {
            switch(position) {
                case 0:  return custFrag;
                case 1:  return cartFrag;
                default: return null;
            }
        }
        @Override
        public int getCount() {
            return 2;
        }
    });

    mActionBar = activity.getSupportActionBar();
    mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    mActionBar.removeAllTabs();
    mActionBar.addTab(mActionBar.newTab().setText(getString(
        R.string.customer_list).setTabListener(mTabListener));
    mActionBar.addTab(mActionBar.newTab().setText(getString(
        R.string.items).setTabListener(mTabListener));

    int selectedTab = 0;
    if (savedInstanceState != null) {
        selectedTab = savedInstanceState.getInt("tab", 0);
    }
    mActionBar.setSelectedNavigationItem(selectedTab);

    return v;
}

// Very important.. this matches FragmentPagerAdapter code
private static String makeFragmentName(int viewId, long id) {
    return "android:switcher:" + viewId + ":" + id;
}

private ActionBar.TabListener mTabListener = new ActionBar.TabListener() {
    void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        mViewPager.setCurrentItem(tab.getPosition());
    }
    void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
    }
    void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
    }
};
于 2013-07-03T12:35:17.157 に答える