[英]Default Behavior for OnBackPressedCallback in Activity?
I would like to implement the OnBackPressedCallback detailed in Navigation Components in my app.我想在我的应用程序中实现导航组件中详述的OnBackPressedCallback 。 The documentation is very clear on how to add this custom behavior in fragments, and works quite well.
该文档非常清楚如何在片段中添加此自定义行为,并且效果很好。 After reading the linked documentation, it states that you should avoid overriding
onBackPressed
in your activity.阅读链接的文档后,它指出您应该避免在您的活动中覆盖
onBackPressed
。 My current onBackPressed
method looks something like this:我当前的
onBackPressed
方法如下所示:
@Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
} else if (shouldOverrideBackPressed()) {
navigationController.popBackStack(R.id.main_fragment, false);
} else {
super.onBackPressed();
}
}
The last line super.onBackPressed();
最后一行
super.onBackPressed();
is what I'm not clear about.是什么我不清楚。 How do I retain the default behavior for the back button in an activity while implementing the
OnBackPressedCallback
?如何在实现
OnBackPressedCallback
保留活动中后退按钮的默认行为? This is my current implementation:这是我目前的实现:
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
} else if (shouldOverrideBackPressed()) {
navigationController.popBackStack(R.id.main_fragment, false);
} else {
setEnabled(false);
MainActivity.this.onBackPressed();
}
}
});
If I don't include the setEnabled(false);
如果我不包括
setEnabled(false);
line, then I get a Stack Overflow error, which makes sense.行,然后我收到堆栈溢出错误,这是有道理的。 But surely there is a more elegant way to provide default behavior?
但是肯定有一种更优雅的方式来提供默认行为吗?
You shouldn't be putting all of that logic in one OnBackPressedCallback
.您不应该将所有这些逻辑放在一个
OnBackPressedCallback
。 Instead, each case should be its own callback that is only enabled when it is the one that should be handling the back pressed.相反,每个 case 都应该是它自己的回调,只有在它应该处理 backpressed 时才启用它。
You should not be calling onBackPressed()
, etc in handleOnBackPressed()
.你不应该调用
onBackPressed()
等在handleOnBackPressed()
An important part of the contract is that when you get a callback to handleOnBackPressed()
, you must handle the back pressed button there.契约的一个重要部分是,当您收到
handleOnBackPressed()
的回调时,您必须处理那里的后退按钮。 That's precisely why you have control over exactly when the callback is enabled or not.这正是您可以准确控制何时启用回调的原因。
This means you should create one OnBackPressedCallback
for your override behavior (although you should probably not being doing that with Navigation anyways) and another for the DrawerLayout
that uses a DrawerListener
for enabling and disabling the callback:这意味着您应该为您的覆盖行为创建一个
OnBackPressedCallback
(尽管您可能无论如何都不应该使用 Navigation 这样做),并为使用DrawerListener
启用和禁用回调的DrawerLayout
另一个:
OnBackPressedDispatcher dispatcher = getOnBackPressedDispatcher();
final OnBackPressedCallback overrideCallback = new OnBackPressedCallback(false) {
@Override
public void handleOnBackPressed() {
navigationController.popBackStack(R.id.main_fragment, false);
}
};
// Whenever your `shouldOverrideBackPressed()` changes, you need to
// call setEnabled(true) or setEnabled(false) so that callback
// is only called exactly when it needs to handle the back button
// Add this one first since they are called in reverse order
dispatcher.addCallback(this, overrideCallback);
// Now set up the DrawerLayout's callback
final DrawerLayout drawerLayout = findViewById(R.id.your_drawer_layout);
final OnBackPressedCallback drawerCallback = new OnBackPressedCallback(
drawerLayout.isDrawerOpen(GravityCompat.START)) {
@Override
public void handleOnBackPressed() {
// Unconditionally close the drawer when it is open
drawerLayout.closeDrawer(GravityCompat.START);
}
};
// Now add a listener so that this callback is only
// enabled when the drawer is open
drawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
@Override
public void onDrawerClosed(View drawerView) {
// Assume you only have one drawer
drawerCallback.setEnabled(false);
}
@Override
public void onDrawerOpened(View drawerView) {
// Assume you only have one drawer
drawerCallback.setEnabled(true);
}
});
// Add it last so that it gets called before the overrideCallback
dispatcher.addCallback(this, drawerCallback);
Of course, if you're overriding things at the Activity level, there's no downside to keeping your logic in onBackPressed()
- as per the documentation , any callbacks registered from Fragments, etc. will correctly be called when you call super.onBackPressed()
.当然,如果您在 Activity 级别覆盖内容,那么将逻辑保留在
onBackPressed()
没有任何缺点 - 根据文档,当您调用super.onBackPressed()
时,将从 Fragment 等注册的任何回调正确调用super.onBackPressed()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.