片段之间的交易只有内的一个动作条选项卡 [英] Transaction between fragments only inside one ActionBar Tab

查看:88
本文介绍了片段之间的交易只有内的一个动作条选项卡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有三个选项卡(动作条的标签),每一个有一个片段在同一时间的应用程序。

TabListener

TabsActivity

TAB1 - > ListFragment1 - > ListFragment2 - > Fragment3

TAB2 - > Tab2Fragment

TAB3 - > Tab3Fragment

现在的问题是,当我创建FragmentTransaction(内OnListItemClicked)从ListFragment1到ListFragment2,其他选项卡里面的片段也更改为ListFragment2。

在最后,我想对标签和$ P $改变片段只在pserve其他标签的状态。

我已经保存状态(OnSavedInstance())。 你知道我在这里失踪了什么?

一些code:

 公共类TabsActivity延伸活动{

    @覆盖
    保护无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.tabs);

        制表符//设置操作栏
        动作条动作条= getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        //实例片段的标签
        片段networksFragment =新NetworksFragment();
        //添加一个新的选项卡并设置其标题文本和选项卡监听器
        actionBar.addTab(actionBar.newTab()的setText(TAB1)
                .setTabListener(新TabsListener(ListFragment1)));

        //实例片段的标签
        片段historyFragment =新HistoryFragment();
        //添加一个新的选项卡并设置其标题文本和选项卡监听器
        actionBar.addTab(actionBar.newTab()的setText(TAB2)
                .setTabListener(新TabsListener(Tab2Fragment)));

        //实例片段的标签
        片段settingsFragment =新SettingsFragment();
        //添加一个新的选项卡并设置其标题文本和选项卡监听器
        actionBar.addTab(actionBar.newTab()的setText(TAB3)
                .setTabListener(新TabsListener(Tab3Fragment)));
    }
}
 


 公共类TabsListener实现ActionBar.TabListener {

    私人片段FRAG;


    //调用添加新的选项卡时创建的侦听器的一个实例
    公共TabsListener(片段networksFragment){
        FRAG = networksFragment;
    }

    @覆盖
    公共无效onTabReselected(标签为arg0,FragmentTransaction ARG1){
        // TODO自动生成方法存根

    }

    @覆盖
    公共无效onTabSelected(TAB键,FragmentTransaction英尺){
        ft.add(R.id.fragment_container,FRAG,NULL);
    }

    @覆盖
    公共无效onTabUnselected(TAB键,FragmentTransaction英尺){
        ft.remove(FRAG);
    }
}
 


 公共类ListFragment1扩展ListFragment {

    @覆盖
    公共无效onListItemClick(ListView的L,视图V,INT位置,长的id){

        getListView()setItemChecked(位置,真正的)。

        ListFragment2 fragment2 = ListFragment2.newInstance(位置);

        FragmentTransaction英尺= getFragmentManager()的BeginTransaction()。
        ft.replace(R.id.fragment_container,fragment2);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        ft.addToBackStack(空);
        ft.commit();
    }
}
 

解决方案

您不会错过任何东西(或者我缺少太)。

我搜索漫长而艰难的方式做到这一点正常,但我无法找到任何东西。我最后做的是写我自己backstack逻辑。 不幸的是我的雇主拥有我的code,所以我不能共享任何逐字,但这里是我的方法:

创建一个枚举与每个标签页一个条目。让我们把它叫做 TabType 。 现在创建类型的实例变量 tabStacks 的HashMap< TabType,堆叠式和LT;字符串>> 。现在,您可以实例化一个堆栈每个选项卡 - 每个堆栈的标签列表,所指定的 Fragment.getTag()。这样,您就不必担心存储引用片段,以及是否他们会当你旋转的设备上消失。你需要一个参照片段的任何时间,抢权标记出栈,并使用 FragmentManager.findFragmentByTag()

现在,每当你想推片段到一个标签,生成一个新的标签(我用 UUID.randomUUID()的toString() ),并用它在你调用 FragmentTransaction.add()。然后按标签上的堆栈当前显示的选项卡上。

请注意:当你想推一个新片段上的一个老顶,不删除()旧,因为 FragmentManager 会考虑它了,它会被清理。请务必分离(),然后连接()后它。仅使用删除()当你永久弹出一个片段,并且只能使用添加()要显示它的第一次。

那么,你就必须要一些相对简单的逻辑添加到您的 TabListener 。当标签处于未选中状态,只需 PEEK()在它的堆栈和 detatch()相关片段。当选择了一个标签, PEEK()在顶部的的堆栈和连接()的片段。

最后,你必须处理的活动周期怪癖(如方向变化)。坚持你的地图以及当前选定的选项卡,在你的的onCreate()。 (你没有得到这个打包和拆包免费的,但它是pretty的容易做的。)幸运的是,你的 TabType 枚举序列化所以应该是微不足道的投入捆绑

I have an app with three tabs (ActionBar Tabs), each one with one fragment at a time.

TabListener

TabsActivity

Tab1 -> ListFragment1 -> ListFragment2 -> Fragment3

Tab2 -> Tab2Fragment

Tab3 -> Tab3Fragment

The problem is when I create the FragmentTransaction (inside OnListItemClicked) from ListFragment1 to ListFragment2, the fragments inside the other tabs also change to ListFragment2.

In the end, I want to change fragments only inside on tab and preserve the state of the other tabs.

I'm already saving the state (OnSavedInstance()). Do you know what I'm missing here?

Some of the code:

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();
    }
}

解决方案

You're not missing anything (or I'm missing it too).

I searched long and hard for a way to do this "properly" but I couldn't find anything. What I ended up doing is writing my own backstack logic. Unfortunately my employer owns my code so I can't share any of that verbatim, but here was my approach:

Create an enum with one entry for each of your tabs. Let's call it TabType. Now create an instance variable tabStacks of type HashMap<TabType, Stack<String>>. Now you can instantiate one stack for each tab - each stack is a list of tags, as specified by Fragment.getTag(). This way you don't have to worry about storing references to Fragments and whether they're going to disappear on you when you rotate the device. Any time you need a reference to a Fragment, grab the right tag off the stack and use FragmentManager.findFragmentByTag().

Now whenever you want to push a Fragment onto a tab, generate a new tag (I used UUID.randomUUID().toString()) and use it in your call to FragmentTransaction.add(). Then push the tag on top of the stack for the currently displayed tab.

Be careful: when you want to push a new fragment on top of an old one, don't remove() the old one, since the FragmentManager will consider it gone and it will be cleaned up. Be sure to detach() it, and then attach() it later. Only use remove() when you're permanently popping a Fragment, and only use add() the first time you want to show it.

Then, you'll have to add some relatively simple logic to your TabListener. When a tab is unselected, simply peek() at its stack and detatch() the associated Fragment. When a tab is selected, peek() at the top of that stack and attach() that fragment.

Lastly, you'll have to deal with Activity lifecycle quirks (like orientation changes). Persist your Map of Stacks as well as the currently selected tab, and unpack it again in your onCreate(). (You don't get this packing and unpacking for free, but it's pretty easy to do.) Luckily your TabType enum is Serializable so it should be trivial to put into a Bundle.

这篇关于片段之间的交易只有内的一个动作条选项卡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