163

Before trying the Navigation component I used to manually do fragment transactions and used the fragment tag in order to fetch the current fragment.

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

Now in my main activity layout I have something like:

<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"
        />

How can I retrieve the current displayed fragment by the Navigation component? Doing

supportFragmentManager.findFragmentById(R.id.nav_host)

returns a NavHostFragment and I want to retrieve my shown 'MyFragment`.

Thank you.

Alin
  • 14,809
  • 40
  • 129
  • 218
  • 4
    There is no way to retrieve the current fragment https://stackoverflow.com/a/50689587/1268507 What are you trying to achieve? maybe there is some other solution for it. – Alex Jul 18 '18 at 05:27
  • I needed from my fragment to start a camera intent, take a picture and use the image taken. To do so, I've started an activity and waited for result in the `onActivityResult` of my main activity. Since I could not get the fragment, I simply moved all this into the fragment itself and seems to work. – Alin Jul 18 '18 at 08:14
  • Do you want to perform an operation on that fragment object. Or just you want which fragment is shown ? – Ranjan Jul 30 '18 at 08:07

38 Answers38

170

I managed to discover a way for now and it is as follows:

NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host);
navHostFragment.getChildFragmentManager().getFragments().get(0);

In case of course you know it is the first fragment. I am still investigating a way without this. I agree it is not the best way but that should be something for now.

Andrei T
  • 2,985
  • 3
  • 21
  • 28
  • 10
    It's great to see a working solution. I gave up on this and started using a shared viewModel between the activity and fragment, This means that I can pass events between them without the need of callbacks or direct access. – Alin Aug 07 '18 at 19:07
  • 2
    As mentioned in this bug report issue https://issuetracker.google.com/issues/119800853 this is not the correct method to do it. Please consider changing the correct answer ! – Nicolas Pietri Feb 02 '19 at 07:38
  • 3
    As it is mentioned, it is not the solution, it is a workaround until a proper solution is found. – Andrei T Feb 02 '19 at 09:15
  • In my case, the top fragment is not the one by zero index, but the one at the last index – Leo DroidCoder Feb 26 '19 at 17:51
  • In general you don't need to do that. If you need to do that there is a flaw in your architecture. At least if you combine it with navigation graph. – Andrei T Feb 28 '19 at 07:31
  • Andrei: in my case, I have a ProgressBar (waiting spinner) in main activity, and I now want to add a cancel button on the spinner. The cancel button in main activity needs to send a message to the fragment to cancel the operation. Should I ditch this approach, and instead create a ProgressBar view inside each fragment? It seems to me that "flawed architecture" can be another word for "this is hard to do with this (flawed?) platform" – Rowan Gontier May 03 '19 at 01:09
  • Add it as a separate question and link it here. – Andrei T May 16 '19 at 09:10
  • java.lang.IndexOutOfBoundsException: Index: 3 – Joseph Wambura Sep 04 '19 at 10:38
  • In the docs, it says "The order of the fragments in the list is the order in which they were added or attached." So I did this and it should be a little safer. But still not the best way.. `navHostFragment.childFragmentManager.fragments.firstOrNull { it.isVisible }` – Joshua King Sep 20 '19 at 16:19
  • 2
    This works, many thanks. I tried getPrimaryNavigationFragment() as suggested in the bug tracker but it doesn't get the job done. – Jerry Hu Jun 23 '20 at 02:21
  • getPrimaryNavigationFragment() fails to find the navHostFragment when you programmatically set a graph and you are on the startDestination. findViewById doesn't fail in that situation. – straya Aug 10 '20 at 13:17
  • 3
    Based on this solution I've created a kotlin function that can check whether the current fragment is of a specific type (instead of the id): `navHostFragment!!.childFragmentManager.fragments.any { it.javaClass == fragmentClass && it.isVisible }` Works quite similar. Hope it'll help anyone! – P Kuijpers Sep 01 '20 at 16:43
  • it looks ugly, hardcoded `get(0)` – user924 Dec 04 '21 at 17:59
88

There is no way I can find to retrieve the current fragment instance. However, you can get the ID of lastly added fragment using the code below.

