How I can retrieve current fragment in NavHostFragment?

后端 未结 8 1308
遇见更好的自我
遇见更好的自我 2020-12-15 17:06

I tried to find a method in the new Navigation components but I didn\'t find anything about that.

I have the current destination with :

mainHostFrag         


        
相关标签:
8条回答
  • 2020-12-15 17:17

    Based on other answers

    Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment();
    Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);
    
    ((Your Fragment Class) fragment).(public method inside the fragment)
    

    worked for me

    0 讨论(0)
  • 2020-12-15 17:18

    Navigation does not provide any mechanism for getting the implementation (i.e., the Fragment itself) of the current destination.

    As per the Creating event callbacks to the activity, you should either communicate with your Fragment by

    • Having the Fragment register a callback in its onAttach method, casting your Activity to an instance of an interface you provide
    • Use a shared ViewModel that your Activity and Fragment use to communicate.
    0 讨论(0)
  • 2020-12-15 17:22

    I post my complete answer with androidx. Care : in my case i needed to retrieve one of the child fragment (could not be the first).

    In MainActivity you should have something like :

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

    Then you have to create a method to retrieve the good fragment.

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

    Finally you get it.

    0 讨论(0)
  • 2020-12-15 17:23

    @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);
    }
    
    0 讨论(0)
  • 2020-12-15 17:33

    Using Michal's answer I wrote this extension function for testing:

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

    Used like this:

    val myFragment = activity.getFragment(MyFragment::class.java)
    
    0 讨论(0)
  • 2020-12-15 17:38

    You can do something like this:

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

    But for more advanced communication Listeners with callback methods registered in Fragment.onAttach() (Fragment -> Activity rather one direction communication) and SharedViewModel (bidirectional, important to have ViewModelProviders, and Lifecycle owner that is scoped to getActivity() rather)

    0 讨论(0)
提交回复
热议问题