For a long time I have been investigating how to save the states between fragments so when I return it is as if you had never left. Google Photos is a key example. When you scroll through your photos and then go to another fragment and return you stay exactly where you were. My question is how can this be achieved since my application loads different fragments and when they return to these they are recreated instead of loading their previous state as it happens with Google Photos. What I have tried:
Part of the code where the nav_host_fragment is defined since it is navView
appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_profile, R.id.navigation_locate, R.id.navigation_contact_messages, R.id.navigation_settings)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment);
//NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
navController = Navigation.findNavController(this, R.id.nav_host_fragment);
//NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
navView.setOnNavigationItemReselectedListener(menuItem -> {
});
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
if (destination.getLabel() != null) {
if (levelsFragment[0].equals(destination.getLabel().toString())) {
//reemplazar por accion
} else if (levelsFragment[1].equals(destination.getLabel().toString())) {
//reemplazar por accion
} else if (levelsFragment[2].equals(destination.getLabel().toString())) {
//reemplazar por accion
} else if (levelsFragment[3].equals(destination.getLabel().toString())) {
//reemplazar por accion
} else if (levelsFragment[4].equals(destination.getLabel().toString())) {
//reemplazar por accion
}
}
});
Xml of the MainActivity containing the bottomNavigation:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
style="@style/bottomNav"
android:layout_width="0dp"
app:itemTextColor="@color/quantum_grey"
android:animateLayoutChanges="true"
app:labelVisibilityMode="auto"
app:itemIconTint="@color/colorAccent"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu" />
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?actionBarSize"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/nav_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
For example in itemReselected I left it blank because every time I browse it would create a new instance for me. The addOnDestinationChangedListener figured this is where saving the state goes. Any help would be appreciated. Here is the page where it is perfectly explained what I want to achieve:Material.io
Bottom navigation behaves differently on Android and iOS. When you select a bottom navigation item (one that’s not currently selected), each platform displays different outcomes:
- On Android: the app navigates to a destination’s top-level screen. Any prior user interactions and temporary screen states are reset,
such as scroll position, tab selection, and in-line search.- On iOS: the destination reflects the user’s prior interaction. If the user previously visited that section of the app, they return to the last screen viewed (with its prior state preserved, if possible). Otherwise, the app navigates to the top-level screen.
Default platform navigation can be overridden when needed to improve the user experience. For example, an Android app that requires frequent switching between sections can preserve each section’s state. Or, an iOS app can return users to the top-level screen (or reset their scroll position) if it better suits the use case.
This is an email from the Google Issue Tracker. Where my concern is clearly expressed and that in Google Photos it is done correctly. THERE HAS TO BE A SOLUTION TO THE PROBLEM
The two biggest issues and annoyances of this bug for our end users with the new Navigation library and Bottom navigation bar are:
- Changing tab with the bottom bar resets the state and backstack of the previous tab/fragment, so our users are completely losing their navigation history (this is correctly implemented in Google Photos app)
- Pressing back from the root of one tab shows the initial tab/fragment instead of leaving the app"
I found this by searching the internet but it is in kotlin and there are things that I cannot understand very well and I don't know if it is exactly what I need: Code in GitHub