我在Android中玩碎片。

我知道我可以通过使用以下代码更改一个片段:

FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMgr.beginTransaction();

MyFragment myFragment = new MyFragment(); //my custom fragment

fragTrans.replace(android.R.id.content, myFragment);
fragTrans.addToBackStack(null);
fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragTrans.commit();

我的问题是,在Java文件中,如何获得当前显示的片段实例?


当前回答

我发现findFragmentByTag不是那么方便。如果你在你的Activity或父Fragment中有字符串currentFragmentTag,你需要将它保存在onSaveInstanceState中并在onCreate中恢复。即使你这样做,当Activity重新创建时,onAttachFragment将在onCreate之前调用,所以你不能在onAttachFragment中使用currentFragmentTag(例如。更新一些基于currentFragmentTag的视图),因为它可能还没有恢复。

我使用以下代码:

Fragment getCurrentFragment() {
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if(fragments.isEmpty()) {
        return null;
    }
    return fragments.get(fragments.size()-1);
}

FragmentManager的文档中指出

列表中片段的顺序是它们被添加或附加的顺序。

当你需要做基于当前片段类型的事情时,只需使用MyFragment的getCurrentFragment()实例而不是currentFragmentTag.equals("my_fragment_tag")。

注意,onAttachFragment中的getCurrentFragment()不会得到附加的片段,而是之前附加的片段。

其他回答

如果你有嵌套片段,如viewpagers内部viewpagers等 你想要得到所有嵌套的片段。

感谢Matt Mombrea的好意,回答一个稍微调整的版本。

private List<Fragment> getVisibleFragments(List<Fragment> searchFragments, List<Fragment> visibleFragments) {
    if (searchFragments != null && searchFragments.size() > 0) {
        for (Fragment fragment : searchFragments) {
            List<Fragment> nestedFragments = new ArrayList<>();
            List<Fragment> childFMFragments = fragment.getChildFragmentManager().getFragments();
            List<Fragment> fmFragments = fragment.getFragmentManager().getFragments();
            fmFragments.retainAll(childFMFragments);
            nestedFragments.addAll(childFMFragments);
            nestedFragments.addAll(fmFragments);
            getVisibleFragments(nestedFragments, visibleFragments);
            if (fragment != null && fragment.isVisible()) {
                visibleFragments.add(fragment);
            }
        }
    }
    return visibleFragments;
}

用法如下:

List<Fragment> allVisibleFragments = getVisibleFragments(searchFragments, visibleFragments);

例如:

List<Fragment> visibleFragments = new ArrayList<>();
List<Fragment> searchFragments = MainActivity.this.getSupportFragmentManager().getFragments();
Toast.makeText(this, ""+getVisibleFragments(searchFragments, visibleFragments), Toast.LENGTH_LONG).show();

有点奇怪,但我看了FragmentManager$FragmentManagerImpl和以下工作为我:

public static Fragment getActiveFragment(Activity activity, int index)
{
    Bundle bundle = new Bundle();
    String key = "i";
    bundle.putInt(key,index);
    Fragment fragment=null;
    try
    {
        fragment = activity.getFragmentManager().getFragment(bundle, key);
    } catch(Exception e){}
    return fragment;
}

要获得第一个活动片段,请使用0作为索引

如果你在使用Kotlin:

var fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)

R.id.fragment_container是片段在其活动中呈现的id

或者如果你想要一个更好的解决方案:

supportFragmentManager.findFragmentById(R.id.content_main)?.let {
    // the fragment exists

    if (it is FooFragment) {
        // The presented fragment is FooFragment type
    }
}

我最近不得不这么做

public Fragment getCurrentFragment() {
     return fragmentManager.findFragmentById(R.id.container);
}

我终于找到了容器上的最后一个碎片。

以上30个答案都不适合我。但这是一个有效的答案:

使用Kotlin,当使用导航组件时:

fun currentVisibleFragment(): Fragment? {
    return supportFragmentManager.fragments.first()?.getChildFragmentManager()?.getFragments()?.get(0)
}