定制返回堆栈的每一个片段TabHost Android中 [英] Custom Back Stack for each Fragment in TabHost in Android

查看:115
本文介绍了定制返回堆栈的每一个片段TabHost Android中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于TabActivity是德precated我试图用已在开发​​Android的网站已经述及片段取代。但正如你们已经知道有关于与片段更换标签,因为只会有一个活动,这是片段活动的问题,也没有后退堆栈的每个片段,正如你可以在对方看到如此问题最开发商都在说,你需要管理自己的自定义回栈作为解决方案。

Since the TabActivity is deprecated I tried to replace it with Fragments which has been already mentioned in developer android website. But as you guys already know there was an issue about replacing tabs with fragments, since there will be only one activity ,which is Fragment Activity, there is no back stack for each of the fragments and as you can see in the other SO questions most of the developers were saying that you need to manage your own custom back stack as a solution.

我已经建立并实施了自己的自定义回堆栈下面你可以看到,它的工作原理完美的,我可以在每个标签跟踪每个片段。

I have created and implemented my own custom back stack as you can see below, it works perfect I can track each fragment in each tab.

TAB1

    Fragment1 > Fragment2 > Fragment3

TAB2

Tab2

    Fragment5 > Fragment6

根据导航上面,如果我从片段1至片段3,之后浏览如果我更改选项卡,TAB2并回到TAB1,我仍然可以看到Fragment3,我甚至可以导航回片段1与我的自定义回堆栈。

According to navigation above, if I navigate from Fragment1 through Fragment 3 and After that If I change the tab to Tab2 to and come back to Tab1, I can still see the Fragment3 and I can even navigate back to Fragment1 with my custom back stack.

但问题是,当我回来TAB1,看到了Fragment3,该Fragment3重新创建,我无法看到的变化,因为我留下之前,我改变标签,TAB2。

But the issue is, When I come back to Tab1 and see the Fragment3, the Fragment3 is re-created and I can not see the changes as I left behind before I change the tab to Tab2.

下面是我的自定义回堆栈;

Here is my Custom back stack;

public static HashMap<String, Stack<Fragment>> customBackStack;

public static Stack<Fragment> simpleStack;
public static Stack<Fragment> contactStack;
public static Stack<Fragment> customStack;
public static Stack<Fragment> throttleStack;
public static Stack<Fragment> homeStack;

customBackStack = new HashMap<String, Stack<Fragment>>();

homeStack = new Stack<Fragment>();
simpleStack = new Stack<Fragment>();
contactStack = new Stack<Fragment>();
customStack = new Stack<Fragment>();
throttleStack = new Stack<Fragment>();

customBackStack.put("home", homeStack);
customBackStack.put("simple", simpleStack);
customBackStack.put("contacts", contactStack);
customBackStack.put("custom", customStack);
customBackStack.put("throttle", throttleStack);

这里是onTabChanged方法;

And here is onTabChanged method;

        public void onTabChanged(String tabId) {
        TabInfo newTab = mTabs.get(tabId);
        if (mLastTab != newTab) {
            FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
            if (mLastTab != null) {
                if (mLastTab.fragment != null) {
                    ft.detach(mLastTab.fragment);
                }
            }
            if (newTab != null) {
                if (newTab.fragment == null) {
                    if (!customBackStack.get(tabId).isEmpty()) {
                        Fragment fragment = customBackStack.get(tabId).pop();
                        customBackStack.get(tabId).push(fragment);
                        ft.replace(mContainerId, fragment);
                    }
                } else {
                    if (!customBackStack.get(tabId).isEmpty()) {
                        Fragment fragment = customBackStack.get(tabId).pop();
                        customBackStack.get(tabId).push(fragment);
                        ft.replace(mContainerId, fragment);
                    }
                }
            }

            mLastTab = newTab;
            ft.commit();
            mActivity.getSupportFragmentManager().executePendingTransactions();
        }
    }

这里是onBack pressed;

And here is onBackPressed;

    public void onBackPressed() {

    Stack<Fragment> stack = customBackStack.get(mTabHost.getCurrentTabTag());

    if (stack.isEmpty()) {
        super.onBackPressed();
    } else {

        Fragment fragment = stack.pop();

        if (fragment.isVisible()) {
            if (stack.isEmpty()) {
                super.onBackPressed();
            } else {
                Fragment frg = stack.pop();
                customBackStack.get(mTabHost.getCurrentTabTag()).push(frg);

                transaction = getSupportFragmentManager().beginTransaction();
                transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right,
                        R.anim.slide_in_right, R.anim.slide_out_left);

                transaction.replace(R.id.realtabcontent, frg).commit();
            }
        } else {
            getSupportFragmentManager().beginTransaction().replace(R.id.realtabcontent, fragment).commit();
        }
    }

}

