Androidx OnBackPressedDispatcher - how to consume the back button press
Asked Answered
M

1

7

I would like the onBackPressedDispatcher to absorb the back button press event. Sometimes but I don't see an option for it. Whats happening is that we are just today trying to upgrade to onBackPressedDispatcher in androidX but we have already overridden onBackPressd in activity. so when our onBackPressedDispatcher calls OnBackPressedCallback afterwards there is also a call to activities onBackPressed override. we don't want that. the onBackpressed should be consumed on the spot. here is what I have so far:

const val TAG = "MyTag"

class MyActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first)
        MyTester(this)
    }

    override fun onBackPressed() {
        super.onBackPressed()
        Log.v(TAG, "Activities class back button Pressed")

    }

    inner class MyTester(var activity: AppCompatActivity) {
        init {
            addBackCB()
        }

        fun addBackCB() {
            var callback = object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    Log.v(TAG, "inner class MyTester back button")
                }
            }
            activity.onBackPressedDispatcher.addCallback(activity, callback);
        }
    }
}

Which prints the following:

V/MyTag: inner class MyTester back button
V/MyTag: Activities class back button Pressed

If I don't call super.onBackPressed() then the dispatcher does not even work. it needs that call.

Metry answered 7/9, 2019 at 21:13 Comment(0)
B
29

This is because the OnBackPressedDispatcher is called in ComponentActivity.onBackPressed(), if you look at the source code:

    @Override
    @MainThread
    public void onBackPressed() {
        mOnBackPressedDispatcher.onBackPressed();
    }

So you'll never reach your callback if you override onBackPressed and never call the super method. I think the whole idea behind OnBackPressedDispatcher is that you shouldn't have to override Activity.onBackPressed if you want your fragments to intercept back presses. This is mentioned in one of the guides.

If you really want your activity to handle the back press, you can try something like this in your override:

    if (onBackPressedDispatcher.hasEnabledCallbacks()) {
      // There's an active callback; let the fragment handle it
      super.onBackPressed()
    } else {
      // Do your activity's back press handling here
    }

Be careful doing this, though. After trying it myself, you might find that hasEnabledCallbacks will return true even when you haven't added any callbacks yourself. This is because your FragmentManager has its own back press callback that's going to be enabled whenever backStackEntryCount > 0. I'm not sure if there's a quick workaround for that.

Blotch answered 11/9, 2019 at 22:43 Comment(2)
hi, yes this is working but i have little question here when i backprress from nested fragment it working fine now i am on firstactivity now backpress open blank screenTufthunter
@SunilChaudhary, I'm not good at Kotlin, but I guess you can use an intent to redirect to the desired page maybe? At least this is what I've done for my project.Joletta

© 2022 - 2024 — McMap. All rights reserved.