0

假设我在片段A,然后移动到B,然后使用后退按钮返回到A. 在活动我执行以下控制装置:OnBackPress片段中显示未能更新

@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(); 
    } 
} 

和同时显示出乙是这样的:

   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的数据模型或UI组件(例如键盘或TextView)?它是否依赖于组件?

R.id.rl_content是容器。 请考虑两种情况: 1.在R.id.rl和被替换 2.不R.id.rl并没有被替换

回答

1

如果你总是从片段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。如果您想要更动态的方法,例如你想从片段A到片段C,或片段B到片段C,然后当你按回去回到栈上的前一个片段。我的目标是使用Kyle Falconer's Solution here

柜面链接死了,我会在这里张贴代码:

@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(); 
    } 
} 

我没有测试过第二个解决方案,但使用的第一个。

+1

+1,因为在大多数情况下,这些解决方案将可能工作(考虑到f将是最后一次) ,但在某些(显示/隐藏软键盘,权限拒绝等)这些将无法正常工作,我们回到原点。 – lionheart

+0

非常有效的一点,我会假设你会用相同的逻辑来解决这个问题,以便自己克服这些问题,例如onfocuschange监听器等等 – BIW

+0

我接受这个答案,因为我确实在各种情况下使用了链接,尤其是(fm.getBackStackEntryCount()> 0)条件。 – lionheart

1

您可以通过几种方式更改A的数据模型或UI组件。

案例1:当A是R.id.rl_content,并正在由B替换在这种情况下,你可以简单地在片段A.

案例onCreateView更新所需的模型或UI 2:当A是不被替换。在这种情况下,片段A不知道何时更新其视图。在你的活动的onBackpressed()中,如果Fragment B正在弹出,你可以调用Fragment 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(); 
       } 
      } 
     } 
    } 

而在你的片段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. 
} 
+0

+1,因为在案例2中 - 我确实使用了接口,并且此解决方案可能在大多数情况下都能正常工作,而案例1是正确的。但是,在某些情况下(例如软键盘,权限denail处理等),此解决方案(在大多数设备上)无法正常工作。我从来没有写过,但我确实提到过我已经尝试使用onBackPressed。 – lionheart

+1

好吧所以我明白你想要处理依赖于单个碎片的情况。在这种情况下,您应该从个别片段中询问他们是否想要处理后备事件。我已经在我的答案的编辑版本中解释了这一点。 –

+0

它不起作用,可能会有'hackish'的做法。看起来有些事情会让其他一些事情不起作用。这可能是特定的情况。我不确定。 – lionheart