我有一个带有三个选项卡(ActionBar选项卡)的应用程序,每个选项卡一次只有一个片段 .
TabListener
TabsActivity
Tab1 - > ListFragment1 - > ListFragment2 - > Fragment3
Tab2 - > Tab2Fragment
Tab3 - > Tab3Fragment
问题是当我从ListFragment1到ListFragment2创建FragmentTransaction(在OnListItemClicked内)时,其他选项卡中的片段也会更改为ListFragment2 .
最后,我想仅在选项卡内更改片段并保留其他选项卡的状态 .
我已经保存了状态(OnSavedInstance()) . 你知道我在这里缺少什么吗?
一些代码:
public class TabsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs);
// setup Action Bar for tabs
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// instantiate fragment for the tab
Fragment networksFragment = new NetworksFragment();
// add a new tab and set its title text and tab listener
actionBar.addTab(actionBar.newTab().setText("Tab1")
.setTabListener(new TabsListener(ListFragment1)));
// instantiate fragment for the tab
Fragment historyFragment = new HistoryFragment();
// add a new tab and set its title text and tab listener
actionBar.addTab(actionBar.newTab().setText("Tab2")
.setTabListener(new TabsListener(Tab2Fragment)));
// instantiate fragment for the tab
Fragment settingsFragment = new SettingsFragment();
// add a new tab and set its title text and tab listener
actionBar.addTab(actionBar.newTab().setText("Tab3")
.setTabListener(new TabsListener(Tab3Fragment)));
}
}
public class TabsListener implements ActionBar.TabListener {
private Fragment frag;
// Called to create an instance of the listener when adding a new tab
public TabsListener(Fragment networksFragment) {
frag = networksFragment;
}
@Override
public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(R.id.fragment_container, frag, null);
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(frag);
}
}
public class ListFragment1 extends ListFragment {
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
getListView().setItemChecked(position, true);
ListFragment2 fragment2 = ListFragment2.newInstance(position);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, fragment2);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
}
}
1 回答
你没有遗漏任何东西(或者我也错过了) .
我搜索得很长,很难找到“正确”的方法,但我找不到任何东西 . 我最终做的是编写自己的backstack逻辑 . 不幸的是,我的雇主拥有我的代码所以我不能逐字分享,但这是我的方法:
为每个选项卡创建一个带有一个条目的
enum
. 我们称之为TabType
. 现在创建HashMap<TabType, Stack<String>>
类型的实例变量tabStacks
. 现在,您可以为每个选项卡实例化一个堆栈 - 每个堆栈都是一个标记列表,由Fragment.getTag()
指定 . 这样您就不必担心存储对Fragments
的引用以及它们在您旋转设备时是否会消失 . 每当您需要引用Fragment
时,从堆栈中抓取正确的标记并使用FragmentManager.findFragmentByTag()
.现在,只要您想将
Fragment
推到选项卡上,生成一个新标签(我使用UUID.randomUUID().toString()
)并在调用FragmentTransaction.add()
时使用它 . 然后将标签推到堆栈顶部,以显示当前显示的选项卡 .Be careful: 当你想在一个旧片段之上推一个新片段时,不要
remove()
旧片段,因为FragmentManager
会认为它消失了,它将被清除 . 一定要detach()
,然后再attach()
. 只有在永久弹出Fragment
时才使用remove()
,并且只在第一次显示时才使用add()
.然后,您将不得不为
TabListener
添加一些相对简单的逻辑 . 取消选中选项卡时,只需在其堆栈peek()
和detatch()
关联的片段 . 选中选项卡时,该堆栈顶部的peek()
和该片段的attach()
.最后,您将不得不处理Activity生命周期怪癖(如方向更改) . 保留
Map
的Stacks
以及当前选定的标签,然后在onCreate()
中重新打开包装 . (你很容易做到 . )幸运的是你的TabType
枚举是Serializable
所以放入Bundle
应该是微不足道的 .