Closed omkar-tenkale closed 2 years ago
Used this approach
class BackHandler():ScopedServices.HandlesBack{
var callback : Callable<Boolean>? = null
override fun onBackEvent(): Boolean {
callback?.let { return it.call() } ?: return false
}
}
@Parcelize
class ABCKey() : DefaultFragmentKey(), DefaultServiceProvider.HasServices {
override fun instantiateFragment(): Fragment = ABCFragment()
override fun getScopeTag(): String = javaClass.name
override fun bindServices(serviceBinder: ServiceBinder) {
with(serviceBinder) {
add(BackHandler(),"BackHandler")
}
}
}
Inside fragment
private val backHandler by lazy { lookup<BackHandler>("BackHandler") }
backHandler.callback = object : Callable<Boolean>{
override fun call(): Boolean {
if(shouldHandle()){
//handleBackPress
return true
}
return false
}
}
Not sure if this can be improved 🤔 @Zhuinden
This is my current code for this
private val backPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
val topKey = backstack.top<FragmentKey>()
val fragment = supportFragmentManager.findFragmentByTag(topKey.fragmentTag)
if (fragment is BackHandler) {
val handled = fragment.onBackPressed()
if (handled) {
return
}
}
val handled = Navigator.onBackPressed(this@MainActivity)
if (handled) {
return
}
// default fallback
this.remove() // this is the only safe way to invoke onBackPressed while cancelling the execution of this callback
onBackPressed() // this is the only safe way to invoke onBackPressed while cancelling the execution of this callback
this@MainActivity.onBackPressedDispatcher.addCallback(this) // this is the only safe way to invoke onBackPressed while cancelling the execution of this callback
}
}
// ...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
onBackPressedDispatcher.addCallback(backPressedCallback)
...
}
@Suppress("RedundantModalityModifier")
override final fun onBackPressed() {
super.onBackPressed() // onBackPressed() was killed by Google (thanks Google)
}
And
interface BackHandler {
fun onBackPressed(): Boolean
}
Then in my Fragment I can do this:
override fun onBackPressed(): Boolean {
if(...) {
...
return true
}
return false
}
But when using this hacky-looking approach using OnBackPressedDispatcher
, it's actually possible to do this in the fragment (i relied on this in 1 fragment, which is why I'm using back like this in this project)
// Fragment onViewCreated
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressedCallback)
backPressedCallback.isEnabled = isOverlayShowing
}
onBackPressed() was killed by Google (thanks Google)
when?
(readme section not very clear)
@omkar-tenkale if you want to use OnBackPressedDispatcher
(which is internally used by BackHandler
in Compose), then you cannot use onBackPressed
because the order is wrong. You would execute your logic in onBackPressed
before super.onBackPressed
can try to delegate the back press to the Fragment's onBackPressedDispatcher
.
It is a major design oversight from Google, actually. It took me a while to be convinced that yes, removing the callback and re-adding the callback is the correct way to do it. In fact, it is the only correct way to do it. 🤨
But it also comes with that [targetSdkVersion 34 and Android Tiramisu deprecates onBackPressed()
entirely](https://developer.android.com/reference/android/app/Activity#onBackPressed()), so I guess they also noticed that AndroidX broke the expected behaviors. I have an issue tracking this https://github.com/Zhuinden/simple-stack/issues/259 but can't do much about it until Tiramisu is out.
oh, got it now, thx!
i know its possible with ScopedServices.HandlesBack but donno how