4

I use a singe activity and embed multiple fragments into it. Now I would like to know within the single activity class, which Fragment is currently being displayed. How can I do this? I had a look at the solution from here How to know if a Fragment is Visible?

MyFragmentClass test = (MyFragmentClass) getSupportFragmentManager().findFragmentByTag("testID");
if (test != null && test.isVisible()) {
     //DO STUFF
}
else {
    //Whatever
}

But I don't know what to you for the parameter "testID". Further, I tried to implement the solution from Get the current fragment object

Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);

But here I get the error message: "Cannot resolve symbol 'fragment_container'"

Does anyone have an idea how to get the name of the current Fragment that is being displayed when using a single activity and multiple fragments approach?

VanessaF
  • 515
  • 11
  • 36

4 Answers4

2

I know there are already 2 answers on mine here but still have 1 more solution so I am writing it here. This is the code:

NavController navController = Navigation.findNavController(this, R.id.fragment);
        int id=navController.getCurrentDestination().getId();
      if(id==R.id.startGameFragment ){ // change the fragment id
          selectedPosition(0);

      }else if(id==R.id.gameFragment ){ // change the fragment id
          selectedPosition(1);

      }else if(id==R.id.endGameFragment ){ // change the fragment id
          selectedPosition(2);

      }
Sambhav Khandelwal
  • 3,585
  • 2
  • 7
  • 38
1

Your 1st approach:

If you want to find fragment by tag you need to set the tag first. You do it while making transaction, for ex:

getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, SheetEditorScreen.class, args, "testID" //Here you set the tag
)

and then you will be able to get fragment by tag as you did:

getSupportFragmentManager().findFragmentByTag("testID");

Your 2nd approach:

If you want to get fragment by id you need to pass container's view id which you declare in your activity's layout xml file (set in setContentView(R.id.main_activity)):

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   xmlns:app="http://schemas.android.com/apk/res-auto">

   <androidx.fragment.app.FragmentContainerView
       android:id="@+id/fragment_container" <--- here is the id
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

and then you can find the visible fragment with:

getSupportFragmentManager().findFragmentById(R.id.fragment_container);
Jan Rozenbajgier
  • 534
  • 4
  • 13
  • Thanks Jan for your answer. I have to admit that I have problems understanding both of your approaches. Regarding the 1 st approach: Where exactly do I have to use the code? In the onCreate method of the Fragment or in the activity? And what do you mean by "You do it while making transaction, for ex"? What is a transaction and what is ex? Regarding the 2nd approach: I don't have any FragmentContainerView in my layout file for the activity. I just use a navHostfragment. Furthermore, I have multiple Fragments. So shall I add your suggested XML code inside every Fragment? – VanessaF Apr 09 '22 at 13:52
  • Share your code where you create fragments, so I could explain it for your case – Jan Rozenbajgier Apr 09 '22 at 14:17
  • Thanks for your answer and effort. I really appreciate it. Actually my code is quite large (more than 500 lines) so I don't think sharing it is a good option. However, I just navigate to the different Fragments by using a onClickListener in the Main Activity and ask for the botton that has been pressed. Afterwards, I navigate to the corresponding Fragement. So the code looks like: `if(view.getId() == R.id.navigation_Fragment1) { navController.navigate(R.id.Fragment1);` } – VanessaF Apr 09 '22 at 14:24
  • need a line where you initialize navController – Jan Rozenbajgier Apr 09 '22 at 14:33
  • Thanks Jan for your comment. I initialize the navController within the `onCreate` method of the Main Activity by using the following line `navController = Navigation.findNavController(this, R.id.navHostfragment);` – VanessaF Apr 09 '22 at 14:35
  • I've never used nav controller, but maybe try `((FragmentActivity)getActivity()).getSupportFragmentManager().findFragmentById(R.id.navHostfragment);`. This should return currently visible fragment. – Jan Rozenbajgier Apr 09 '22 at 14:38
  • Thanks for your answer. When using `Fragment currentFragment = ((FragmentActivity)getActivity()).getSupportFragmentManager().findFragmentById(R.id.navHostfragment);` I get the error "Cannot resolve method 'getActivity()'". When using `Fragment currentFragment = (getSupportFragmentManager().findFragmentById(R.id.navHostfragment));` I get the error "Required type: android.app.Fragment Provided: androidx.fragment.app.Fragment" – VanessaF Apr 09 '22 at 14:47
  • Change it to: `androidx.fragment.app.Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.navHostfragment);` – Jan Rozenbajgier Apr 09 '22 at 15:01
  • Thanks for your answer. Now actually the code compiles and runs but when I print the current Fragment by using `Log.e("LogTag_Main", "currentFragment: " + currentFragment);` I get a very strange output `currentFragment: NavHostFragment{e6d2f4a} (bc743eb7-dba6-4de1-a3a2-580b9b4eb3c4 id=0x7f08013a)` and the very strange thing is that I always get exactly the same output no matter which Fragment is being displayed. When changing the fragment the main activity generates the same output when using your suggested approach – VanessaF Apr 09 '22 at 15:18
  • Thanks Jan for your effort. Unfortunately your suggested solutions did not really work. I am now using one of the solutions suggested by Sambhav. K. Still, I highly appreciate your help and effort. – VanessaF Apr 10 '22 at 07:48
1

Now, because I get clearer about your problem, I am adding another solution. That worked with FrameLayout and fragment transaction. But, this will work with NavController also. Try this code:

public Fragment getCurrentlyVisibleFragment(){
    Fragment navHostFragment = getSupportFragmentManager().findFragmentById(R.id.navHostFragment);
    return navHostFragment == null ? null : navHostFragment.getChildFragmentManager().getFragments().get(0);
}
Sambhav Khandelwal
  • 3,585
  • 2
  • 7
  • 38
0

You can do something like this:

  1. Create a field of Fragment in your activity. Like this:
private Fragment mCurrentlyDisplayingFragment;
  1. Whenever changing the fragment, just pass that fragment object to that. Like this:
MyFragment fragment = new MyFragment();
// show it in the frame layout
mCurrentlyDisplayingFragment = fragment;

Now, whenever you are checking, just check this field.

halfer
  • 19,824
  • 17
  • 99
  • 186
Sambhav Khandelwal
  • 3,585
  • 2
  • 7
  • 38
  • Thanks for your answer. I have to admit that I have problems understanding it. Where exactly shall I put the code of your 2. step? I just want to know in the main activity which is the fragment that is currently being displayed. – VanessaF Apr 09 '22 at 11:01
  • When looking at my 2 examples from Stackoverflow answers, do you know which value I should use for `"testID"` (approach 1) or `R.id.fragment_container` (approach 2)? – VanessaF Apr 09 '22 at 11:05
  • Whenever you change the fragment, you create an instance of that fragment right? Then you pass it to that. Now, when you change the fragment, you can pass that fragment to that `mCurrentlyDisplayingFragment` object. – Sambhav Khandelwal Apr 10 '22 at 04:47
  • And that second argumen (`testId`) t is used when you are changing the fragments using `FragmentTransaction`. Not nav controller – Sambhav Khandelwal Apr 10 '22 at 04:53