Search code examples
androidandroid-fragmentskotlinandroid-navigation-bar

Move between fragments without recreation- Kotlin


I'm trying to move between two fragments without recreation of them so the data in the previous fragment won't disappear.

I tried to look over the internet for answers and tried for hours but without success. I looked at those links:

After show() and hide() I also tried the AddToBackStack() but yet no success

class MainActivity : AppCompatActivity(){

    private val onNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        @Override
        when (item.itemId) {
            R.id.navigation_home -> {
                //replaceFragment(SignInFragment())
                supportFragmentManager.beginTransaction().hide(AllEventsFragment()).commit()
                supportFragmentManager.beginTransaction().show(SignInFragment()).commit()
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_events -> {
                //replaceFragment(AllEventsFragment())
                supportFragmentManager.beginTransaction().hide(SignInFragment()).commit()
                supportFragmentManager.beginTransaction().show(AllEventsFragment()).commit()
                if (currentUser.isNotEmpty()) {
                    updateRecyclerView()
                    sign_in_error?.visibility = View.INVISIBLE
                }
                return@OnNavigationItemSelectedListener true
            }
        }
        return@OnNavigationItemSelectedListener false
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        supportFragmentManager.beginTransaction().add(R.id.activity_main, AllEventsFragment(), "2").commit()
        supportFragmentManager.beginTransaction().add(R.id.activity_main, SignInFragment(), "1").commit()
        val navView: BottomNavigationView = findViewById(R.id.nav_view)
        navView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener)
        personInEvent = false
    }

The result is overlapping fragments without an option to really navigate between them. I really tried everything I know there are some answers over the internet but none of them helped me fix my issue. I would really appreciate some help with this frustrating issue.

Before navigation: Before navigation:

After navigation: After navigation:


Solution

  • supportFragmentManager.beginTransaction().hide(AllEventsFragment()).commit()
    

    your recreating your fragments every time! calling AllEventsFragment() is equivelant to new AllEventsFragment()

    you need to instantiate them first for example, your code needs to be like this,

        val fragment1: Fragment = SignInFragment()
        val fragment2: Fragment = AllEventsFragment()
        var active = fragment1
    
          override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
                supportFragmentManager.beginTransaction().add(R.id.activity_main,fragment2 , "2").commit()
                supportFragmentManager.beginTransaction().add(R.id.activity_main, fragment1, "1").commit()
                val navView: BottomNavigationView = findViewById(R.id.nav_view)
                navView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener)
                personInEvent = false
            }
    

    inside your listener

        R.id.navigation_home -> {
                     supportFragmentManager.beginTransaction().beginTransaction().hide(active).show(fragment1).commit();
                        active = fragment1;
                    return@OnNavigationItemSelectedListener true
                }
     R.id.navigation_events -> {
                    //replaceFragment(AllEventsFragment())
                    supportFragmentManager.beginTransaction().beginTransaction().hide(active).show(fragment2).commit();
    active = fragment2
    )
    
        //handle rest of the cases