52

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

我的当前目的地是:

mainHostFragment.findNavController().currentDestination

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

4

10 回答 10

46

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

根据对活动的创建事件回调,您应该通过以下方式与您的 Fragment 进行通信

  • 让 Fragment 在其onAttach方法中注册一个回调,将您的 Activity 转换为您提供的接口的实例
  • ViewModel使用您的 Activity 和 Fragment 用于通信的共享。
于 2018-06-04T22:25:18.417 回答
45

引用显示的片段(AndroidX):

爪哇

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

科特林

val navHostFragment: Fragment? =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment)
navHostFragment?.childFragmentManager?.fragments?.get(0)

nav_host_fragment是您的标签fragment的IDactivity_main.xmlandroid:name="androidx.navigation.fragment.NavHostFragment"

于 2019-12-11T06:06:29.117 回答
30

你可以这样做:

  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)
            }
        }
    }

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

于 2018-08-22T08:18:03.113 回答
13

基于其他答案

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

((Your Fragment Class) fragment).(public method inside the fragment)

为我工作

于 2019-12-31T22:50:36.563 回答
8

使用 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
}

像这样使用:

val myFragment = activity.getFragment(MyFragment::class.java)
于 2018-11-16T02:57:55.103 回答
3

@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);

  }

}enter code here

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);
}
于 2020-06-09T06:16:51.693 回答
2

我用androidx发布了我的完整答案。关心:在我的情况下,我需要检索一个子片段(不能是第一个)。

MainActivity你应该有类似的东西:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        mAppBarConfiguration = new AppBarConfiguration.Builder(
                 R.id.mytest, R.id.nav_help)
                .setDrawerLayout(drawer)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
        NavigationUI.setupWithNavController(navigationView, navController);
...

然后你必须创建一个方法来检索好的片段。

 private MyTestFragment getMyTestFragment(){
        MyTestFragment resultFragment = null;
        Fragment navHostFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
        if(navHostFragment != null && navHostFragment.getChildFragmentManager() != null) {
            List<Fragment> fragmentList = navHostFragment.getChildFragmentManager().getFragments();
            for (Fragment fragment : fragmentList) {
                if (fragment instanceof MyTest) {
                    resultFragment = (MyTest) fragment;
                    break;
                }
            }
        }
        return resultFragment;
    }

最后你明白了。

于 2020-08-12T11:11:12.820 回答
2

从具有 NavHostFragment 的 Activity 中,可以使用下面的代码片段来检索 Active Fragment 的实例。

科特林

val currentFragment = mNavHostFragment?.childFragmentManager?.primaryNavigationFragment

爪哇

Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment();
Fragment currentFragment = navHostFragment.getChildFragmentManager().getFragments().get(0);
于 2020-05-17T16:15:39.453 回答
0

我认为有可能出现异常,因此您可以使用接口回调,这是从一端到另一端进行通信的可靠方法,只需通过代码下方的引用检查。

片段 A(){ interface ClickPostItemListener { fun onClicked(position: Int) }

val itemListener = object : ClickPostItemListener{
    override fun onClicked(position: Int) {
        postBackNForth(position)
    }

}  } Fragment B(clickItem:ClickPostItemListener ){ clickItem() }
于 2021-06-14T13:34:10.030 回答
0

真正处理这个问题的最好和正确的方法是使用接口。视图模型应该真正用于在活动和片段之间传递数据。这是我解决这个问题的方法:

创建接口

interface NavigationInterface {
    fun referenceCourseListFragment(fragment: CourseListFragment)
    fun referenceCouseDetailFragment(fragment: CourseDetailInfoFragment)
}

确保活动实现接口

class NotesActivity : AppCompatActivity(), NavigationInterface {}

确保为您需要引用的每个片段创建 lateinit var,然后

private lateinit var courseListFragment: CourseListFragment
private lateinit var courseDetailInfoFragment: CourseDetailInfoFragment

现在在 onCreateView 方法中的每个片段中,确保创建接口侦听器并使用接口回传片段

private lateinit var navigationInterface: NavigationInterface

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    //establish interface communication
    activity?.let {
        instantiateNavigationInterface(it)
    }
    // Inflate the layout for this fragment
    fragmentView = inflater.inflate(R.layout.fragment_course_list, container, 
    false)
    navigationInterface.referenceCourseListFragment(this)
    return fragmentView
}

现在回到活动中,您应该能够通过接口回调实例化片段对象以供参考

override fun referenceCourseListFragment(fragment: CourseListFragment) {
    courseListFragment = fragment
}

override fun referenceCouseDetailFragment(fragment: CourseDetailInfoFragment) 
{
    courseDetailInfoFragment = fragment
}
于 2021-01-07T16:15:22.620 回答