Contents
Mobile App Development Tutorial How To Manage Multiple Fragments On Single Activity
Purpose
Android comes with an activity stack and we don’t need to maintain the stack while opening or closing an activity. Android will automatically handle the stack and show you the top activity when you press the Back button. But it is necessary to handle fragments explicitly because Android is not going to handle them automatically. For example, some applications might require something like the left sliding menus or the bottom tab bar that has multiple items with a particular work flow in each.
Here, I would like to share with you how you can handle this using a single activity and fragment container as stack.
You should create an enum object to define all of menu/tab types that will be showed in your application.
public static enum MenuType { MENU_1, MENU_2, MENU_3 }
2 Creating base activity class.
2.1 Creating fragment container
To store fragments of all menus/tabs, we need to use Map object as container. Each element of it consists of a pair of key and value in which key is type of menu/tab and value is stack of fragments. We will push and pop the fragment into corresponding stack.
public Map<MenuType, Stack<Fragment>> mStackMap; protected MenuType mCurrentMenuTab = MenuType.MENU_1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initStackFragments(); } private void initStackFragments() { mStackMap = new HashMap<MenuType, Stack<Fragment>>(); for (MenuType menuType : MenuType.values()) { mStackMap.put(menuType, new Stack<Fragment>()); } }
It is active menu/tab that will be operated then.
public void setCurrentMenuOrTab(MenuType menuType) { mCurrentMenuTab = menuType; }
2.3 Pushing new fragment
Whenever you want to display any new fragment, just push that fragment into stack using following code.
public void pushFragment(Fragment fragment, boolean shouldAdd) { if (shouldAdd) { mStackMap.get(mCurrentMenuTab).push(fragment); } FragmentManager manager = getSupportFragmentManager(); FragmentTransaction ft = manager.beginTransaction(); ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right); ft.replace(getFragmentContainerResId(), fragment, fragment.getClass().getSimpleName()); ft.commitAllowingStateLoss(); }
2.4 Poping the current fragment
Whenever you want to destroy the current fragment and go back to previous fragment, just pop that fragment using following code without sending data to previous fragment
public void popFragment() { final Stack<Fragment> stackFragment = mStackMap.get(mCurrentMenuTab); if (stackFragment.size() > 1) { Fragment fragment = stackFragment.elementAt(stackFragment.size() - 2); stackFragment.pop(); if (fragment != null) { FragmentManager manager = getSupportFragmentManager(); FragmentTransaction ft = manager.beginTransaction(); ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right); ft.replace(getFragmentContainerResId(), fragment, fragment.getClass().getSimpleName()); ft.commitAllowingStateLoss(); } } }
Here you can pop a fragment and send data to previous fragment
public void popFragment(Bundle argBundle) { final Stack<Fragment> stackFragment = mStackMap.get(mCurrentMenuTab); if (stackFragment.size() > 1) { Fragment fragment = stackFragment.elementAt(stackFragment.size() - 2); stackFragment.pop(); if (fragment != null) { if (argBundle != null) { fragment.setArguments(argBundle); } FragmentManager manager = getSupportFragmentManager(); FragmentTransaction ft = manager.beginTransaction(); ft.replace(getFragmentContainerResId(), fragment, fragment.getClass().getSimpleName()); ft.commitAllowingStateLoss(); } } }
When the backPressed event fires, we will check whether stack size of current menu/tab is <=1 or not. If it is not, then we will pop last fragment and display the previous fragment by following code.
@Override public void onBackPressed() { if (mStackMap.get(mCurrentMenuTab).size() <= 1) { super.onBackPressed(); // or call finish.. } else { popFragment(); } }
3 Create running activity
To use this helper, we just create any activity and extend the base class above. The Inheritance class overrides getFragmentContainerResId() method to determine component will use to push/pop fragment.
@Override protected int getFragmentContainerResId() { return R.id.container; }
4 Example
public class DrawerFragment extends Fragment { public static final String TAG = DrawerFragment.class.getSimpleName(); private MainActivity mainActivity; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mainActivity = (MainActivity) getActivity(); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View rootView = inflater.inflate(R.layout.fragment_drawer, container, false); rootView.findViewById(R.id.bt_menu_1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mainActivity.setCurrentMenuOrTab(BaseStackViewActivity.MenuType.MENU_1); mainActivity.pushFragment(new MenuFirstHomeFragment(), true); mainActivity.openAndCloseDrawer(); } }); rootView.findViewById(R.id.bt_menu_2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mainActivity.setCurrentMenuOrTab(BaseStackViewActivity.MenuType.MENU_2); mainActivity.pushFragment(new MenuSecondHomeFragment(), true); mainActivity.openAndCloseDrawer(); } }); rootView.findViewById(R.id.bt_menu_3).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mainActivity.setCurrentMenuOrTab(BaseStackViewActivity.MenuType.MENU_3); mainActivity.pushFragment(new MenuThirdHomeFragment(), true); mainActivity.openAndCloseDrawer(); } }); return rootView; } }
Conclusion
With this post, I hope you can be more confident using fragments in your application implementation with stack fragment manager.
Brought to you by the RobustTechHouse team. RobustTechHouse works on mobile app development projects and eCommerce & web development projects. If you like our articles, please also check out our Facebook page.
I dugg some of you post as I thought they were very beneficial invaluable