Kawsar
Kawsar

Reputation: 127

Close drawer navigation view on backpressed while using jetpack nagivation ui components

The first thing that I am mentioning is, onBackpressed() is deprecated in the activity scope. And I am facing the problem of closing the drawer layout onthe back button click. I am using the jetpack navigation component. When I click to the hamburger icon, the drawer is opening. After that if I click the back button it should close drawer first then the second time should exit the app but it's not closing the drawer.Without close the drawer app exits on first-time back button clicks. Now I want such behavior that while the drawer is open, it should close first when I click the back button of the device.

I am using single activity pattern and jetpack navigation ui components. My codes are right below

// jetpack navigation with kotlin
def nav_version = "2.6.0-alpha01"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

and this is the codes in my Mainactivity.kt

class MainActivity : AppCompatActivity() {

    private val binding by viewBinding(ActivityMainBinding::inflate)
    lateinit var controller: NavController
    lateinit var config: AppBarConfiguration
    lateinit var listener: NavController.OnDestinationChangedListener


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        //set the toolbar as default action bar
        setSupportActionBar(binding.toolbar)
        supportActionBar?.setDisplayShowHomeEnabled(true)
        supportActionBar?.setDisplayShowHomeEnabled(true)

        //set the toolbar with navigation graph
        val host = supportFragmentManager
            .findFragmentById(R.id.fragmentContainerView) as NavHostFragment

        controller = host.navController
        config = AppBarConfiguration(controller.graph, binding.drawerLayout)
        setupActionBarWithNavController(controller, config)
        //set navview to navcontroller
        binding.navView.setupWithNavController(controller)

        //nav listener
        listener = NavController
            .OnDestinationChangedListener { controller, destination, arguments ->}

    }
    override fun onSupportNavigateUp(): Boolean {
        return controller.navigateUp(config) || super.onSupportNavigateUp()

    }
    override fun onResume() {
        super.onResume()
        controller.addOnDestinationChangedListener(listener)
    }
    override fun onPause() {
        super.onPause()
        controller.removeOnDestinationChangedListener(listener)
    }
}

Upvotes: 4

Views: 1006

Answers (3)

Ananthakrishnan K R
Ananthakrishnan K R

Reputation: 379

According to this I/O talk, It is recommended to enable the callback when drawer is open and disable when drawer is closed.

val callback = onBackPressedDispatcher.addCallback(this, false) {
    binding.drawerLayout.closeDrawer(GravityCompat.START)
}
            
binding.drawerLayout.addDrawerListener(object : DrawerListener {  
        
    override fun onDrawerOpened(drawerView: View) {
        callback.isEnabled = true
    }
        
    override fun onDrawerClosed(drawerView: View) {
        callback.isEnabled = false
    }

    override fun onDrawerSlide(drawerView: View, slideOffset: Float) = Unit    
    override fun onDrawerStateChanged(newState: Int) = Unit
})

Here is the Offical documentation

Upvotes: 2

Sam Chen
Sam Chen

Reputation: 8857

At the bottom of you onCreate():

onBackPressedDispatcher.addCallback {
    if (drawerLayout.isOpen) drawerLayout.close() else finish()
}

Upvotes: 0

Malik Saifullah
Malik Saifullah

Reputation: 584

Drawer can be closed programmatically by using drawer.closeDrawer(Gravity.LEFT) or some other gravity depending on usecase.

Here is how you can handle onBackPress in your case.

onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                // Checking if drawer is open
                if (binding.drawerLayout.isDrawerOpen(binding.navView)) {
                    // Close the drawer on left
                    binding.drawerLayout.closeDrawer(Gravity.LEFT)
                } else {
                    // Drawer not open close the application
                    finish()
                }

            }
        })

You can check how to learn more how to handle onBackPressed() Here.
onBackPressed() deprecated, What is the alternative?

Upvotes: 1

Related Questions