navController.currentDestination?.getId()

It returns the ID in navigation file. Hope this helps.

IgorGanapolsky
  • 26,189
  • 23
  • 116
  • 147
slhddn
  • 1,917
  • 1
  • 15
  • 21
  • Thank you for your answer. I needed to retrieve the fragment so I can interact with it. Since navController can't return it, I ended using a shared viewmodel to talk between activity and its fragments – Alin Jul 28 '18 at 20:25
  • 16
    i expected that the returned id matches the id in the nav xml, but it does not, so in other words you cannot check navController.getCurrentDestination().getId()==R.id.myfrag – IulianT Feb 07 '19 at 16:52
  • 9
    @LeresAldtai It matches the ID of fragment in the navigation file. – slhddn Feb 07 '19 at 22:47
  • 1
    Thank you @slhddn. Your comment helped me and was able to retrieve the id from the fragment and make this work. Added an answer here with my code in case useful to someone else. Cheers. – Francislainy Campos Jul 15 '20 at 05:28
  • 2
    I still didn't understand how we can match if we are on the required fragment. findNavController().currentDestination.id value is 2131296642, R.id.myFragment value is 1000319. Though the ids don't matter, posting it for understanding. Basically I want to check and match which fragment I am on from a BaseFragment for setting up a common backpresscallback for all fragments. – akhilsreekar Jun 20 '21 at 22:50
  • @akhilsreekar When you're debugging, the R.id.xxx values are not the same for some reason. I see similar values as you described. However, even though both values appear different to the debugger, the comparison shows that they're equal... – Nicolas Oct 06 '21 at 15:14
  • 1
    @lulianT this will work: navController.currentDestination?.id == navController.graph[R.id.nav_graph_fragment_id].id – userVadim Sep 21 '22 at 19:25
58

You should look the childFragmentManager primaryNavigationFragment property of your nav fragment, this is where the current displayed fragment is referenced.

val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment)
    navHost?.let { navFragment ->
        navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment->
                //DO YOUR STUFF
        }
    }
}
Nicolas Pietri
  • 653
  • 5
  • 8
34

This seems like the cleanest solution. Update: Changed extension function to property. Thanks Igor Wojda.

1. Create the following extension

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

val FragmentManager.currentNavigationFragment: Fragment?
    get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()

2. In Activity with NavHostFragment use it like this:

val currentFragment = supportFragmentManager.currentNavigationFragment
Aleksandar Ilic
  • 1,521
  • 16
  • 19
  • 2
    Nice - one this I would change - I would define extension as property `FragmentManager.currentNavigationFragment` (not as a function) – Igor Apr 03 '20 at 13:00
  • Returns `null` each time with Navigation lib version `2.3.5` and gradle version `7.0.2`. I am using a `NavDrawer` perhaps that is interfering? Either way, went with a different, but similar solution. – Sakiboy Sep 20 '21 at 20:43
28

Use addOnDestinationChangedListener in activity having NavHostFragment

For Java

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

For Kotlin

var navController :NavController=Navigation.findNavController(this, R.id.nav_host_fragment)
    navController.addOnDestinationChangedListener { controller, destination, arguments ->
        Log.e(TAG, "onDestinationChanged: "+destination.label);

    }
Mukul Bhardwaj
  • 562
  • 5
  • 16
22

this might be late but for anyone who's still looking

val currentFragment = NavHostFragment.findNavController(nav_host_fragment).currentDestination?.id

then you can do something like

if(currentFragment == R.id.myFragment){
     //do something
}

note that this is for kotlin, java code should be almost the same

nuhkoca
  • 1,777
  • 4
  • 20
  • 44
MoTahir
  • 863
  • 7
  • 22
14

My requirement is to get the current visible fragment from Parent activity,my solution is

 private Fragment getCurrentVisibleFragment() {
        NavHostFragment navHostFragment = (NavHostFragment)getSupportFragmentManager().getPrimaryNavigationFragment();
        FragmentManager fragmentManager = navHostFragment.getChildFragmentManager();
        Fragment fragment = fragmentManager.getPrimaryNavigationFragment();
        if(fragment instanceof Fragment ){
            return fragment ;
        }
        return null;
    }

