我的应用有一个SlidingMenu,菜单中的每个项目都是一个新的SherlockFragment。大多数是简单的单窗格片段,但我遇到的问题应该是双窗格。我决定使用带有ActionBar Tabs的ViewPager来实现它。
ViewPager有两个页面,CustomerFragment(客户列表)和CartFragment(购物车项目网格,顶部有TextView,用于显示所选客户的名称)。当用户单击某人的姓名时,ViewPager将翻页并显示该名称。由于它全部包含在父片段中,因此我决定使用ChildFragmentManager实现ViewPager的最佳方法是:
@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父片段上的主页按钮时它不会崩溃,它只会在我第一次转到不同的父片段时抛出此异常。
This site表示FragmentManager在不允许的情况下尝试进行交易,但我无法找到可能的位置。当我删除onCreateView()中的fm.beginTransaction.add()调用时,它不会给出此错误,但是我无法在片段之间进行通信,因为在接口调用中没有要引用的父片段。 / p>
答案 0 :(得分:2)
这不是你应该怎么做的。如果你想使用ViewPager,你需要调用ViewPager#setPagerAdapter();在你的情况下,这个适配器将从FragmentPagerAdapter扩展,它使用getChildFragmentManager()结果构建。
此代码应该为您完成工作。
// 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) {
}
};