Reputation: 483
I can not comprehend this behavior of my fragment transactions. Can someone please intervent before I go crazy. In my MainActivity I set it up correctly:
private final GuideFragment guideFragment = new GuideFragment();
private final MapFragment mapFragment = new MapFragment();
private final MoreFragment moreFragment = new MoreFragment();
Fragment active;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
switch (item.getItemId()) {
case R.id.navigation_guide:
if (!guideFragment.isAdded()) {
transaction.add(R.id.content,guideFragment).commit();
active = guideFragment;
Log.d(TAG, "add Fragment1");
break;
} else {
transaction.hide(active).show(guideFragment).commit();
active = guideFragment;
Log.d(TAG, "show Fragment1");
break;
}
case R.id.navigation_map:
if (!mapFragment.isAdded()) {
transaction.add(R.id.content, mapFragment).commit();
active = mapFragment;
Log.d(TAG,"add Fragment2");
break;
} else {
transaction.hide(active).show(mapFragment).commit();
active = mapFragment;
Log.d(TAG,"show Fragment2");
break;
}
case R.id.navigation_more:
if (!moreFragment.isAdded()) {
transaction.add(R.id.content,moreFragment).commit();
active = moreFragment;
Log.d(TAG,"add Fragment3");
break;
} else {
transaction.hide(active).show(moreFragment).commit();
active = moreFragment;
Log.d(TAG,"show Fragment3");
break;
}
}
return true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
//start with guide view/fragment
switchTabView(R.id.navigation_guide);
}
//method to start or switch a tab
private void switchTabView(int itemId) {
navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
navigation.setSelectedItemId(itemId);
}
My App has 3 Tabs as you can see above: Tab1 (Guide) Tab2 (Map) Tab3 (More).
When the app launches, the first Tab (Guide) is added and shown correctly. Then I tap on Map (next Fragment), this is added and shown correctly. Finally on the More Tab (my 3rd Tab) all works great.
But when the activity launches and I tap 1-3 (Guide to Map) so far correct - then 3-2 (More Tab to Map Tab) all good - but then back from 2-1 (Map to Guide) there is suddenly the 3rd tab Fragment (More) shown where the Guide Fragment should be.
Someone has an idea on what is wrong? Would appreciate some help.
Solution thanks to Mateus
transaction.hide(fragment3).hide(fragment2).show(fragment1).commit();
I am not sure if calling two times hide fragment is that clean but I think with 3 tabs it is still okay. With more tabs I would consider to handle this in a different way like remove() or replace() fragments.
Update - Solution is more tricky as expected:
switch (item.getItemId()) {
case R.id.navigation_guide:
if (!guideFragment.isAdded()) {
transaction.add(R.id.content,guideFragment).commit();
Log.d(TAG, "add Fragment1");
break;
} else {
if (!moreFragment.isAdded() && mapFragment.isAdded()) {
transaction.hide(mapFragment).show(guideFragment).commit();
}
if (moreFragment.isAdded() && !mapFragment.isAdded()) {
transaction.hide(moreFragment).show(guideFragment).commit();
}
if (moreFragment.isAdded() && mapFragment.isAdded()) {
transaction.hide(moreFragment).hide(mapFragment).show(guideFragment).commit();
}
Log.d(TAG, "show Fragment1");
break;
}
case R.id.navigation_map:
if (!mapFragment.isAdded()) {
transaction.add(R.id.content, mapFragment).commit();
Log.d(TAG,"add Fragment2");
break;
} else {
if (!moreFragment.isAdded()) {
transaction.hide(guideFragment).show(mapFragment).commit();
} else {
transaction.hide(guideFragment).hide(moreFragment).show(mapFragment).commit();
}
Log.d(TAG,"show Fragment2");
break;
}
case R.id.navigation_more:
if (!moreFragment.isAdded()) {
transaction.add(R.id.content,moreFragment).commit();
Log.d(TAG,"add Fragment3");
break;
} else {
if (!mapFragment.isAdded()) {
transaction.hide(guideFragment).show(moreFragment).commit();
} else {
transaction.hide(guideFragment).hide(mapFragment).show(moreFragment).commit();
}
Log.d(TAG,"show Fragment3");
break;
}
}
Finally bug free, you have to check if other fragments are added!
Upvotes: 2
Views: 771
Reputation: 11
When I want to go to another fragment in the same activity I use this:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container,yourFragment);
transaction.commit();
Container is a layout in your activity. Use it to show your fragment.
Also you have to init in each case of bottomNavigationView
the FragmentTransaction
object!
I believe that this is what you are looking for!
Upvotes: 1
Reputation: 5532
At the point you go back from 2 to 1, this line will be called:
transaction.hide(active).show(guideFragment).commit();
The problem is that when you hide active(Fragment 2) and show Fragment 1, Fragment 3(which was added after Fragment 1, therefore is "on top" of Fragment1) is still being shown. You'd have to call hide on Fragment 3 too to see Fragment 1.
In other words, you need to adjust your code to hide all the other fragments everytime you want to show a specific one.
Also check this discussion about choosing between show/hide and add/remove/replace to confirm that the first strategy better suits your needs.
Upvotes: 3