Android ViewPageAdapter,每个选项卡具有单独的后退堆栈 [英] Android ViewPageAdapter with a separate backstack for each tab

查看:78
本文介绍了Android ViewPageAdapter,每个选项卡具有单独的后退堆栈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有单个活动的Android应用程序.该活动包含一个带有ViewPageAdapter的SlidingTabLayout,如

I have an Android App with a single activity. The activity contains a SlidingTabLayout with a ViewPageAdapter as in this example. Each tab contains a respective root fragment which I then replace with other fragments as the user uses that screen. A visual representation is shown below:

在我当前的实现中,我将执行以下操作:转到tab1,通过用ProductListFragment替换ProductRootFragment来立即加载ProductListFragment.我单击一个产品,它将ProductListFragment替换为ProductDetailFragment.现在,我切换到tab2,并且通过替换Tab2RootFragment立即加载Tab2ListFragment.我单击一个项目,然后Tab2DetailFragment替换Tab2ListFragment.现在返回Tab1,并且正如我期望的那样,仍然显示ProductDetailFragment.但是,如果现在单击后退"按钮,则不会像我期望的那样将我带回到ProductListFragment.相反,它从堆栈中弹出Tab2DetailFragment.

With my current implementation I do the following: go to tab1, the ProductListFragment immediately loads by replacing the ProductRootFragment with the ProductListFragment. I click on a product and it replaces the ProductListFragment with the ProductDetailFragment. Now I switch to tab2 and Tab2ListFragment immediately loads by replacing Tab2RootFragment. I click on an item and the Tab2DetailFragment replaces the Tab2ListFragment. I now return to Tab1 and, as I expect, ProductDetailFragment is still displayed. However, if I now click the back button, it doesn't take me back to ProductListFragment as I expect. Instead it pops off Tab2DetailFragment from the backstack.

我想为每个选项卡"片段实现一个单独的堆栈.关于此的已经有好几篇文章,但它们似乎都已过时,并且有些文章提出了非常详尽的解决方案. (请参见此处此处

I want to implement a separate backstack for each "tab" fragment. There are several posts about this already but they all seem to be outdated and some suggest very elaborate solutions. (See here, here and here...)

似乎,在最新版本的SDK中,Android可以自动处理此后向堆栈层次结构,而无需在我替换片段的事务中使用getChildFragmentManager而不是getSupportFragmentManager来手动实现某种后向堆栈.但是,我无法使它正常工作. (我凭直觉感到,正确的解决方案在于让Android处理此问题,因为感觉就像手动覆盖后退按钮并实现自己的堆栈是一个精心设计的技巧.)

It seems that in the latest versions of the SDK Android can automatically handle this backstack hierarchy without the need to manually implement some kind of backstack by using getChildFragmentManager rather than getSupportFragmentManager in my transactions where I replace the fragments. I have, however, not been able to get this to work. (I intuitively feel that the correct solution lies along the lines of letting Android handle this as it feels like manually overriding the back button and implementing your own stack is an elaborate hack.)

有人可以解释一下如何正确实现预期的行为,即为每个选项卡维护一个单独的后台堆栈吗?还是链接到有关如何实现所需行为的简单,精心设计和最新的示例?

Can someone please explain how to properly implement the expected behavior where a separate backstack is maintained for each tab? Or perhaps link to a simple, well-designed and up-to-date example of how to achieve the desired behavior?

有关我的代码的其他信息: 在我的MainActivity.java中,我使用getSupportFragmentManager()构造了ViewPagerAdapter.

Additional information about my code: In my MainActivity.java, I construct the ViewPagerAdapter using getSupportFragmentManager().

ViewPagerAdapter.java

ViewPagerAdapter.java

@Override
public Fragment getItem(int position) {
    switch(position){
        case 0: return new ProductRootFragment();
        ...
    }
    ...
}

ProductRootFragment.java

ProductRootFragment.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.product_root_fragment, container, false);

    FragmentTransaction transaction = getFragmentManager()
            .beginTransaction();
    transaction.replace(R.id.product_root_container, new ProductListFragment());
    transaction.commit();
    return view;
}

ProductListFragment.java

ProductListFragment.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View layout = inflater.inflate(R.layout.product_list_fragment, container, false);
    view = (ProductListView) layout;
    return view;
}
...
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    ...
    ProductDetailFragment newFragment = new ProductDetailFragment();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.product_root_container, newFragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

ProductDetailFragment.java

ProductDetailFragment.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    view = (ProductDetailView) inflater.inflate(R.layout.product_detail_fragment, container, false);
    return view;
}

推荐答案

我知道回答这个问题太迟了,但是也许有人仍然需要它. 为此,您必须在根片段中使用getChildFragmentManager()而不是getFragmentManager()

I know its late to answer this question, but maybe someone still need it. For achieve this you must use getChildFragmentManager() instead of getFragmentManager() in your root fragments

例如,我有一个使用ViewPager和TabLayout的活动,我添加了 RootFragment1RootFragment2到ViewPager并使用ViewPager设置TabLayout. 现在在我的RootFragment1中替换我的Tab1Fragment1,我使用以下代码:

For example I have a activity with ViewPager and TabLayout and I add RootFragment1 and RootFragment2 to ViewPager and setup TabLayout with ViewPager. Now in my RootFragment1 for replace my Tab1Fragment1 I use this code:

final FragmentTransaction ft = getChildFragmentManager().beginTransaction();
ft.replace(R.id.RootFrame1, Tab1Fragment1.newInstance(), "MyTag");
ft.commit();

并需要这样的方法从后台弹出片段:

And need the method to popup fragment from backstack likes this:

public boolean popBackStack() {
    if(getChildFragmentManager().getBackStackEntryCount() > 0) {
        getChildFragmentManager().popBackStackImmediate();
        return true;
    } else
        return false;
}

例如,我在Tab1Fragment1中有一个按钮,用当前按钮替换片段Tab1Fragment2.按钮onClickListener必须看起来像这样:

And for example I have a button in the Tab1Fragment1 that replace fragment Tab1Fragment2 with current. The button onClickListener must look likes this:

button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        final FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.RootFrame1, Tab1Fragment2.newInstance(), "MyTag");
        ft.addToBackStack(null);
        ft.commit();
    }
});

我对第二个片段(RootFragment2)也一样.

I do same with second fragment (RootFragment2).

之后,现在我只需要覆盖MainActivityonBackPressed(),如下所示:

After that, now I only need to override onBackPressed() of my MainActivity likes below:

@Override
public void onBackPressed() {
    if (viewPager.getCurrentItem() == 0) {
        RootFragment1 fragment = ((RootFragment1) sectionsPagerAdapter.getItem(0));
        if (!fragment.popBackStack())
            super.onBackPressed();
    } else if (viewPager.getCurrentItem() == 1) {
        RootFragment2 fragment = ((RootFragment2) sectionsPagerAdapter.getItem(1));
        if (!fragment.popBackStack())
            super.onBackPressed();
    } else
        super.onBackPressed();
}

我检查每个选项卡是否包含片段,然后从其堆栈中弹出,否则调用super.onBackPressed()进行默认操作.

That I check if each tab contains fragment then I popup from its backstack else call super.onBackPressed() to do default action.

这篇关于Android ViewPageAdapter,每个选项卡具有单独的后退堆栈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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