当前位置: 首页 > 面试题库 >

删除并重新添加片段后,保留getChildFragmentManager导航堆栈

勾炜
2023-03-14
问题内容

我有活动:

`<RelativeLayout>
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    <Button/>
    <Button/>
</RelativeLayout>`

在此容器内,取决于所按下的按钮是FragmentA还是FragmentB。这些片段是嵌套子片段的 容器 。即,每个片段中都包含自己的导航堆栈。

在活动的onCreate中,我将实例化这两个片段:

fragmentA = (FragmentContainer) Fragment.instantiate(this, FragmentContainer.class.getName()); fragmentB = (FragmentContainer) Fragment.instantiate(this, FragmentContainer.class.getName());

然后,我继续互相替换:

final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction() .replace(R.id.container, fragment); .commitAllowingStateLoss();

到目前为止,一切都很好。但

问题:

每次我用fragmentB替换fragmentA时(反之亦然) -getChildFragmentManager()
破坏其导航堆栈,fragmentA / B每次都从头开始,而不是替换之前包含的嵌套片段。

有任何想法吗?至少可行吗?康斯坦丁,祝你有美好的一天


问题答案:

所以这就是我解决的方法:

MainActivity.xml

<RelativeLayout>
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

MainActivity.java

public class MainActivity extends FragmentActivity {

    final FragmentContainer [] fragmentContainers = new FragmentContainer[3];
    int currentTabIndex = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final FragmentMetaData [] fragmentContainersMetaData = {
                new FragmentMetaData(FragmentA.class.getName(), null),
                new FragmentMetaData(FragmentB.class.getName(), null),
                new FragmentMetaData(FragmentC.class.getName(), null)
        };

        for (int i = 0; i < fragmentContainers.length; i++) {
            fragmentContainers[i] = (FragmentContainer) Fragment.instantiate(this, FragmentContainer.class.getName());
            fragmentContainers[i].addMetaData(fragmentContainersMetaData[i]);
        }

        tabPageNavigationSelection(0);
    }

    void replaceFragmentBy(final Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();                    
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.container, fragment);
        fragmentTransaction.commitAllowingStateLoss();
    }

    // Method to switch between tabs
    void tabPageNavigationSelection (final int index) {
        if (currentTabIndex == index) {
            fragmentContainers[currentTabIndex].clearStackExceptRootFragment();
        } else {
            currentTabIndex = index;
            replaceFragmentBy(fragmentContainers[currentTabIndex]);
        }
    }
}

FragmentContainer.xml

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="@color/lightest_gray"
    android:id="@+id/nestedContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

FragmentContainer.java

public final class FragmentContainer extends Fragment {
    private final List<FragmentMetaData> fragmentMetaDataStack = new ArrayList<>();

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        initialize(inflater, container, R.layout.fragment_container);

        for (FragmentMetaData metaData : fragmentMetaDataStack) {
            showNestedFragment(Fragment.instantiate(getActivity(), metaData.className, metaData.fragmentBundle), fragmentMetaDataStack.indexOf(metaData) > 0, true);
        }

        return getFragmentView();
    }

    @Override
    public void onResume() {
        super.onResume();
        if (getChildFragmentManager().getFragments() == null){
            return;
        }

        int stackDepth = getChildFragmentManager().getFragments().size();
        if (stackDepth > 0 && fragmentMetaDataStack.size() < stackDepth &&
                getChildFragmentManager().getFragments().get(fragmentMetaDataStack.size() - 1) != null) {
            getChildFragmentManager().getFragments().get(fragmentMetaDataStack.size()-1).onResume();
        }
    }

    public void showNestedFragment(final Fragment fragment, final boolean addToBackStack, final boolean isRestoring) {
        final FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.nestedContainer, fragment);
        if (addToBackStack) {
            fragmentTransaction.addToBackStack(null);
        }

        if (!isRestoring) {
            fragmentMetaDataStack.add(new FragmentMetaData(fragment.getClass().getName(), fragment.getArguments()));
        }

        fragmentTransaction.commitAllowingStateLoss();
    }

    public void onBackPressed() {
        if (getChildFragmentManager().getBackStackEntryCount() > 0) {
            getChildFragmentManager().popBackStack();
            fragmentMetaDataStack.remove(fragmentMetaDataStack.size() - 1);
        } else {
            getActivity().finish();
        }
    }

    public void addMetaData(FragmentMetaData metaData) {
        fragmentMetaDataStack.add(metaData);
    }

    public void clearStackExceptRootFragment() {
        getChildFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        while (fragmentMetaDataStack.size() > 1) {
            fragmentMetaDataStack.remove(1);
        }
    }
}

希望这会对尝试复制instagram导航模型的人有所帮助:)



 类似资料:
  • 我正在使用UI导航图。我有片段和。我的应用程序在片段上启动,以显示一些信息。然后,用户可以按下后退键,以结束。然后,用户通常从中选择一些内容,并以结束。 通常,我可以从堆栈中弹出并显示。但是,当应用程序刚刚启动时,后面的堆栈中没有。我想我可以手动将添加到backstack,但我想知道导航UI图是否允许我这样做。 我无法更改应用程序片段的顺序。这意味着我仍然需要首先显示。

  • 场景我试图实现的目标: 使用两个框架容器加载活动(用于项目列表和详细信息) 在应用程序启动时,在listFrame中添加listFragment,在detailsFrame容器中添加一些初始infoFragment 在列表项中导航,而不将每个细节事务添加到后堆栈中(只希望在堆栈中保留infoFragment) 一旦用户点击后退按钮(向后导航),他就会返回到初始信息片段,即在启动时添加的信息片段 如

  • 我尝试使用Android导航组件,但后堆栈有问题。 我有片段A,B。要从A导航到B,我写下: 但我如何才能返回到点击的返回按钮?

  • 我正在使用android中的新导航架构组件,在移动到一个新的片段后,我被困在清除导航堆栈中。 示例:我在loginFragment中,当我导航到home片段时,我希望该片段从堆栈中清除,这样当用户按下back按钮时,他就不会返回到loginFragment。 我正在使用一个简单的navhostfragment.findnavcontroller(Fragment).navigate(r.id.ho

  • 如何从堆栈中弹出特定片段,并从片段中删除其他片段?例如,这些是我的片段,我现在在E right know。 A- 想从E回到B,清除C和D。我怎么能做到这一点?

  • 我需要删除活动onPause事件上的Google地图片段,并将其添加回Resume事件。我该怎么做? 因此这个后退按钮非常慢 需要它为Android性能问题-TabHost-定时器-设置货币标签()-谷歌地图API V2 编辑: 事实上我做到了。但是仍然有延迟问题。如何在后堆栈停止/关闭意图? 编辑: 另外,我现在正试图删除和添加回片段,请看这个-