如何获取当前显示的片段?

Lee*_*fin 409 android android-intent android-layout android-fragments

我在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();
Run Code Online (Sandbox Code Playgroud)

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

ram*_*oid 434

在事务中添加片段时,应使用标记.

fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT");
Run Code Online (Sandbox Code Playgroud)

...以后如果要检查片段是否可见:

MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
   // add your code here
}
Run Code Online (Sandbox Code Playgroud)

另请参阅http://developer.android.com/reference/android/app/Fragment.html

  • 好的,但是我需要一种方法来立即获取当前显示的Fragment实例,而不是迭代地检查所有片段,然后决定现在在屏幕上显示哪个片段.我认为你的答案需要我的代码迭代检查我的每个片段,找出可见的片段...... (71认同)
  • 是的,但一次可以看到多个片段.所以没有什么比"唯一活跃的片段"...... (31认同)
  • 为什么每个人都赞同这个答案?当然,它是一个很好的代码,但没有回答通过标签获取特定片段的问题.但是Asker想要当前显示的片段,这意味着他不知道显示哪个片段.是的,可能有多个片段,但阅读问题只会在UI上显示1个片段....抱歉不得不downvote因为它没有回答问题上下文. (11认同)
  • 好吧,即使显示了几个片段,我仍然需要一种方法来获取它们......并且这种方法比迭代检查我的每个片段更好.我担心"get them"这样的方法就像getDisplayedFragment(),但不确定Android中是否有这样的方法 (6认同)
  • 我不知道为什么这对你来说是一个问题...你通常在一个活动中只有很少的碎片,如果它们是可见的,检查它们应该不是一个问题. (2认同)

小智 386

我知道这是一个老帖子,但之前也遇到了麻烦.找到了一个在onBackStackChanged()听力功能中做到这一点的解决方案

  @Override
    public void onBackPressed() {
        super.onBackPressed();

         Fragment f = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
      if(f instanceof CustomFragmentClass) 
        // do something with f
        ((CustomFragmentClass) f).doSomething();

    }
Run Code Online (Sandbox Code Playgroud)

这对我有用,因为我不想遍历每个片段,我必须找到一个可见的片段.希望它也可以帮助其他人.

  • 如果`.getFragmentManager`报告不兼容的类型,就像在我的情况下一样,这是因为我使用的是`android.support.app.v4.Fragment`,在这种情况下使用的正确方法是`getSupportFragmentManager` (44认同)
  • 正是在使用导航抽屉屏幕旋转后处理onBackPressed()时我正在寻找的东西.感谢您回来分享这个. (12认同)
  • 或者你可以使用`findFragmentByTag()`来代替`findFragmentById`,如果你在将片段添加到`fragmentManager.beginTransaction().add(containerID,frag,fragmentTag)时添加了标签.addToBackStack(fragmentTag).commit( );` (3认同)

Mat*_*rea 149

这是我的解决方案,我发现它适用于低碎片方案

public Fragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    if(fragments != null){
        for(Fragment fragment : fragments){
            if(fragment != null && fragment.isVisible())
                return fragment;
        }
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

  • 在某些情况下,`fragment`可以为null,例如弹出后栈时.所以最好使用`if(fragment!= null && fragment.isVisible())`. (13认同)
  • 方法不完整,因为可能不仅有一个片段可见 (8认同)
  • 从技术上讲,这应该根据问题标记为答案.Asker想要显示片段,不知道它是哪个片段.其他答案继续按标签获取片段 (3认同)

小智 76

每次显示片段时,都必须将其标记为backstack:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_ENTER_MASK);       
ft.add(R.id.primaryLayout, fragment, tag);
ft.addToBackStack(tag);
ft.commit();        
Run Code Online (Sandbox Code Playgroud)

然后,当您需要获取当前片段时,您可以使用此方法:

