Created
June 13, 2019 12:12
-
-
Save smihajlovski/fa53e60a4df1dd20eecfa24735ecc67c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MainActivity extends AppCompatActivity implements FragmentInteractionCallback { | |
private Map<String, Stack<String>> tagStacks; | |
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, DashboardFragment.newInstance(false)); | |
break; | |
case DashboardFragment.ACTION_NOTIFICATION: | |
showFragment(bundle, NotificationsFragment.newInstance(false)); | |
break; | |
case NotificationsFragment.ACTION_DASHBOARD: | |
showFragment(bundle, DashboardFragment.newInstance(false)); | |
break; | |
} | |
} | |
} | |
@Override | |
public void onBackPressed() { | |
resolveBackPressed(); | |
} | |
private void createStacks() { | |
binder.bottomNavigationView.inflateMenu(R.menu.bottom_nav_tabs); | |
binder.bottomNavigationView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener); | |
homeFragment = HomeFragment.newInstance(true); | |
dashboardFragment = DashboardFragment.newInstance(true); | |
notificationFragment = NotificationsFragment.newInstance(true); | |
tagStacks = new LinkedHashMap<>(); | |
tagStacks.put(TAB_HOME, new Stack<>()); | |
tagStacks.put(TAB_DASHBOARD, new Stack<>()); | |
tagStacks.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); | |
binder.bottomNavigationView.setOnNavigationItemReselectedListener(onNavigationItemReselectedListener); | |
} | |
private final 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 final BottomNavigationView.OnNavigationItemReselectedListener onNavigationItemReselectedListener = menuItem -> { | |
switch (menuItem.getItemId()) { | |
case R.id.tab_home: | |
popStackExceptFirst(); | |
break; | |
case R.id.tab_dashboard: | |
popStackExceptFirst(); | |
break; | |
case R.id.tab_notifications: | |
popStackExceptFirst(); | |
break; | |
} | |
}; | |
private void selectedTab(String tabId) { | |
currentTab = tabId; | |
BaseFragment.setCurrentTab(currentTab); | |
if (tagStacks.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(), tagStacks, TAB_HOME, homeFragment, R.id.frame_layout, true); | |
resolveStackLists(tabId); | |
assignCurrentFragment(homeFragment); | |
break; | |
case TAB_DASHBOARD: | |
addAdditionalTabFragment(getSupportFragmentManager(), tagStacks, TAB_DASHBOARD, dashboardFragment, currentFragment, R.id.frame_layout, true); | |
resolveStackLists(tabId); | |
assignCurrentFragment(dashboardFragment); | |
break; | |
case TAB_NOTIFICATIONS: | |
addAdditionalTabFragment(getSupportFragmentManager(), tagStacks, 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 | |
*/ | |
Fragment targetFragment = getSupportFragmentManager().findFragmentByTag(tagStacks.get(tabId).lastElement()); | |
showHideTabFragment(getSupportFragmentManager(), targetFragment, currentFragment); | |
resolveStackLists(tabId); | |
assignCurrentFragment(targetFragment); | |
} | |
} | |
private void popFragment() { | |
/* | |
* Select the second last fragment in current tab's stack, | |
* which will be shown after the fragment transaction given below | |
*/ | |
String fragmentTag = tagStacks.get(currentTab).elementAt(tagStacks.get(currentTab).size() - 2); | |
Fragment fragment = getSupportFragmentManager().findFragmentByTag(fragmentTag); | |
/*pop current fragment from stack */ | |
tagStacks.get(currentTab).pop(); | |
removeFragment(getSupportFragmentManager(), fragment, currentFragment); | |
assignCurrentFragment(fragment); | |
} | |
private void resolveBackPressed() { | |
int stackValue = 0; | |
if (tagStacks.get(currentTab).size() == 1) { | |
Stack<String> value = tagStacks.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)); | |
Fragment targetFragment = getSupportFragmentManager().findFragmentByTag(tagStacks.get(currentTab).lastElement()); | |
showHideTabFragment(getSupportFragmentManager(), targetFragment, currentFragment); | |
assignCurrentFragment(targetFragment); | |
updateStackToIndexFirst(stackList, tempCurrent); | |
menuStacks.remove(0); | |
} | |
private void navigateToPreviousMenu() { | |
menuStacks.remove(0); | |
currentTab = menuStacks.get(0); | |
BaseFragment.setCurrentTab(currentTab); | |
binder.bottomNavigationView.setSelectedItemId(resolveTabPositions(currentTab)); | |
Fragment targetFragment = getSupportFragmentManager().findFragmentByTag(tagStacks.get(currentTab).lastElement()); | |
showHideTabFragment(getSupportFragmentManager(), targetFragment, currentFragment); | |
assignCurrentFragment(targetFragment); | |
} | |
private void popStackExceptFirst() { | |
if (tagStacks.get(currentTab).size() == 1) { | |
return; | |
} | |
while (!tagStacks.get(currentTab).empty() | |
&& !getSupportFragmentManager().findFragmentByTag(tagStacks.get(currentTab).peek()).getArguments().getBoolean(EXTRA_IS_ROOT_FRAGMENT)) { | |
getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(tagStacks.get(currentTab).peek())); | |
tagStacks.get(currentTab).pop(); | |
} | |
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tagStacks.get(currentTab).elementAt(0)); | |
removeFragment(getSupportFragmentManager(), fragment, currentFragment); | |
assignCurrentFragment(fragment); | |
} | |
/* | |
* 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(), tagStacks, 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 getSupportFragmentManager().findFragmentByTag(tagStacks.get(currentTab).elementAt(tagStacks.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