Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if a fragment is presented or hidden?

Tags:

android

I am maintaining a backstack of fragments and pop the stack when back button is pressed. I need to reload data every time a fragment is made visible and do some cleanup when it gets hidden. For this I need to detect when a fragment is shown and hidden. This is a very common question but surprisingly none of accepted answers work for me. I

I am adding fragments to backstack using code like this:

public void pushFragment(Fragment f) {
    getFragmentManager().beginTransaction()
            .add(R.id.content_frame, f, null)
            .addToBackStack(null)
            .commit();
}

I am popping fragments off using this code:

public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 1) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

I am trying to detect from a fragment class when it becomes visible or hidden (either because it is being popped off the stack or another fragment was pushed on top). So far I have tried these callbacks:

  • onViewCreated/onDestroyView: Only called when the fragment is added to stack and popped off the stack. Not called when the fragment gets hidden or visible because of other fragments on the stack.
  • onHiddenChanged: Never called. Many have said on SO that this works. But not working for me for some reason.
  • setUserVisibleHint: Never called
  • onStart/onPause etc: They don't really apply here because they simply reflect the lifecycle of the host activity.

Is there a Fragment callback that will let me detect when a fragment is being shown or hidden? I will rather not use a backstack listener because I want every fragment class to have its own show/hide logic.

Edit: If I use replace() to add the fragment (instead of add()) then the view for the previously shown fragment gets destroyed. As a result if that fragment ever to appear on top of the stack again its view is recreated. In this situation onViewCreated/onDestroyView or onStart/onStop will be called every time a fragment is shown or hidden. I suppose I could use that approach. The down side is that the views are created and destroyed frequently. I might as well be using activities instead of fragments for master-detail navigation in that case.

like image 538
RajV Avatar asked Aug 30 '16 13:08

RajV


People also ask

How do you know if a fragment is visible?

fragment:fragment:1.1. 0 you can just use onPause and onResume callbacks to determine which fragment is currently visible for the user. onResume callback is called when fragment became visible and onPause when it stops to be visible.

How do you check if a fragment is null or not?

You can use findFragmentByTag() or findFragmentById() functions to get a fragment. If mentioned methods are returning null then that fragment does not exist.

How do I get the currently displayed fragment?

To get the current fragment that's active in your Android Activity class, you need to use the supportFragmentManager object. The supportFragmentManager has findFragmentById() and findFragmentByTag() methods that you can use to get a fragment instance.

Which method is called once the fragments gets visible?

onStart()The onStart() method is called once the fragment gets visible. onResume()Fragment becomes active.


1 Answers

Edit again If you need a callback you can override onHiddenChanged like this:

public void onHiddenChanged(boolean hidden) {
if(hidden){// Do you stuff here}
} 

As PPartisan mentioned you claimed that onHiddenChanged is never called.
The reason for that is because onHiddenChanged doesn't get called the first time an fragment is shown.

Called when the hidden state (as returned by isHidden()) of the fragment has changed. Fragments start out not hidden; this will be called whenever the fragment changes state from that.

To fix this: add this to your code:

FragmentTransaction mFragmentTransaction = getFragmentManager().beginTransaction();
if (f!= null) {
        mFragmentTransaction .hide(f);
    }
mFragmentTransaction.add(R.id.content_frame, f, null)
mFragmentTransaction.addToBackStack(null)
mFragmentTransaction.commit();

More on the on this SO thread

like image 171
Nir Duan Avatar answered Sep 29 '22 11:09

Nir Duan