public BaseFragment getActiveFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}
Run Code Online (Sandbox Code Playgroud)

  • 我很确定这种技术不适用于与ViewPager一起使用的碎片,因为它们不是通过标签添加的.只是折腾那里. (4认同)
  • 当你调用`addToBackStack(tag)`时,这似乎才有效,但是如果你不想将片段添加到后栈呢? (3认同)

tai*_*iny 21

我用来查找当前显示片段的是以下代码.它很简单,现在对我有用.它运行在包含片段的活动中

    FragmentManager fragManager = this.getSupportFragmentManager();
    int count = this.getSupportFragmentManager().getBackStackEntryCount();
    Fragment frag = fragManager.getFragments().get(count>0?count-1:count);
Run Code Online (Sandbox Code Playgroud)

  • 您应该检查以确保count> 0,以便get(count-1)不会抛出IndexOutofBoundsException (3认同)

loc*_*ost 14

反应方式:

Observable.from(getSupportFragmentManager().getFragments())
    .filter(fragment -> fragment.isVisible())
    .subscribe(fragment1 -> {
        // Do something with it
    }, throwable1 -> {
        // 
    });
Run Code Online (Sandbox Code Playgroud)

  • 那怎么反应?你使用一个observable但它只会发出一次 (5认同)
  • 这只是一种矫枉过正.一个简单的增强型forloop可以做同样的事情,甚至更快. (5认同)

Tho*_*dax 11

我的方法基于try/catch,如下所示:

MyFragment viewer = null;
    if(getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT) instanceOf MyFragment){
    viewer = (MyFragment) getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT);
}
Run Code Online (Sandbox Code Playgroud)

但可能有更好的方法......

  • 什么是MY_TAG_FRAGMENT (2认同)
  • 我的问题是如何获取当前显示的片段,这意味着可能有很多片段,我只想获取当前显示的实例,为什么使用 (MyFragment) ?我的意思是它可以是屏幕上显示的任何片段......并且我想获取当前显示的片段。 (2认同)
  • 好吧,我真的不明白你的意思,我的意思是我需要一种方法来立即获取当前显示的 Fragment 实例,而不是迭代检查所有片段,然后决定现在在屏幕上显示哪个片段。 (2认同)

Caf*_*han 10

科特林方式;

val currentFragment = supportFragmentManager.fragments.last()
Run Code Online (Sandbox Code Playgroud)

  • 小心。如果之前没有任何碎片堆栈,可能会导致空异常! (2认同)
  • 正确的方法是:supportFragmentManager.fragments.last()?.getChildFragmentManager()?.getFragments()?.get(0) (2认同)

Cor*_*Roy 10

如果您使用的是AndroidX Navigation

val currentFragment = findNavController(R.id.your_navhost)?.currentDestination
Run Code Online (Sandbox Code Playgroud)

有关此导航组件的更多信息:https : //developer.android.com/guide/navigation/navigation-getting-started

  • 仅当您正确设置 AndroidX 导航并以某种方式调用您的 navHost“your_navhost”时,它才会编译。 (2认同)

Nat*_*tiv 9

那么,这个问题得到了很多的意见和关注,但仍然没有包含在从我的目的最简单的方法 - 使用getFragments().

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);
Run Code Online (Sandbox Code Playgroud)


Moh*_*eza 8

这有点晚了,但对于任何感兴趣的人:如果您知道FragmentManager中所需片段的索引,只需获取对它的引用并检查isMenuVisible()函数!这里 :

getSupportFragmentManager().getFragments().get(0).isMenuVisible()
Run Code Online (Sandbox Code Playgroud)

如果true它对用户可见等等!


小智 7

1)

ft.replace(R.id.content_frame, fragment, **tag**).commit();
Run Code Online (Sandbox Code Playgroud)

2)

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment currentFragment = fragmentManager.findFragmentById(R.id.content_frame);
Run Code Online (Sandbox Code Playgroud)

3)

if (currentFragment.getTag().equals(**"Fragment_Main"**))
{
 //Do something
}
else
if (currentFragment.getTag().equals(**"Fragment_DM"**))
{
//Do something
}
Run Code Online (Sandbox Code Playgroud)


