Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
316 views
in Technique[技术] by (71.8m points)

java - Retain getChildFragmentManager navigation stack after removing and re-adding fragment

I have activity:

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

Inside this container, depending on which button pressed appear FragmentA or FragmentB. These fragments are containers for nested child-fragments. I.e. in each fragment contains its own navigation stack.

In onCreate of Activity I instantiate these 2 fragments:

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

Then, I'm continue replacing one each other:

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

So far, so good, everything is working. BUT

Problem:

Every time I replace fragmentA by fragmentB (and vice verse) - getChildFragmentManager() destroy its navigation stack and fragmentA/B starts every time from scratch, not with the nested fragment it contained before being replaced.

Any ideas? Is it doable, at least? Have a brilliant day, Konstantin

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So that's how I solved this:

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

Hopefully, it would help someone, who's trying to copy instagram navigation model :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...