Activity 中 OnBackPressedCallback 的默认行为?
Default Behavior for OnBackPressedCallback in Activity?
我想在我的应用程序中实现导航组件中详述的 OnBackPressedCallback。该文档非常清楚如何在片段中添加此自定义行为,并且效果很好。阅读链接文档后,它指出您应该避免在 activity 中覆盖 onBackPressed
。我当前的 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();
}
}
最后一行super.onBackPressed();
是我不清楚的地方。在实现 OnBackPressedCallback
时,如何在 activity 中保留后退按钮的默认行为?这是我当前的实现:
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();
}
}
});
如果我不包含 setEnabled(false);
行,则会收到堆栈溢出错误,这是有道理的。但肯定有更优雅的方式来提供默认行为吗?
您不应该将所有这些逻辑放在一个 OnBackPressedCallback
中。相反,每个案例都应该是它自己的 自己的 回调,只有在它应该处理后退时才会启用。
您应该不在handleOnBackPressed()
中调用onBackPressed()
等。合同的一个重要部分是,当您收到 handleOnBackPressed()
的回调时,您必须在那里处理后退按钮。这正是您可以准确控制何时启用回调的原因。
这意味着你应该为你的覆盖行为创建一个 OnBackPressedCallback
(尽管你可能不应该用导航这样做)和另一个使用 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);
当然,如果您要覆盖 Activity 级别的内容,将您的逻辑保持在 onBackPressed()
中没有任何不利之处 - 根据 the documentation,从 Fragments 注册的任何回调等将在您调用 super.onBackPressed()
.
时正确调用
我想在我的应用程序中实现导航组件中详述的 OnBackPressedCallback。该文档非常清楚如何在片段中添加此自定义行为,并且效果很好。阅读链接文档后,它指出您应该避免在 activity 中覆盖 onBackPressed
。我当前的 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();
}
}
最后一行super.onBackPressed();
是我不清楚的地方。在实现 OnBackPressedCallback
时,如何在 activity 中保留后退按钮的默认行为?这是我当前的实现:
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();
}
}
});
如果我不包含 setEnabled(false);
行,则会收到堆栈溢出错误,这是有道理的。但肯定有更优雅的方式来提供默认行为吗?
您不应该将所有这些逻辑放在一个 OnBackPressedCallback
中。相反,每个案例都应该是它自己的 自己的 回调,只有在它应该处理后退时才会启用。
您应该不在handleOnBackPressed()
中调用onBackPressed()
等。合同的一个重要部分是,当您收到 handleOnBackPressed()
的回调时,您必须在那里处理后退按钮。这正是您可以准确控制何时启用回调的原因。
这意味着你应该为你的覆盖行为创建一个 OnBackPressedCallback
(尽管你可能不应该用导航这样做)和另一个使用 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);
当然,如果您要覆盖 Activity 级别的内容,将您的逻辑保持在 onBackPressed()
中没有任何不利之处 - 根据 the documentation,从 Fragments 注册的任何回调等将在您调用 super.onBackPressed()
.