How to copy YouTube's app navigation logic

Multi tool use
How to copy YouTube's app navigation logic
I want to implement in my app navigation logic like in Youtube app. (BottomNavigationView + Fragment management). I want this, because these fragments are heavy, so I want them to be lazy initialized and then stored in backstack, I feel like YouTube is doing it this way. I have implemented BottomNagivationView but I have problems with Fragment Management.
My code:
bottomNavigationView.setOnTabSelectedListener { position, _ ->
setFragment(OnlinePageFragment.Page.values()[position])
}
where Pages is enum
enum class Page(index: Int, val klass: Class<*>) {
ONE(0, OnePageFragment::class.java),
TWO(1, TwoPageFragment::class.java),
THREE(2, ThreePageFragment::class.java)
}
and here is my setFragment function
fun setFragment(page: OnlinePageFragment.Page) {
var fragment: Fragment? = supportFragmentManager.findFragmentByTag(page.klass.name)
val tag = page.klass.name
if (fragment == null)
fragment = OnlinePageFragment.newInstance(page, null)
val ft = supportFragmentManager.beginTransaction()
with(ft) {
replace(R.id.fragmentContainer, fragment, tag)
addToBackStack(tag)
commit()
}
}
override fun onBackPressed() {
if (supportFragmentManager.backStackEntryCount == 1) finish()
else super.onBackPressed()
}
And it's working, but not as good as YouTube app. YouTube app has some magic behaviour i.e. it keeps only one transaction per each fragment, while my app allows to create "infinite" backstack of transactions. Do you have any ideas how it works in YouTube app ?
2 Answers
2
Without using view pager you can manage it.
I have implemented Please check this. https://github.com/sandeshsk/BackStackFragmentRedirectsToHome
Please update if there is any issue.
This is a method which assigns fragment
public void addFragment(FragmentManager fragmentManager,
Fragment fragment,
int containerId,boolean isFromHome){
fragmentManager.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
if(isFromHome){
fragmentTransaction.replace(containerId,fragment);
}else{
fragmentTransaction.add(new HomeFragment(),"Home");
fragmentTransaction.addToBackStack("Home");
}
fragmentTransaction.replace(containerId,fragment).commit();
}
This is your navigation item listener
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
addFragment(getSupportFragmentManager(), new HomeFragment(), R.id.frame, true);
}else{
getSupportFragmentManager().popBackStack();
}
return true;
case R.id.navigation_dashboard:
addFragment(getSupportFragmentManager(),new DashboardFragment(),R.id.frame,false);
return true;
case R.id.navigation_notifications:
addFragment(getSupportFragmentManager(),new NotificationFragment(),R.id.frame,false);
return true;
case R.id.navigation_setting:
addFragment(getSupportFragmentManager(),new SettingFragment(),R.id.frame,false);
return true;
}
return false;
}
};
onBackPressed method
@Override
public void onBackPressed() {
if(getSupportFragmentManager().getBackStackEntryCount()>0){
navigation.setSelectedItemId(R.id.navigation_home);
}else {
super.onBackPressed();
}
}
I guess the best way here is to use ViewPager
to store root fragments. Navigation bar will change pages of ViewPager
.
ViewPager
ViewPager
Root fragments will store content fragments inside their ChildFragmentManagers
and implement logic of navigation between content fragments.
ChildFragmentManagers
Also you will need to implement logic of delegation backpress events from activity to root fragments, to perform navigation in their backstack.
UPD #1
Make sure, that root fragments are not destroyed inside ViewPager, use setOffscreenPageLimit()
UPD #2
If you don't want to use ViewPager, you can use code from this answer to manage root fragments.
@StachuBarański if it's too heavy to load 3 fragments at start at first load only the first one and others populate with data if user swipes to see them.
– hardartcore
Aug 8 '17 at 6:18
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
ViewPager is my current implementation, and I wanted to change it since It's too heavy to load 3 fragments at once.
– Stachu Barański
Aug 7 '17 at 21:13