This may help some one with same problem.

CLIFFORD P Y
  • 16,974
  • 6
  • 30
  • 45
9
navController().currentDestination?.id

will give you your current Fragment's id where

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

this id is the id which you have given in your Navigation Graph XML file under fragment tag. You could also compare currentDestination.label if you want.

Abhishek Bansal
  • 5,197
  • 4
  • 40
  • 69
8

First, you get the current fragment by id, then you can find the fragment, depending on that id.

int id = navController.getCurrentDestination().getId();
Fragment fragment = getSupportFragmentManager().findFragmentById(id);
Srikar Reddy
  • 3,650
  • 4
  • 36
  • 58
Abu-Bakr
  • 408
  • 6
  • 12
5

Found working solution.

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
    }
}
Tomas Kuhn
  • 141
  • 2
  • 4
  • 1
    currentDestination as FragmentNavigator.Destination will crash if you are navigating to a dialog. – TatiOverflow Aug 31 '21 at 18:11
  • @TatiOverflow you are right .. this will cause a crash...... so you can solve it by checking for type........ check my answer https://stackoverflow.com/a/75648904/5829679 – Muhamed El-Banna Mar 06 '23 at 09:07
4

As per @slhddn answer and comment this is how I'm using it and retrieving the fragment id from the nav_graph.xml file:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    setSupportActionBar(findViewById(R.id.toolbar))

    val navController = findNavController(this, R.id.nav_host_fragment)

    ivSettingsCog.setOnClickListener {

        if (navController.currentDestination?.id == R.id.updatesFragment) // Id as per set up on nav_graph.xml file
        {
            navController.navigate(R.id.action_updatesFragment_to_settingsFragment)
        }

    }

}

}
Francislainy Campos
  • 3,462
  • 4
  • 33
  • 81
4

Using navigation components, I got the current displayed fragment using this line of code:

val fragment = parentFragmentManager.primaryNavigationFragment
Jazib Khan
  • 408
  • 4
  • 13
3

From an Activity that uses NavHostFragment, you can use the code below to retrieve the instance of the Active Fragment.

val fragmentInstance = myNavHostFragment?.childFragmentManager?.primaryNavigationFragment
jjz
  • 2,007
  • 3
  • 21
  • 30
3

Within your activity, hosting the NavHostFragment we can write the following piece of code to fetch the instance of the currently displayed fragment

Fragment fragment = myNavHostFragment.getChildFragmentManager().findFragmentById(R.id.navHostFragmentId)
if(fragment instanceOf MyFragment) {
  //Write your code here
}

Here R.id.navHostFragmentId is the resId for the NavHostFragment within your activity xml

Maximus
  • 136
  • 1
  • 4
2

Make :

• in some button in your fragment:

val navController = findNavController(this)
  navController.popBackStack()

• In your Activity onBackPressed()

override fun onBackPressed() {
        val navController = findNavController(R.id.nav_host_fragment)
        val id = navController.currentDestination?.getId()
        if (id == R.id.detailMovieFragment){
            navController.popBackStack()
            return
        }

        super.onBackPressed()
    } 
2

The first fragment in navhost fragment is the current fragment

Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment();
if (navHostFragment != null) 
{Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);}
Eren Tüfekçi
  • 2,463
  • 3
  • 16
  • 35
  • Could you elaborate on your answer a bit more? Maybe by explaining your code. – Twenty Feb 12 '20 at 00:20
  • Code-only answers are discouraged. Please provide an explanation why and how your answer solves the problem. – Igor F. Feb 12 '20 at 08:14
  • This is the correct answer. Just test it. First we obtain the navigation's primary fragment which is used to allocate the fragments we inflate on navigation. Secondly we obtain the child fragment manager, which is the private fm the primary fragment has built inside to manage the different fragments we inflate. Lastly, all we have to do is obtain the last fragment inflated. Check a kotlin example working: val pF = supportFragmentManager.primaryNavigationFragment val cF = pF!!.childFragmentManager.fragments.last() cF.updateMethod() – Ramiro G.M. Feb 22 '21 at 02:43
