When I used fragment (.add) method and used “fade_in/fade_out” animation When moving between them. It is gives me this error “java.lang.IllegalStateException: commit already called”. I followed this tutorial to add fragments and this question to use animation.
Her’s my code
final Fragment fragment1 = new HomeFragment();
final Fragment fragment2 = new LibraryFragment();
final Fragment fragment3 = new ImageFragment();
final FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment active = fragment1;
private void initializeBottomNavigation() {
// animations
ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
ft.setCustomAnimations(android.R.anim.fade_out, android.R.anim.fade_in);
// add fragments
ft.add(R.id.fragment_layout, fragment3, "3").hide(fragment3).commit();
ft.add(R.id.fragment_layout, fragment2, "2").hide(fragment2).commit();
ft.add(R.id.fragment_layout,fragment1, "1").commit();
// show and hid them when click on BottomNav items
BottomNavigationView navigationView = findViewById(R.id.bottom_navigation);
navigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.home_item:
ft.hide(active).show(fragment1).commit();
active = fragment1;
return true;
case R.id.books_item:
ft.hide(active).show(fragment2).commit();
active = fragment2;
return true;
case R.id.image_item:
ft.hide(active).show(fragment3).commit();
active = fragment3;
return true;
}
return false;
}
});
}
Advertisement
Answer
FragmentTransaction is a one-time use object. You shouldn’t reuse it in multiple actions, but rather start a new transaction every time you want to change some Fragments.
In your case this is: once during initialisation, and once on every bottom bar press.
First of all, remove the line FragmentTransition ft = fm.beginTransaction() from the top since you can’t reuse that object.
Then change the function like so where you create a new transaction for every button press:
private void initializeBottomNavigation() {
// first one transaction to add each Fragment
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_layout, fragment3, "3").hide(fragment3);
ft.add(R.id.fragment_layout, fragment2, "2").hide(fragment2);
ft.add(R.id.fragment_layout, fragment1, "1");
// commit once! to finish the transaction
ft.commit();
// show and hide them when click on BottomNav items
BottomNavigationView navigationView = findViewById(R.id.bottom_navigation);
navigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
// start a new transaction
FragmentTransaction ft = fm.beginTransaction();
// animations
ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
ft.setCustomAnimations(android.R.anim.fade_out, android.R.anim.fade_in);
switch (item.getItemId()) {
case R.id.home_item:
ft.hide(active).show(fragment1).commit();
active = fragment1;
return true;
case R.id.books_item:
ft.hide(active).show(fragment2).commit();
active = fragment2;
return true;
case R.id.image_item:
ft.hide(active).show(fragment3).commit();
active = fragment3;
return true;
}
return false;
}
});
}