OnBackPress 显示的片段更新失败
OnBackPress the fragment to be shown fails to update
假设我在片段 A 中,然后移动到 B,然后使用返回按钮 returns 到 A。
在 activity 中,我正在执行以下覆盖:
@Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
Fragment frag = fm.findFragmentByTag(Consts.A);
if (frag != null){
Log.d(Consts.TAGS.ACTIVITY_ORDER,"");
fm.beginTransaction().remove(frag).commit();
fm.popBackStack();
}
}
显示 B 时是这样的:
FragmentManager fm = getActivity().getSupportFragmentManager();
Fragment f = BFragment.newInstance(Consts.B);
fm.beginTransaction()
.replace(R.id.rl_content,
f,
Consts.B)
.addToBackStack(null)
.commit();
现在,一旦我们执行popBackStack()
,A中将执行哪个方法(如果有的话)?
如果none,我们如何在返回后立即更改A的数据模型或UI组件(例如键盘或TextView
)?是否依赖于组件?
R.id.rl_content
是容器。
请考虑两种情况:
1. A在R.id.rl
中,正在被替换
2. A 不在 R.id.rl
中且未被替换
如果您总是从片段 B 返回到片段 A,反之亦然,我建议在片段本身内使用此解决方案。
@Override
public void onResume() {
super.onResume();
Fragment f = AFragment.newInstance(Consts.A);
if(getView() == null){
return;
}
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.replace(R.id.rl_content, f);
trans.addToBackStack(null);
trans.commit();
return true;
}
return false;
}
});
}
您可以使用相同的代码自由地从 B 移动到 A 以及从 A 移动到 B。如果你想要一个更动态的方法,例如你想从 Fragment A 转到 Fragment C,或从 Fragment B 转到 Fragment C,然后当你按返回时返回到堆栈上的前一个片段。我的目标是使用 Kyle Falconer's Solution here
以防 link 死亡,我将 post 代码放在这里:
@Override
public void onBackPressed(){
FragmentManager fm = getFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
Log.i("MainActivity", "popping backstack");
fm.popBackStack();
} else {
Log.i("MainActivity", "nothing on backstack, calling super");
super.onBackPressed();
}
}
我没有测试第二种解决方案,但使用第一种。
有几种方法可以更改 A 的数据模型或 UI 组件。
情况1:当A在R.id.rl_content
中被B替换时。在这种情况下,您可以简单地更新所需的模型或UI在片段 A 的 onCreateView。
情况2:当A没有被替换时。在这种情况下,片段 A 不知道何时更新其视图。在 activity 的 onBackpressed()
中,如果正在弹出片段 B,您可以调用片段 A 的 updateView() 方法。
@Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
FragmentB fragmentB = (FragmentB)fm.findFragmentByTag(Consts.B);
if (fragmentB != null){
Log.d(Consts.TAGS.ACTIVITY_ORDER,"");
fm.beginTransaction().remove(fragmentB).commit();
fm.popBackStack();
FragmentA fragmentA = (FragmentA)fm.findFragmentByTag(Consts.A);
if (fragmentA != null) {
fragmentA.updateView();
}
}
}
编辑
我了解到您还想处理隐藏键盘等场景。
为此,您可能希望将 backpress 事件传递给各个片段。有点像这样:
@Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
FragmentB fragmentB = (FragmentB)fm.findFragmentByTag(Consts.B);
if (fragmentB != null){
if (!fragmentB.onBackPress()) {
// This means fragment B doesn't want to consume backpress therefore remove it.
Log.d(Consts.TAGS.ACTIVITY_ORDER,"");
fm.beginTransaction().remove(fragmentB).commit();
fm.popBackStack();
FragmentA fragmentA = (FragmentA)fm.findFragmentByTag(Consts.A);
if (fragmentA != null) {
fragmentA.updateView();
}
}
}
}
然后在您的 Fragment B 中创建一个 onBackPress 函数,如下所示:
public boolean onBackPressed() {
// if keyboard is showing then hide it here and return true to consume the back press event or else return false to dismiss this fragment.
}
假设我在片段 A 中,然后移动到 B,然后使用返回按钮 returns 到 A。 在 activity 中,我正在执行以下覆盖:
@Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
Fragment frag = fm.findFragmentByTag(Consts.A);
if (frag != null){
Log.d(Consts.TAGS.ACTIVITY_ORDER,"");
fm.beginTransaction().remove(frag).commit();
fm.popBackStack();
}
}
显示 B 时是这样的:
FragmentManager fm = getActivity().getSupportFragmentManager();
Fragment f = BFragment.newInstance(Consts.B);
fm.beginTransaction()
.replace(R.id.rl_content,
f,
Consts.B)
.addToBackStack(null)
.commit();
现在,一旦我们执行popBackStack()
,A中将执行哪个方法(如果有的话)?
如果none,我们如何在返回后立即更改A的数据模型或UI组件(例如键盘或TextView
)?是否依赖于组件?
R.id.rl_content
是容器。
请考虑两种情况:
1. A在R.id.rl
中,正在被替换
2. A 不在 R.id.rl
中且未被替换
如果您总是从片段 B 返回到片段 A,反之亦然,我建议在片段本身内使用此解决方案。
@Override
public void onResume() {
super.onResume();
Fragment f = AFragment.newInstance(Consts.A);
if(getView() == null){
return;
}
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.replace(R.id.rl_content, f);
trans.addToBackStack(null);
trans.commit();
return true;
}
return false;
}
});
}
您可以使用相同的代码自由地从 B 移动到 A 以及从 A 移动到 B。如果你想要一个更动态的方法,例如你想从 Fragment A 转到 Fragment C,或从 Fragment B 转到 Fragment C,然后当你按返回时返回到堆栈上的前一个片段。我的目标是使用 Kyle Falconer's Solution here
以防 link 死亡,我将 post 代码放在这里:
@Override
public void onBackPressed(){
FragmentManager fm = getFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
Log.i("MainActivity", "popping backstack");
fm.popBackStack();
} else {
Log.i("MainActivity", "nothing on backstack, calling super");
super.onBackPressed();
}
}
我没有测试第二种解决方案,但使用第一种。
有几种方法可以更改 A 的数据模型或 UI 组件。
情况1:当A在R.id.rl_content
中被B替换时。在这种情况下,您可以简单地更新所需的模型或UI在片段 A 的 onCreateView。
情况2:当A没有被替换时。在这种情况下,片段 A 不知道何时更新其视图。在 activity 的 onBackpressed()
中,如果正在弹出片段 B,您可以调用片段 A 的 updateView() 方法。
@Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
FragmentB fragmentB = (FragmentB)fm.findFragmentByTag(Consts.B);
if (fragmentB != null){
Log.d(Consts.TAGS.ACTIVITY_ORDER,"");
fm.beginTransaction().remove(fragmentB).commit();
fm.popBackStack();
FragmentA fragmentA = (FragmentA)fm.findFragmentByTag(Consts.A);
if (fragmentA != null) {
fragmentA.updateView();
}
}
}
编辑
我了解到您还想处理隐藏键盘等场景。 为此,您可能希望将 backpress 事件传递给各个片段。有点像这样:
@Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
FragmentB fragmentB = (FragmentB)fm.findFragmentByTag(Consts.B);
if (fragmentB != null){
if (!fragmentB.onBackPress()) {
// This means fragment B doesn't want to consume backpress therefore remove it.
Log.d(Consts.TAGS.ACTIVITY_ORDER,"");
fm.beginTransaction().remove(fragmentB).commit();
fm.popBackStack();
FragmentA fragmentA = (FragmentA)fm.findFragmentByTag(Consts.A);
if (fragmentA != null) {
fragmentA.updateView();
}
}
}
}
然后在您的 Fragment B 中创建一个 onBackPress 函数,如下所示:
public boolean onBackPressed() {
// if keyboard is showing then hide it here and return true to consume the back press event or else return false to dismiss this fragment.
}