2

Finally the working solution for those of you who are still searching Actually it is very simple and you can achieve this using callback.

follow these steps:

  1. Create a listener inside the fragment you want to get the instance from activity onCreate()

    public class HomeFragment extends Fragment {
    
    private OnCreateFragment createLIstener;
    
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        createLIstener.onFragmentCreated(this);
        View root = inflater.inflate(R.layout.fragment_home, container, false);
        //findViews(root);
        return root;
    }
    
    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.menu_main, menu);
    
    }
    
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId()==R.id.action_show_filter){
            //do something
        }
        return super.onOptionsItemSelected(item);
    }
    
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            createLIstener = (OnCreateFragment) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implement OnArticleSelectedListener");
            }
        }
    
        public interface OnCreateFragment{
            void onFragmentCreated(Fragment f);
        }
    }
    
  2. Implement your listener in the host Fragment/Activity

    public class MainActivity extends AppCompatActivity implements HomeFragment.OnCreateFragment {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            BottomNavigationView navView = findViewById(R.id.nav_view);
           // Passing each menu ID as a set of Ids because each
           // menu should be considered as top level destinations.
            AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                    R.id.navigation_home,
                    R. ----)
            .build();
            NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
            NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
            NavigationUI.setupWithNavController(navView, navController);
        }
    
        @Override
        public void onFragmentCreated(Fragment f) {
            if (f!=null){
                H.debug("fragment created listener: "+f.getId());
                f.setHasOptionsMenu(true);
            }else {
                H.debug("fragment created listener: NULL");
            }
        }
    }
    

And that is everything you need to do the job. Hop this help someone

2

The best way I could figure out with 1 fragment, Kotlin, Navigation usage:

On your layout file add the tag: "android:tag="main_fragment_tag""

<fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/nav_host"
        app:navGraph= "@navigation/nav_item"
        android:tag="main_fragment_tag"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost= "true"
        />

On your Activity:

val navHostFragment = supportFragmentManager.findFragmentByTag("main_fragment_tag") as NavHostFragment
val mainFragment = navHostFragment.childFragmentManager.fragments[0] as MainFragment
mainFragment.mainFragmentMethod()
patel dhruval
  • 1,002
  • 10
  • 12
2

