首页 文章

片段之间的事务仅在一个ActionBar选项卡内

提问于
浏览
7

我有一个带有三个选项卡(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 回答

  • 6

    你没有遗漏任何东西(或者我也错过了) .

    我搜索得很长,很难找到“正确”的方法,但我找不到任何东西 . 我最终做的是编写自己的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生命周期怪癖(如方向更改) . 保留 MapStacks 以及当前选定的标签,然后在 onCreate() 中重新打开包装 . (你很容易做到 . )幸运的是你的 TabType 枚举是 Serializable 所以放入 Bundle 应该是微不足道的 .

相关问题