Android导航架构组件 - 获取当前可见片段

Ali*_*lin 47 android android-navigation android-jetpack

在尝试导航组件之前,我曾经手动执行片段事务并使用片段标记来获取当前片段.

val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment

现在在我的主要活动布局中,我有类似的东西:

<fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/nav_host"
        app:navGraph= "@navigation/nav_item"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost= "true"
        />
Run Code Online (Sandbox Code Playgroud)

如何通过导航组件检索当前显示的片段?干

supportFragmentManager.findFragmentById(R.id.nav_host)

返回一个NavHostFragment,我想检索我显示的'MyFragment`.

谢谢.

And*_*der 49

我设法找到了一种方法,现在如下:

NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host);
navHostFragment.getChildFragmentManager().getFragments().get(0);
Run Code Online (Sandbox Code Playgroud)

如果你知道它是第一个片段.我还在调查没有这个的方法.我同意这不是最好的方法,但这应该是现在的事情.

  • 很高兴看到一个有效的解决方案.我放弃了这一点并开始在活动和片段之间使用共享的viewModel,这意味着我可以在它们之间传递事件而无需回调或直接访问. (3认同)
  • 如前所述,这不是解决方案,而是一种解决方法,直到找到合适的解决方案。 (3认同)
  • 正如此错误报告问题 https://issuetracker.google.com/issues/119800853 中所述,这不是正确的方法。请考虑更改正确答案! (2认同)
  • 这有效,非常感谢。我按照错误跟踪器中的建议尝试了 getPrimaryNavigationFragment(),但它没有完成工作。 (2认同)
  • 基于这个解决方案,我创建了一个 kotlin 函数,可以检查当前片段是否属于特定类型(而不是 id): `navHostFragment!!.childFragmentManager.fragments.any { it.javaClass ==fragmentClass &amp;&amp; it. isVisible }` 工作原理非常相似。希望它能帮助任何人! (2认同)

slh*_*ddn 24

我无法找到检索当前片段实例的方法.但是,您可以使用下面的代码获取最后添加的片段的ID.

navController.getCurrentDestination().getId()
Run Code Online (Sandbox Code Playgroud)

它返回导航文件中的ID.希望这可以帮助.

  • 我希望返回的 id 与导航 xml 中的 id 匹配,但事实并非如此,因此换句话说,您无法检查 navController.getCurrentDestination().getId()==R.id.myfrag (11认同)
  • @LeresAldtai 它匹配导航文件中片段的 ID。 (5认同)
  • 我仍然不明白如果我们在所需的片段上我们如何匹配。findNavController().currentDestination.id 值为 2131296642,R.id.myFragment 值为 1000319。虽然 ids 并不重要,但发布它以供理解。基本上我想检查并匹配我在 BaseFragment 上的片段,以便为所有片段设置公共 backpresscallback。 (2认同)

Ale*_*lic 24

这似乎是最干净的解决方案。更新:将扩展功能更改为属性。感谢伊戈尔Wojda

1.创建以下扩展

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager

val FragmentManager.currentNavigationFragment: Fragment?
    get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()
Run Code Online (Sandbox Code Playgroud)

2.ActivityNavHostFragment使用这样的:

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

  • 很好 - 我要更改的一个 - 我会将扩展定义为属性 `FragmentManager.currentNavigationFragment` (而不是作为函数) (2认同)

Nic*_*tri 18

您应该查看导航片段的childFragmentManager primaryNavigationFragment属性,这是引用当前显示的片段的位置。

val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment)
    navHost?.let { navFragment ->
        navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment->
                //DO YOUR STUFF
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此方法现在记录在 fragmentManager https://issuetracker.google.com/issues/119800853 (3认同)

MoT*_*hir 13

这可能晚了,但对于仍在寻找的人

val currentFragment = NavHostFragment.findNavController(nav_host_fragment).currentDestination?.id
Run Code Online (Sandbox Code Playgroud)

然后你可以做类似的事情

if(currentFragment == R.id.myFragment){
     //do something
}
Run Code Online (Sandbox Code Playgroud)

请注意,这是针对 kotlin 的,java 代码应该几乎相同

  • 这是java代码,/sf/answers/4237779311/ (2认同)

Abh*_*sal 7

navController().currentDestination?.id
Run Code Online (Sandbox Code Playgroud)

会给你你当前Fragment的 id 在哪里

private fun navController() = Navigation.findNavController(this, R.id.navHostFragment)

Run Code Online (Sandbox Code Playgroud)

这个 id 是你Navigation Graph XMLfragment标签下的文件中给出的 id 。currentDestination.label如果你愿意,你也可以比较。


Muk*_*waj 6

用于addOnDestinationChangedListener具有NavHostFragment

 NavController navController= Navigation.findNavController(MainActivity.this,R.id.your_nav_host);

        navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
                Log.e(TAG, "onDestinationChanged: "+destination.getLabel());
            }
        });
Run Code Online (Sandbox Code Playgroud)


CLI*_*P Y 6

我的要求是从父活动中获取当前可见的片段,我的解决方案是

 private LoginFragment getCurrentVisibleFragment() {
        NavHostFragment navHostFragment = (NavHostFragment)getSupportFragmentManager().getPrimaryNavigationFragment();
        FragmentManager fragmentManager = navHostFragment.getChildFragmentManager();
        Fragment loginFragment = fragmentManager.getPrimaryNavigationFragment();
        if(loginFragment instanceof LoginFragment){
            return (LoginFragment)loginFragment;
        }
        return null;
    }
Run Code Online (Sandbox Code Playgroud)

这可能会帮助一些有同样问题的人。


Tom*_*uhn 5

找到工作解决方案。

private fun getCurrentFragment(): Fragment? {
    val currentNavHost = supportFragmentManager.findFragmentById(R.id.nav_host_id)
    val currentFragmentClassName = ((this as NavHost).navController.currentDestination as FragmentNavigator.Destination).className
    return currentNavHost?.childFragmentManager?.fragments?.filterNotNull()?.find {
        it.javaClass.name == currentFragmentClassName
    }
}
Run Code Online (Sandbox Code Playgroud)


Abu*_*akr 5

首先,您通过 id 获取当前片段,然后您可以根据该 id 找到片段。

int id = navController.getCurrentDestination().getId();
Fragment fragment = getSupportFragmentManager().findFragmentById(id);
Run Code Online (Sandbox Code Playgroud)