Here is my solution for java

    NavHostFragment  navHostFragment= (NavHostFragment) getSupportFragmentManager().getFragments().get(0);
    MyFragment  fragment = (MyFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
    fragment.doSomething();
Luis Muñoz
  • 139
  • 1
  • 4
2

create extension function on Fragment Manager

inline fun <reified T : Fragment> FragmentManager.findNavFragment(hostId: Int): T? {

    val navHostFragment = findFragmentById(hostId)

    return navHostFragment?.childFragmentManager?.fragments?.findLast {
        it is T
    } as T?
}

Now simply use it by giving id of the hosting fragment and get the specified fragment

    val myFragment: MyFragment? = supportFragmentManager.findNavFragment<MyFragment>(R.id.nav_host_id)
Jalees Mukarram
  • 106
  • 1
  • 4
1

can you please check with getChildFragmentManager() call with

NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
AskNilesh
  • 67,701
  • 16
  • 123
  • 163
1

If you need the instance of your fragment, you can go with:

(Activity) => supportFragmentManager.fragments.first().childFragmentManager.fragments.first()

It's very ugly but from there you can check if it's an instance of the fragment you want to play around with

Ailelame
  • 11
  • 1
1

On Androidx, I have tried many methods for finding out required fragment from NavHostFragment. Finally I could crack it with below method

public Fragment getFunctionalFragment (String tag_name)
{
    NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
    FragmentManager navHostManager = Objects.requireNonNull(navHostFragment).getChildFragmentManager();

    Fragment fragment=null;
    List fragment_list = navHostManager.getFragments();

    for (int i=0; i < fragment_list.size() ; i ++ )
    {
        if ( fragment_list.get(i) instanceof HomeFragment && tag_name.equals("frg_home")) {
            fragment = (HomeFragment) fragment_list.get(i);
            break;
        }
    }

    return fragment;
}
Yevgeniy Leychenko
  • 1,287
  • 11
  • 25
Karthik
  • 11
  • 1
  • 1
    Welcome to SO! Please, before you post your answer, check it... Code is not clear. Another issue: if your are just bringing code, explain your solution a little bit, maximum when there are 16 more answers, so you should explain the Pros of your answer. – David García Bodego Oct 31 '19 at 07:52
1

This code works from me

NavDestination current = NavHostFragment.findNavController(getSupportFragmentManager().getPrimaryNavigationFragment().getFragmentManager().getFragments().get(0)).getCurrentDestination();

switch (current.getId()) {
    case R.id.navigation_saved:
        // WRITE CODE
        break;
}
Manaus
  • 407
  • 5
  • 9
Faisal Shaikh
  • 3,900
  • 5
  • 40
  • 77
1

this might be late but may help someone later.

if you are using nested navigations you can get id like this in Kotlin

val nav = Navigation.findNavController(requireActivity(), R.id.fragment_nav_host).currentDestination

and this is one of fragments in fragment_nav_host.xml

<fragment
    android:id="@+id/sampleFragment"
    android:name="com.app.sample.SampleFragment"
    android:label="SampleFragment"
    tools:layout="@layout/fragment_sample" />

and you can check all you need like this

if (nav.id == R.id.sampleFragment || nav.label == "SampleFragment"){}
Payam Monsef
  • 296
  • 3
  • 6
1
val fragment: YourFragment? = yourNavHost.findFragment()

Note: findFragment extension function is located in androidx.fragment.app package, and it's generic function

Narek Hayrapetyan
  • 1,731
  • 15
  • 27
1

You should try get fragmentHost and then get its first child then instanceof CustomFragment .

Here example

@Override
public void onBackPressed() {
    // get parent host
    Fragment fragmentHost = getSupportFragmentManager().findFragmentById(
            R.id.frame_container);
    // get first child fragment
    Fragment fragment = fragmentHost.getChildFragmentManager()
                                    .getFragments().get(0);
    if (fragment instanceof AccountFragment) {
        Log.d(STRING.TAG, "onBackPressed: home");
        if (doubleBackToExitPressedOnce) {
            super.onBackPressed();
            return;
        }
        
        this.doubleBackToExitPressedOnce = true;
        FancyToast.makeText(this, STRING.message_exit,
                            FancyToast.LENGTH_SHORT, FancyToast.INFO, false)
                  .show();
        
        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            
            @Override
            public void run() {
                doubleBackToExitPressedOnce = false;
            }
        }, STRING.delayMillis);
    } else {
        Log.d(STRING.TAG, "onBackPressed: not home");
        super.onBackPressed();
    }
}
Nguyen Huy
  • 11
  • 1
0

I combined Andrei Toaders answer and Mukul Bhardwajs answer with an OnBackStackChangedListener.

As an attribute:

private FooFragment fragment;

In my onCreate

NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host);
FragmentManager navHostManager = Objects.requireNonNull(navHostFragment).getChildFragmentManager();
FragmentManager.OnBackStackChangedListener listener = () -> {
        List<Fragment> frags = navHostManager.getFragments();
        if(!frags.isEmpty()) {
            fragment = (FooFragment) frags.get(0);
        }
};
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
        if(destination.getId()==R.id.FooFragment){
            navHostManager.addOnBackStackChangedListener(listener);
        } else {
            navHostManager.removeOnBackStackChangedListener(listener);
           fragment = null;
        }
});

This way i can get a fragment, which will be displayed later on. One even may be able to loop though frags and check multiple fragments with instanceof.

Xerusial
  • 525
  • 1
  • 5
  • 17
0

I need to do this to setup a bottom navigation view and I did it this way:

val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home)
        val bottomNavBar: BottomNavigationView = nav_content_view
        NavigationUI.setupWithNavController(bottomNavBar, navController)
0

The best way to achieve this is to register a fragment lifecycle callback.

