Skip to content

Instantly share code, notes, and snippets.

@smihajlovski
Last active August 13, 2018 07:40
Show Gist options
  • Save smihajlovski/45b2126fcd0570fa16fd39adda219817 to your computer and use it in GitHub Desktop.
Save smihajlovski/45b2126fcd0570fa16fd39adda219817 to your computer and use it in GitHub Desktop.
public class MainActivity extends AppCompatActivity implements FragmentInteractionCallback {
private Map<String, Stack<Fragment>> stacks;
private String currentTab;
private ActivityMainBinding binder;
private List<String> stackList;
private List<String> menuStacks;
private Fragment currentFragment;
private Fragment homeFragment;
private Fragment dashboardFragment;
private Fragment notificationFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binder = DataBindingUtil.setContentView(this, R.layout.activity_main);
createStacks();
}
@Override
public void onFragmentInteractionCallback(Bundle bundle) {
String action = bundle.getString(ACTION);
if (action != null) {
switch (action) {
case HomeFragment.ACTION_DASHBOARD:
showFragment(bundle, new DashboardFragment());
break;
case DashboardFragment.ACTION_NOTIFICATION:
showFragment(bundle, new NotificationsFragment());
break;
case NotificationsFragment.ACTION_DASHBOARD:
showFragment(bundle, new DashboardFragment());
break;
}
}
}
@Override
public void onBackPressed() {
resolveBackPressed();
}
private void createStacks() {
binder.bottomNavigationView.inflateMenu(R.menu.bottom_nav_tabs);
binder.bottomNavigationView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener);
homeFragment = new HomeFragment();
dashboardFragment = new DashboardFragment();
notificationFragment = new NotificationsFragment();
stacks = new LinkedHashMap<>();
stacks.put(TAB_HOME, new Stack<>());
stacks.put(TAB_DASHBOARD, new Stack<>());
stacks.put(TAB_NOTIFICATIONS, new Stack<>());
menuStacks = new ArrayList<>();
menuStacks.add(TAB_HOME);
stackList = new ArrayList<>();
stackList.add(TAB_HOME);
stackList.add(TAB_DASHBOARD);
stackList.add(TAB_NOTIFICATIONS);
binder.bottomNavigationView.setSelectedItemId(R.id.tab_home);
}
private BottomNavigationView.OnNavigationItemSelectedListener onNavigationItemSelectedListener = item -> {
switch (item.getItemId()) {
case R.id.tab_home:
selectedTab(TAB_HOME);
return true;
case R.id.tab_dashboard:
selectedTab(TAB_DASHBOARD);
return true;
case R.id.tab_notifications:
selectedTab(TAB_NOTIFICATIONS);
return true;
}
return false;
};
private void selectedTab(String tabId) {
currentTab = tabId;
BaseFragment.setCurrentTab(currentTab);
if (stacks.get(tabId).size() == 0) {
/*
* First time this tab is selected. So add first fragment of that tab.
* We are adding a new fragment which is not present in stack. So add to stack is true.
*/
switch (tabId) {
case TAB_HOME:
addInitialTabFragment(getSupportFragmentManager(), stacks, TAB_HOME, homeFragment, R.id.frame_layout, true);
resolveStackLists(tabId);
assignCurrentFragment(homeFragment);
break;
case TAB_DASHBOARD:
addAdditionalTabFragment(getSupportFragmentManager(), stacks, TAB_DASHBOARD, dashboardFragment, currentFragment, R.id.frame_layout, true);
resolveStackLists(tabId);
assignCurrentFragment(dashboardFragment);
break;
case TAB_NOTIFICATIONS:
addAdditionalTabFragment(getSupportFragmentManager(), stacks, TAB_NOTIFICATIONS, notificationFragment, currentFragment, R.id.frame_layout, true);
resolveStackLists(tabId);
assignCurrentFragment(notificationFragment);
break;
}
} else {
/*
* We are switching tabs, and target tab already has at least one fragment.
* Show the target fragment
*/
showHideTabFragment(getSupportFragmentManager(), stacks.get(tabId).lastElement(), currentFragment);
resolveStackLists(tabId);
assignCurrentFragment(stacks.get(tabId).lastElement());
}
}
private void popFragment() {
/*
* Select the second last fragment in current tab's stack,
* which will be shown after the fragment transaction given below
*/
Fragment fragment = stacks.get(currentTab).elementAt(stacks.get(currentTab).size() - 2);
/*pop current fragment from stack */
stacks.get(currentTab).pop();
removeFragment(getSupportFragmentManager(), fragment, currentFragment);
assignCurrentFragment(fragment);
}
private void resolveBackPressed() {
int stackValue = 0;
if (stacks.get(currentTab).size() == 1) {
Stack<Fragment> value = stacks.get(stackList.get(1));
if (value.size() > 1) {
stackValue = value.size();
popAndNavigateToPreviousMenu();
}
if (stackValue <= 1) {
if (menuStacks.size() > 1) {
navigateToPreviousMenu();
} else {
finish();
}
}
} else {
popFragment();
}
}
/*Pops the last fragment inside particular tab and goes to the second tab in the stack*/
private void popAndNavigateToPreviousMenu() {
String tempCurrent = stackList.get(0);
currentTab = stackList.get(1);
BaseFragment.setCurrentTab(currentTab);
binder.bottomNavigationView.setSelectedItemId(resolveTabPositions(currentTab));
showHideTabFragment(getSupportFragmentManager(), stacks.get(currentTab).lastElement(), currentFragment);
assignCurrentFragment(stacks.get(currentTab).lastElement());
updateStackToIndexFirst(stackList, tempCurrent);
menuStacks.remove(0);
}
private void navigateToPreviousMenu() {
menuStacks.remove(0);
currentTab = menuStacks.get(0);
BaseFragment.setCurrentTab(currentTab);
binder.bottomNavigationView.setSelectedItemId(resolveTabPositions(currentTab));
showHideTabFragment(getSupportFragmentManager(), stacks.get(currentTab).lastElement(), currentFragment);
assignCurrentFragment(stacks.get(currentTab).lastElement());
}
/*
* Add a fragment to the stack of a particular tab
*/
private void showFragment(Bundle bundle, Fragment fragmentToAdd) {
String tab = bundle.getString(DATA_KEY_1);
boolean shouldAdd = bundle.getBoolean(DATA_KEY_2);
addShowHideFragment(getSupportFragmentManager(), stacks, tab, fragmentToAdd, getCurrentFragmentFromShownStack(), R.id.frame_layout, shouldAdd);
assignCurrentFragment(fragmentToAdd);
}
private int resolveTabPositions(String currentTab) {
int tabIndex = 0;
switch (currentTab) {
case TAB_HOME:
tabIndex = R.id.tab_home;
break;
case TAB_DASHBOARD:
tabIndex = R.id.tab_dashboard;
break;
case TAB_NOTIFICATIONS:
tabIndex = R.id.tab_notifications;
break;
}
return tabIndex;
}
private void resolveStackLists(String tabId) {
updateStackIndex(stackList, tabId);
updateTabStackIndex(menuStacks, tabId);
}
private Fragment getCurrentFragmentFromShownStack() {
return stacks.get(currentTab).elementAt(stacks.get(currentTab).size() - 1);
}
private void assignCurrentFragment(Fragment current) {
currentFragment = current;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment