My app uses a BottomNavigationBar to switch between Fragments, and it does it this way:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BottomNavigationView bottomNav = findViewById(R.id.barra); bottomNav.setOnNavigationItemSelectedListener(navListener); getSupportFragmentManager().beginTransaction().replace(R.id.container, new KeyboardFragment()).commit(); bottomNav.setSelectedItemId(R.id.keyboard); } private BottomNavigationView.OnNavigationItemSelectedListener navListener = new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { Fragment selectedFragment = null; switch (item.getItemId()){ case R.id.camera: selectedFragment = new CameraFragment(); break; case R.id.keyboard: selectedFragment = new KeyboardFragment(); break; case R.id.settings: selectedFragment = new SettingsFragment(); break; } getSupportFragmentManager().beginTransaction().replace(R.id.container, selectedFragment).commit(); return true; } }; }
I want those Fragments
to be static, so their content and views do not dissapear when I switch between them. I have tried to create them inside MainActivity
‘s onCreate()
method, but it only helps with retaining text inside EditText
widgets, the rest of the views and content dissapear.
I have seen other similar questions, but they are answered poorly and I am new to this. Following some answers to similar questions, I have tried to use functions like add()
or attach()
instead of replace()
but I don’t think I’m doing it well; in fact sometimes my app crashes.
Should I paste here my layout.xml files too? The fragments are “displayed” into a simple FrameLayout
. Thanks beforehand 🙂
Advertisement
Answer
This is how I solved the problem succesfully:
- First of all, all of the Fragments are declared as fields inside
MainActivity
class, as well as the variableselected
, which will be used later:
public class MainActivity extends AppCompatActivity { public KeyboardFragment keyboard_fragment = new KeyboardFragment(); public CameraFragment camera_fragment = new CameraFragment(); public SettingsFragment settings_fragment = new SettingsFragment(); Fragment selected = teclado_fragment;` //...
- Then, the following methods are defined inside the class too, where
R.id.container
is the FrameLayout or whatever view that is being used to display the inflated Fragments:
private void createFragment(Fragment fragment){ getSupportFragmentManager().beginTransaction() .add(R.id.container, fragment) .hide(fragment) .commit(); } private void showFragment(Fragment fragment){ getSupportFragmentManager().beginTransaction() .show(fragment) .commit(); } private void hideFragment(Fragment fragment){ getSupportFragmentManager().beginTransaction() .hide(fragment) .commit(); }
- Finally, whatever menu’s listener is defined this way inside
MainActivity
‘sOnCreate()
method:
private BottomNavigationView.OnNavigationItemSelectedListener navListener = new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()){ case R.id.camera: hideFragment(selected); selected = camera_fragment; showFragment(seleccionado); break; case R.id.keyboard: hideFragment(selected); selected = keyboard_fragment; showFragment(seleccionado); break; case R.id.settings: hideFragment(selected); selected = settings_fragment; showFragment(seleccionado); break; } return true; } };
This way, the menu just hides and shows Fragments visually, and they are only declared once not to be destroyed until the app closes, thus mantaining all their fields and views in memory as long as the app is running.