切换选项卡时重置片段backstack

时间:2014-07-05 20:14:25

标签: android android-fragments tabs

现在我的第一个问题是,在互联网上找不到答案之后。通常这应该是一件非常简单的事情,但它花了我几个小时,所以请原谅我,如果它是一个初学者的问题。此外,我想确保我在花费更多时间之前采取正确的方式只是为了看到它最终它不能按我的意愿工作,我实现它的方式。

问题:

我的应用有3个标签,其中3个片段作为内容,每个标签一个。我使用Tabs,因为我问的所有用户都想要Tabs而不是导航抽屉,我听用户,而不是google(抱歉)。此外,3个选项卡具有非常不同的“角色”(语言指南,货币转换器和自己的笔记本用于自己的短语等),并且以这种方式拆分它是有意义的(imo)。如果有人有其他想法,请继续,我打开: - )

标签导航到目前为止按预期工作。但是现在我想为单个Tabs构建更多的导航,我不知道还有什么方法可以去... Theres只是这么简单的事情... ...

第一个选项卡有一些imageButtons以进一步导航到此部分(请参见屏幕截图1),以在语言部分中选择一个类别。当然这意味着选项卡应该保持在原位以便能够轻松切换到转换器i.E,只需从选项卡1切换到新片段(参见屏幕截图2),依此类推。您在下面的屏幕截图中看到的按钮具有clicklisteners,可将当前片段更改为新片段(如“Daily”)

为此,我打开另一个片段并将其添加到backstack。也许你已经可以猜到现在发生了什么。如果按下后退按钮,我会回到第一个片段。当我在标签1上打开的片段内部切换标签时,问题就开始了。添加的片段仍然在后台,这意味着如果我按下标签2或3上的后退按钮,显示的内容会以某种方式与其他片段混合。见截图3

我是否在某处犯了错误,或者我只是在切换标签时告诉后端堆栈“重置”,这样就不会出现这个问题?

感谢您提供信息并抱歉语言和拼写错误,英语不是我的主要语言。

Tablistener类切换标签片段:

public  class MyTabListener implements ActionBar.TabListener {
Fragment fragment;

public MyTabListener(Fragment fragment) {
    this.fragment = fragment;
}

public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
    ft.replace(R.id.fragment_container, fragment);
}

public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
    ft.remove(fragment);
}

public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
    // nothing done here
}

}

第一个片段的Fragments类看起来像这样(不是完整代码):

public static class FragmentTab1 extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        final View view = inflater.inflate(R.layout.tab, container, false);

        ImageButton catBtn_Daily = (ImageButton) view.findViewById(R.id.catBtn_Daily);
        ImageButton catBtn_OnTheRoad = (ImageButton) view.findViewById(R.id.catBtn_OnTheRoad);
        ImageButton catBtn_Shopping = (ImageButton) view.findViewById(R.id.catBtn_Shopping);
        ImageButton catBtn_Restaurant = (ImageButton) view.findViewById(R.id.catBtn_Restaurant);
        ImageButton catBtn_Romance = (ImageButton) view.findViewById(R.id.catBtn_Romance);
        ImageButton catBtn_Emergency = (ImageButton) view.findViewById(R.id.catBtn_Emergency);


        // attach an OnClickListener
        catBtn_Daily.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {

                 // Create new fragment and transaction
                 Fragment newFragment = new FragmentTab4();

                 FragmentTransaction transaction = getFragmentManager().beginTransaction();

                 transaction.replace(R.id.fragment_container, newFragment);
                 transaction.addToBackStack(null);

                 transaction.setTransition(4097);
                 transaction.commit();
             }
        });

Mainactivity:

public class MainActivity extends Activity {
ActionBar.Tab tab1, tab2, tab3;
Fragment fragmentTab1 = new FragmentTab1();
Fragment fragmentTab2 = new FragmentTab2();
Fragment fragmentTab3 = new FragmentTab3();

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_tab_test);

    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    tab1 = actionBar.newTab().setText("Home");
    tab2 = actionBar.newTab().setText("Calculator");
    tab3 = actionBar.newTab().setText("Notebook");

    tab1.setTabListener(new MyTabListener(fragmentTab1));
    tab2.setTabListener(new MyTabListener(fragmentTab2));
    tab3.setTabListener(new MyTabListener(fragmentTab3));

    actionBar.addTab(tab1);
    actionBar.addTab(tab2);
    actionBar.addTab(tab3);

还不能发布照片,代表太低......

请看这里(第三张图片叫做Untitled-3.png)

屏幕1:https://www.dropbox.com/s/3av3pf6a17p2w42/Untitled-1.png

屏幕2:https://www.dropbox.com/s/3av3pf6a17p2w42/Untitled-2.png

屏幕3:https://www.dropbox.com/s/3av3pf6a17p2w42/Untitled-3.png

3 个答案:

答案 0 :(得分:1)

最好不要使用片段后端堆栈。您可以维护自己的堆栈并覆盖onBackPressed()以提供适当的行为。

@Override protected void onBackPressed()
{
    if(myStack.isEmpty())
        super.onBackPressed(); // default handling finishes the activity
    else
    {
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_container, myStack.pop());
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
        transaction.commit();            
    }
}

答案 1 :(得分:0)

您可以尝试以下操作:

public void onTabSelected(YourTab tab) {
    Fragment fragment = new YourTabFragment();
    replaceRootFragment(fragment);
}

public void replaceRootFragment(Fragment fragment) {
    if (getSupportFragmentManager().getBackStackEntryCount() != 0) {
        int id = getSupportFragmentManager().getBackStackEntryAt(0).getId();
        try {
            getSupportFragmentManager().popBackStackImmediate(id, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        } catch (IllegalStateException e) {
            return;
        }
    }
    getSupportFragmentManager().beginTransaction()
            .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
            .replace(R.id.container, fragment)
            .commit();
}

单击选项卡时调用onTabSelected。

答案 2 :(得分:0)

实际上,您可能想要考虑采用完全不同的方法。如果我理解正确,您可能需要考虑将ViewPager与FragmentPagerAdapter一起使用(请参阅此处的Google文档代码示例:FragmentPagerAdapter)。

本质上,viewpager会在您的选项卡下显示片段,适配器提供要显示的片段列表,您可以通过在viewpager上调用setCurrentItem来选择当前的“页面”(当用户单击选项卡时)。此外,用户可以在页面之间滑动(您可以通过收听寻呼机事件来更新选定的选项卡,请参阅此处的Google文档代码示例:ViewPager)。

这种方法避免了整个后台问题,听起来更像是你所追求的。

希望它有所帮助。