Mr *_*r L 7

您可以查询哪个片段加载到“活动”内容框架中,并获取片段类或片段“简单名称”(作为字符串)。

public String getCurrentFragment(){
     return activity.getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();
}
Run Code Online (Sandbox Code Playgroud)

用法:

Log.d(TAG, getCurrentFragment());
Run Code Online (Sandbox Code Playgroud)

输出:

D/MainActivity: FragOne
Run Code Online (Sandbox Code Playgroud)


coo*_*994 6

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

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

fun currentVisibleFragment(): Fragment? {
    return supportFragmentManager.fragments.first()?.getChildFragmentManager()?.getFragments()?.get(0)
}
Run Code Online (Sandbox Code Playgroud)


Ano*_*p M 6

这应该有效 -

val visibleFragment = supportFragmentManager.fragments.findLast { fgm -> fgm.isVisible }
Timber.d("backStackIterator: visibleFragment: $visibleFragment")
Run Code Online (Sandbox Code Playgroud)


Nas*_*she 5

受到泰尼回答的启发,这是我的两分钱.从大多数其他实现中修改很少.

private Fragment getCurrentFragment() {
    FragmentManager fragmentManager = myActivity.getSupportFragmentManager();
    int stackCount = fragmentManager.getBackStackEntryCount();
    if( fragmentManager.getFragments() != null ) return fragmentManager.getFragments().get( stackCount > 0 ? stackCount-1 : stackCount );
    else return null;
}
Run Code Online (Sandbox Code Playgroud)

"myActivity"如果是您当前的活动或使用对您的活动的引用,请替换为"this".


Kev*_*vie 5

有一个叫方法findFragmentById()SupportFragmentManager.我在活动容器中使用它,如:

public Fragment currentFragment(){
    return getSupportFragmentManager().findFragmentById(R.id.activity_newsfeed_frame);
}
Run Code Online (Sandbox Code Playgroud)

这就是如何获得你的当前Fragment.如果您有自定义Fragment并需要检查Fragment它是什么,我通常使用instanceof:

if (currentFragment() instanceof MyFrag){
    // Do something here
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这是获取当前片段的简单方法..

getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
  @Override public void onBackStackChanged() {
    currentFragment = fragmentManager.findFragmentById(R.id.content);
    if (currentFragment !=  null && (currentFragment instanceof LoginScreenFragment)) {
      logout.setVisibility(View.GONE);
    } else {
      logout.setVisibility(View.VISIBLE);
    }
  }
});
Run Code Online (Sandbox Code Playgroud)


Har*_*han 5

查看此解决方案。获取当前 Fragment 对我有用。

if(getSupportFragmentManager().getBackStackEntryCount() > 0){
        android.support.v4.app.Fragment f = 
         getSupportFragmentManager().findFragmentById(R.id.fragment_container);
        if(f instanceof ProfileFragment){
            Log.d(TAG, "Profile Fragment");
        }else if(f instanceof SavedLocationsFragment){
            Log.d(TAG, "SavedLocations Fragment");
        }else if(f instanceof AddLocationFragment){
            Log.d(TAG, "Add Locations Fragment");
        }
Run Code Online (Sandbox Code Playgroud)


pab*_*ros 5

如果到达这里并且您正在使用Kotlin:

var fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
Run Code Online (Sandbox Code Playgroud)

R.id.fragment_containeridfragment是展示自己的activity

或者,如果您需要更好的解决方案:

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

    if (it is FooFragment) {
        // The presented fragment is FooFragment type
    }
}
Run Code Online (Sandbox Code Playgroud)


Sad*_*dan 5

就这么简单,不需要编写那么多代码 yourFragment.isAdded()yourFragment.isVisible()

我更喜欢 isAdded(),它们都返回布尔值在 if 条件中使用它,并且必须在 onCreate() 中初始化您的片段,否则您将获得空点异常。