androidkotlinandroid-fragmentsandroid-toolbarandroid-bottomnav

How to change label of fragment toolbar while using fragment manager with bottom navigation component


I got 3 fragments and 1 activity. MainActivity, CameraFragment, HomeFragment, HistoryFragment

I just want to save all HistoryFragment states so whenever user access it, it won't recreated again.

whatever, I have found the most common solution with fragmentManager

Here's all my codes,

MainActivity.kt

    class MainActivity : AppCompatActivity() {
    
         private val historyFragment = HistoryFragment()
         private val homeFragment = HomeFragment()
         private val cameraFragment = CameraFragment()
         private val fragmentManager = supportFragmentManager
    
    
         override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
    
         val ft = fragmentManager.beginTransaction()
                   ft.add(R.id.fragmentContainerView, historyFragment, Constants.TAG_HISTORY)
                     .hide(historyFragment)
                     .add(R.id.fragmentContainerView, homeFragment, Constants.TAG_HOME)
    
         cameraViewModel.activeFragment = if (hasPermission()) {
                     //camera
                     ft.add(R.id.fragmentContainerView, cameraFragment, Constants.TAG_CAMERA)
                     ft.hide(homeFragment)
    
                     cameraFragment
             } else {
                     //home
                     homeFragment
                    }
         ft.commit()

         val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment
         val navController = navHostFragment.findNavController()
         binding.bottomNav.setupWithNavController(navController)

         binding.bottomNav.setOnItemSelectedListener { item ->
             when (item.itemId) {
                 R.id.historyFragment -> {

                 when (cameraViewModel.activeFragment) {
                    is HomeFragment -> fragmentManager.beginTransaction().hide(cameraViewModel.activeFragment).show(historyFragment).commit()
                 }
         
                cameraViewModel.activeFragment = historyFragment
                item.isChecked = true
                true
            }
            
    }
}

HistoryFragment.kt

class HistoryFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
        ): View {

        binding = FragmentHistoryBinding.inflate(inflater, container, false)

        // tool bar
        (activity as AppCompatActivity).setSupportActionBar(binding.toolBarHistory)

        val appBarConfiguration = AppBarConfiguration(
            setOf(R.id.historyFragment, R.id.homeFragment, R.id.cameraFragment)
        )

        NavigationUI.setupActionBarWithNavController(requireActivity() as AppCompatActivity, findNavController(), appBarConfiguration)

        return binding.root
    }
}

toolbar in fragment_history.xml

<androidx.appcompat.widget.Toolbar
            android:id="@+id/tool_bar_history"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"/>

The problem is when I open app, MainActivity runs then it shows homeFragment and when I click on history item in bottom navigation, homeFragment gets hide and it shows historyFragment but with label Home in title bar not History

I have used Logcat and I have detected that when I call: navController.currentDestination?.id in historyFragment, I get id for homeFragment

I hope you give me solution for this or any other way to save fragment with no bugs thanks in advance


Solution

  • Well this should be a comment but I can't. Still, I'm sharing it with you in case you still don't find a solution.

    I don't have much context on what specifically you want to store from the fragment or why. I would still consider that if you want to store the entire state of a fragment [data or steps] while the activity is active, I would recommend using an activity-scoped view model

    private val someViewModel: SomeViewModel by activityViewModels()
    

    So that every change you want to store from the History fragment can be stored in the view model and then if you go to another fragment and then come back to the fragment, it gets this data and shows it to the user, so it is recreated but with the most recent data and not from scratch.

    As additional data to find this delegate you should add the dependency:

    implementation "androidx.fragment:fragment-ktx:1.6.1"