As per the original question, if your NavHostFragment is defined as...

<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"
        />

Then in your main activity onCreate(..)...

nav_host.childFragmentManager.registerFragmentLifecycleCallbacks(
    object:FragmentManager.FragmentLifecycleCallbacks() {
        override fun onFragmentViewCreated(
            fm: FragmentManager, f: Fragment, v: View,
            savedInstanceState: Bundle?
        ) {
            // callback method always called whenever a
            // fragment is added, or, a back-press returns
            // to the start-destination
        }
    }
)

Other callback methods may be overridden to fit your requirements.

miguelt
  • 384
  • 4
  • 8
0

This solution will work in most situations Try this:

val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment?.parentFragment as MainFragment

or this:

val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment as MainFragment
user2288580
  • 2,210
  • 23
  • 16
0

This works for me

(navController.currentDestination as FragmentNavigator.Destination).className 

It will return canonicalName of your fragment

Inc
  • 469
  • 5
  • 5
0

Add the following method in your Activity class:

private Fragment getCurrentFragment() {
    NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager()
            .findFragmentById(R.id.nav_host);
    if (navHostFragment != null) return navHostFragment.getChildFragmentManager()
            .getPrimaryNavigationFragment();
    return null;
}

That's the shortest and cleanest solution for your problem.

Hope it helps!

Shahood ul Hassan
  • 745
  • 2
  • 9
  • 19
0

Kotlin version code for get currently active fragment in Navigation Graph

fun getCurrentFragmentInstance(activity: HomeActivity): Fragment? {
    val navHostFragment =
        activity.supportFragmentManager.primaryNavigationFragment as NavHostFragment?
    val fragmentManager: FragmentManager = navHostFragment!!.childFragmentManager
    return fragmentManager.primaryNavigationFragment
}
0

I did a bit different in my app than all these answers

  1. I created global variable in class myClass (myClass.kt)

    var currentFragmentName: String = "defaultValue"

  2. When in Fragment I update it (TagsFragment.kt)

    currentFragmentName = "tagsFragment"

  3. And in my case in back button (in parent activity of TagsFragment.kt)

    Log.d(TAG, myClass.currentFragmentName) val homeFragment = HomeFragment() if(InTorry.currentFragmentName=="tagsFragment"){ setCurrentFragment(homeFragment,"fragment_tag_home") }

awariat
  • 331
  • 1
  • 5
  • 22
0
private fun checkIfFragmentVisible(): Boolean {
    findNavController().currentDestination?.let { navDestination ->
        if (navDestination is FragmentNavigator.Destination)
            return navDestination.className == myFragment().javaClass.name

        if (navDestination is DialogFragmentNavigator.Destination)
            return navDestination.className == myFragment().javaClass.name
    }

    return false
}
Muhamed El-Banna
  • 593
  • 7
  • 21
0

To communicate between Activity and fragment it is better and easier now to use a shared viewmodel.

just pass activity context while creating the viemmodel instance both in activity and fragment. Look at the code below

In Activity

SharedViewModel sharedViewModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    sharedViewModel = new ViewModelProvider(this).get(SharedViewModel.class);
    // ...
}

In Fragment

SharedViewModel sharedViewModel;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
    // ...
}
Shubham Goel
  • 1,962
  • 17
  • 25
-2

In your activity define a fragment object. And from each fragment call this method by passing fragment object, like So the static fragment object will be overridden by current showing fragment every time.

//method in MainActivity
private static Fragment fragment;

public void setFragment(Fragment fragment){
this.fragment = fragment;
}

//And from your fragment class, you can call
((<yourActivity in which fragment present>)getActivity()).setFragment(<your fragment object>);

//if you want to set it directly;
 ((<yourActivity in which fragment present>)getActivity()).fragment=<your fragment object>;

You can also set callback from fragment to activity, for a better approach and pass your current fragment object.

Ranjan
  • 1,326
  • 18
  • 38
  • 3
    Thank you for your time. I was looking for something to use from the Navigation component itself. – Alin Jul 30 '18 at 20:54