其结果是,客户后方堆工作正常除最后片断改变的标签是越来越回来的标签后重新创建之前,其不恢复如像在标签活性

As a result, custom back stack works fine except the last fragment before changing the tab is getting re-created after coming back to the tab, its not resuming as like in tab activity.

不知道如何解决呢?

修改

您可以在这里找到我的示例应用程序对于这个问题的解决方案。

You can find my sample Application here as a solution regarding to this issue.

GitHub上

推荐答案

我修改了Google的样品tablistener到以下内容:

I modified googles sample tablistener to following:

public static class TabListener<T extends SherlockFragment> implements ActionBar.TabListener {
    private final SherlockFragmentActivity mActivity;
    private final String mTag;
    private final Class<T> mClass;
    private final Bundle mArgs;
    public SherlockFragment mFragment;
    private final Stack<SherlockFragment> mStack;

    public TabListener(SherlockFragmentActivity activity, String tag, Class<T> clz) {
        this(activity, tag, clz, null, null);
    }

    public TabListener(SherlockFragmentActivity activity, String tag, Class<T> clz, Bundle args, Stack<SherlockFragment> stack) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
        mArgs = args;
        mStack = stack;

        // Check to see if we already have a fragment for this tab, probably
        // from a previously saved state.  If so, deactivate it, because our
        // initial state is that a tab isn't shown.
        mFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag);
        if (mFragment != null && !mFragment.isDetached()) {
            FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
            ft.detach(mFragment);
            ft.commit();
        }
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // we need to reattach ALL fragments thats in the custom stack, if we don't we'll have problems with setCustomAnimation for fragments.
        if (mFragment == null) {
            mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName(), mArgs);
            ft.replace(android.R.id.content, mFragment, mTag);
        } else {
            ft.attach(mFragment);
        }
        if(mStack != null) {
            for(SherlockFragment fragment: mStack) {
                ft.attach(fragment);
            }
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            ft.detach(mFragment);
        }
        if(mStack != null) {
            for(SherlockFragment fragment: mStack) {
                if(fragment!= null && !fragment.isDetached()) {
                    ft.detach(fragment);
                }
            }
        }
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }
}

和活动的onkeydown梅索德我重写为以下内容:

And the activity onKeyDown methode I override to following:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        int index = getSupportActionBar().getSelectedNavigationIndex();
        Stack<SherlockFragment> stack = null;
        SherlockFragment fragment = null;
        String rootTag = null;
        switch(index) {
            case 0:
                stack = mWatersTabListener.mStack;
                fragment = mWatersTabListener.mFragment;
                rootTag = mWatersTabListener.mTag;
                break;
            case 1:
                stack = mHarborTabListener.mStack;
                fragment = mHarborTabListener.mFragment;
                rootTag = mHarborTabListener.mTag;
                break;
        }

        if(stack.isEmpty()) {
            return super.onKeyDown(keyCode, event);
        } else {
            SherlockFragment topFragment = stack.pop();
            FragmentManager fragmentManager = getSupportFragmentManager();

            FragmentTransaction ft = fragmentManager.beginTransaction();

            ft.setCustomAnimations(R.anim.fragment_slide_right_enter,
                    R.anim.fragment_slide_right_exit);

            if(topFragment != null && !topFragment.isDetached()) {
                ft.detach(topFragment);
            }

            if(stack.isEmpty()) {
                ft.replace(android.R.id.content, fragment, rootTag);
                ft.commit();
                return true;
            } else {
                SherlockFragment nextFragment = stack.peek();
                ft.replace(android.R.id.content, nextFragment);
                ft.commit();
                return true;
            }
        }
    }
    return super.onKeyDown(keyCode, event);
}

最重要的事情要注意的是,你必须选择时,附上所有的碎片在您的自定义堆栈和你有未选定时分离都管不好。如果有问题,理解code段只问。

The important things to take note of is that you have to attach all fragments in your custom stack when selected and you have to detach all as well when unselected. If there is problem with understanding the code snippets just ask.

这篇关于定制返回堆栈的每一个片段TabHost Android中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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