我如何在NavHostFragment中检索当前片段?

Ben*_*ihr 10 android android-fragments kotlin android-architecture-components android-architecture-navigation

我试图在新的导航组件中找到一个方法,但我没有找到任何相关的方法.

我目前的目的地是:

mainHostFragment.findNavController().currentDestination
Run Code Online (Sandbox Code Playgroud)

但我无法获得任何对显示片段的引用.

isa*_*ent 34

参考显示的片段(AndroidX):

public Fragment getForegroundFragment(){
    Fragment navHostFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
    return navHostFragment == null ? null : navHostFragment.getChildFragmentManager().getFragments().get(0);
}
Run Code Online (Sandbox Code Playgroud)

这里nav_host_fragment是一个在的IDfragment在你的标签activity_main.xmlandroid:name="androidx.navigation.fragment.NavHostFragment"

  • 如果他们想检查当前片段是什么,`childFragmentManager.findFragmentById` 有什么帮助? (2认同)

ian*_*ake 18

导航不提供任何获取当前目的地的实现(即片段本身)的机制.

根据活动创建事件回调,您应该与Fragment by进行通信

  • 让Fragment在其onAttach方法中注册回调,将Activity转换为您提供的接口的实例
  • 使用ViewModel您的活动和片段用于通信的共享.

  • 所有链接都显示了如何在片段之间进行通信。但是如果导航不提供任何获取当前目的地实现的机制,我们如何从活动中调用片段方法? (7认同)
  • @服务器-请参阅[此问题](https://issuetracker.google.com/issues/119800853)以及如何使用`getPrimaryNavigationFragment()`来检索当前片段。 (4认同)
  • 非常感谢。有用。val navHostFragment = supportFragmentManager.primaryNavigationFragment as NavHostFragment val yourFragment = currentFragmentClassName.childFragmentManager.primaryNavigationFragment as YourFragment (2认同)

Mic*_*bro 12

你可以这样做:

  override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        val navHostFragment = supportFragmentManager.fragments.first() as? NavHostFragment
        if(navHostFragment != null) {
            val childFragments = navHostFragment.childFragmentManager.fragments
            childFragments.forEach { fragment ->
                fragment.onActivityResult(requestCode, resultCode, data)
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是对于更高级的通信,Fragment.onAttach()(Fragment -> Activity rather one direction communication)和SharedViewModel中注册了回调方法的监听器(bidirectional重要的是要有ViewModelProviders, and Lifecycle owner that is scoped to getActivity())


Ere*_*kçi 12

基于其他答案

Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment();
Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);

((Your Fragment Class) fragment).(public method inside the fragment)
Run Code Online (Sandbox Code Playgroud)

为我工作


Cam*_*lMG 7

使用 Michal 的回答,我编写了这个扩展函数用于测试:

@Suppress("UNCHECKED_CAST")
fun <F : Fragment> AppCompatActivity.getFragment(fragmentClass: Class<F>): F? {
    val navHostFragment = this.supportFragmentManager.fragments.first() as NavHostFragment

    navHostFragment.childFragmentManager.fragments.forEach {
        if (fragmentClass.isAssignableFrom(it.javaClass)) {
            return it as F
        }
    }

    return null
}
Run Code Online (Sandbox Code Playgroud)

像这样使用:

val myFragment = activity.getFragment(MyFragment::class.java)
Run Code Online (Sandbox Code Playgroud)

  • 您可以将其压缩为 `inline fun &lt;reified T : Fragment&gt; FragmentManager.findFragmentByClass(): T? =fragments.firstOrNull { 它是 T } 作为 T?` (2认同)

Sou*_*Das 5

你可以这样做:

@Override
public void onBackPressed() {
    super.onBackPressed();
   
    NavController navController = Navigation.findNavController(this, R.id.fragment);
    int id=navController.getCurrentDestination().getId();
    if(id == R.id.startGameFragment ){
        selectedPosition(0);
    } else if(id == R.id.gameFragment ){
        selectedPosition(1);
    } else if(id == R.id.endGameFragment){
        selectedPosition(2);
    }
}

private void selectedPosition(int pos){
    for (int i = 0; i >=nav_view.getMenu().size(); i++) {
        nav_view.getMenu().getItem(pos).setChecked(false);

    }
    nav_view.getMenu().getItem(pos).setChecked(true);
}
Run Code Online (Sandbox Code Playgroud)