I am adding a BottomNavigationView with three fragments to my app. Everything works correctly, except one thing.
In the first fragment, there is an EditText view, in the second a ListView and in the third one some texts and images loaded from a JSON hosted in the server.
This is my code:
bottomNavigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.menu_dash:
fragment = new frg_dash();
break;
case R.id.menu_list:
fragment = new frg_list();
break;
case R.id.menu_info:
fragment = new frg_info();
break;
}
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.contenedor_principal, fragment).commit();
return true;
}
});
The problem is that every time I go from one fragment to another using the bottomNavigationView buttons, the Fragment starts all its execution again.
The result I'm looking for is that if the user in the second fragment is, for example, in the middle of the ListView, it goes to the third fragment and returns again, the ListView continues where it was. Or if you press the button of the third Fragment in the bottomNavigationView, do not load the data again from the server.
I guess the problem is that when you click on a bottomNavigationView button, the fragment is created again:
... switch (id) {
case R.id.menu_dash:
fragment = new frg_dash();
break; ...
But it's just a guess. I suppose it can be controlled with the onCreate, onActivityCreated and onCreateView methods, but again, they are just my assumptions.
I've tried it with the hide () and show () parameters of the fragments, but without success ... or I'm not applying it well
I greatly appreciate the help in advance.
EDIT
This is my example currently with all the parts related to the answer:
public void replaceFragment(Fragment fragment, @Nullable Bundle bundle, boolean popBackStack, boolean findInStack) {
Log.v("2134", "Dentro");
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
String tag = fragment.getClass().getName();
Log.v("2134", "tag:" + tag);
Fragment parentFragment;
if (findInStack && fm.findFragmentByTag(tag) != null) {
parentFragment = fm.findFragmentByTag(tag);
} else {
parentFragment = fragment;
}
// if user passes the @bundle in not null, then can be added to the fragment
if (bundle != null) {
parentFragment.setArguments(bundle);
} else {
parentFragment.setArguments(null);
}
// this is for the very first fragment not to be added into the back stack.
if (popBackStack) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else {
ft.addToBackStack(parentFragment.getClass().getName() + "");
}
ft.replace(R.id.contenedor_principal, parentFragment, tag);
ft.commit();
fm.executePendingTransactions();
}
...
bottomNavigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.menu_panel:
fragment = new frg_panel();
break;
case R.id.menu_promos:
fragment = new frg_promociones();
break;
case R.id.menu_catalogo:
fragment = new frg_catalogo();
break;
}
replaceFragment(fragment, null, true, true);
return true;
}
});
Use this code to open your fragment. Your fragment will not create every time. It will get same fragment from stack if exist.
/**
* replace or add fragment to the container
*
* @param fragment pass android.support.v4.app.Fragment
* @param bundle pass your extra bundle if any
* @param popBackStack if true it will clear back stack
* @param findInStack if true it will load old fragment if found
*/
public void replaceFragment(Fragment fragment, @Nullable Bundle bundle, boolean popBackStack, boolean findInStack) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
String tag = fragment.getClass().getName();
Fragment parentFragment;
if (findInStack && fm.findFragmentByTag(tag) != null) {
parentFragment = fm.findFragmentByTag(tag);
} else {
parentFragment = fragment;
}
// if user passes the @bundle in not null, then can be added to the fragment
if (bundle != null)
parentFragment.setArguments(bundle);
else parentFragment.setArguments(null);
// this is for the very first fragment not to be added into the back stack.
if (popBackStack) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else {
ft.addToBackStack(parentFragment.getClass().getName() + "");
}
ft.replace(R.id.contenedor_principal, parentFragment, tag);
ft.commit();
fm.executePendingTransactions();
}
use it like
Update :
If your fragment is home or dashboard fragment then
Fragment f = new YourFragment();
replaceFragment(f, null, true, true);
Otherwise
Fragment f = new YourFragment();
replaceFragment(f, null, false, true);
Important This code is not replacement of saving all states or variables in fragment. This code will useful because it will not create fragment instance again.
For saving all states and variables in fragment for future use see this answer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With