【问题标题】:Is there a way to get fragment from top of stack?有没有办法从堆栈顶部获取片段?
【发布时间】:2013-02-22 16:15:39
【问题描述】:

我的 MainActivity 中有一个 ListFragment。这是我设置片段对象的方式。

FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment newFragment = new MyFragment();
fragmentTransaction.replace(R.id.framecontainer, newFragment, "tag");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

问题是当用户按下返回按钮时,我至少必须通过调用来更改操作栏和菜单

getActionBar().setTitle(title);
getActionBar().setDisplayHomeAsUpEnabled(isEnabled);
invalidateOptionsMenu();

我必须知道当前正在显示什么样的片段,以便我知道如何设置操作栏。我将设置选项作为参数存储在片段中。

String title = fragment.getArguments().getString("KEY_TITLE");
boolean isEnabled = fragment.getArguments().getBoolean("KEY_ISENABLED");

我确实搜索了相关问题,我意识到我可以通过调用来获取片段

MyFragment fragment = (MyFragment) getSupportFragmentManager()
        .findFragmentByTag("tag");

但是,我必须将所有标签存储在自定义堆栈中,并在每次用户按下 onBackPressed() 中的返回按钮时调用 pop()

那么,我的问题是有没有办法让我直接从堆栈中获取当前可见片段?

注意:请记住,片段类型不同,而不仅仅是 MyFragment。

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    这样的事情应该可以帮助您的活动在后台解决这个问题:

    private Fragment getCurrentFragment(){
        FragmentManager fragmentManager = getSupportFragmentManager();
        String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName();
        Fragment currentFragment = fragmentManager.findFragmentByTag(fragmentTag);
        return currentFragment;
    }
    
    @Override
    public void onBackPressed() {
        Fragment fragmentBeforeBackPress = getCurrentFragment();
        // Perform the usual back action
        super.onBackPressed();
        Fragment fragmentAfterBackPress = getCurrentFragment();
    }
    

    希望这会有所帮助。

    【讨论】:

    • 看来如果我按照你的方式做,我也必须设置fragmentTransaction.addToBackStack(tag);否则,我会得到 NullPointerException。所以 fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); 不是指标签名称
    • 是的......你将不得不检查空值和错误的数学((getBackStackEntryCount-1)> 0等)。我写的有点太快了。此外,没有标签添加的片段将显示为空。
    • @umerk44 您必须考虑在您的getCurrentFragment 实现中为空的backstack 名称。我更喜欢使用字符串名称来避免instanceof 类型检测,并且在调试时发现它最有帮助——执行一个打印出名称的 backstack walk/loop。
    • 我认为您将片段标记名(在添加或替换片段时使用)与回栈名称(只能用于使用该名称弹出片段)混合。我想知道上面是否真的有效。
    • 这是一个很好的答案!。谢谢
    【解决方案2】:
    FragmentManager.findFragmentById(fragmentsContainerId) 
    

    function 将链接返回到后台堆栈中的顶部 Fragment。使用示例:

        fragmentManager.addOnBackStackChangedListener(new OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                Fragment fr = fragmentManager.findFragmentById(R.id.fragmentsContainer);
                if(fr!=null){
                    Log.e("fragment=", f.getClass().getSimpleName());
                }
            }
        });
    

    编辑: 现在在 2018 年,FragmentManager 中有 getFragments 方法返回 List<Fragment>。来自文档:The order of the fragments in the list is the order in which they were added or attached。所以看起来我们可以从该列表中取出最后一个片段:

         List<Fragment> list = fragmentManager.getFragments();
         //get last one 
         Fragment topFragment = list.get(list.size() - 1);
    

    【讨论】:

    • 这看起来有点奇怪......但对我来说确实很好:)。文档确实说它会搜索 backstack,所以希望它总是从堆栈顶部搜索,在所有版本的 Android 中(手指交叉)。
    • 我一直在寻找这个。感谢您了解此侦听器的工作原理
    • getFragments 为我工作!我建议你把它放在评论的顶部以获得更多的知名度:)
    【解决方案3】:

    看起来有些事情已经变得更好了,因为下面的代码对我来说非常适合,但我没有在已经提供的答案中找到它,无论是在这里还是在邻居问题中。

    科特林:

    supportFragmentManager.fragments[supportFragmentManager.fragments.size - 1]
    

    Java:

    getSupportFragmentManager().getFragments()
    .get(getSupportFragmentManager().getFragments().size() - 1)
    

    【讨论】:

      【解决方案4】:

      已经有一个答案标记为正确,我的附加信息不会 与那个不同。但是,我在使用接收器时遇到了麻烦 确定接收者所在的片段是否是当前顶部 堆栈上的片段。你可以很容易地在很多 NPE 和 Index 中跑出界。 所以我写了这个,也许它对某人有帮助。

      private boolean isFragmentOnTop(Activity parentActivity, final String fragmentName){
              FragmentManager fmManager = parentActivity.getFragmentManager();
              if(fmManager.getBackStackEntryCount() == 0){
                  LOG.i("BackStack entry count is 0: " + this);
                  return false;
              }
              String fragmentNameOnStackTop = "";
              final FragmentManager.BackStackEntry topEntry = fmManager.getBackStackEntryAt(fmManager.getBackStackEntryCount() -1);
              if(topEntry != null) {
                  fragmentNameOnStackTop = topEntry.getName();
              }
              LOG.d("Got fragments name: " + fragmentNameOnStackTop);
              return fragmentNameOnStackTop != null ? fragmentNameOnStackTop.equals(fragmentName) : false;
          }
      

      请注意,这适用于具有一些片段的活动。请注意,如果您是 使用 ViewPager 和 childfragmentmanager。

      别忘了在FragmentTransaction.addToBackStack(fragmentName)中设置fragmentName

      【讨论】:

        【解决方案5】:

        这个辅助方法从栈顶获取片段:

        public Fragment getTopFragment() {
            if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
                return null;
            }
            String fragmentTag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
            return getSupportFragmentManager().findFragmentByTag(fragmentTag);
        }
        

        【讨论】:

          猜你喜欢
          • 2021-06-03
          • 2012-07-07
          • 2021-07-23
          • 1970-01-01
          • 2021-12-17
          • 2011-06-23
          • 1970-01-01
          • 2012-06-18
          • 2019-10-14
          相关资源
          最近更新 更多