Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment.isVisible() returns false even when Fragment added and visible

I am perplexed by how Fragment.isVisible() is supposed to work. Even though I have a fragment added in Activity.create(), Fragment.isVisible() returns false even when FragmentManager.commitNow() is used.

Fragment.isVisible() returns false even in onResume(). However, when a UI button gets clicked the returned value is correct.

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

public final static String TAG = "HideFragmentOnChange";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ((Button)findViewById(R.id.my_button)).setOnClickListener(this);

    if(savedInstanceState == null){
        Fragment fragmentA = new FragmentA();

        Log.d(TAG, "onCreate: Before FragmentTransaction FragA: " + (fragmentA.isVisible() ? "visible" : "not visible"));

        getSupportFragmentManager().beginTransaction()
                .add(R.id.fragment_container, fragmentA, "fragA")
                .commitNow();

        Log.d(TAG, "onCreate: After FragmentTransaction FragA: " + (fragmentA.isVisible() ? "visible" : "not visible"));

    }

    this.runOnUiThread(new Runnable(){
        @Override
        public void run() {
            Fragment fragA = getSupportFragmentManager().findFragmentByTag("fragA");
            Log.d(TAG, "runOnUiThread after onCreate(): FragA: " + (fragA.isVisible() ? "visible" : "not visible"));
        }
    });
}

@Override
protected void onResume() {
    super.onResume();

    Fragment fragA = getSupportFragmentManager().findFragmentByTag("fragA");
    Log.d(TAG, "onResume: FragA: " + (fragA.isVisible() ? "visible" : "not visible"));

    this.runOnUiThread(new Runnable(){
        @Override
        public void run() {
            Fragment fragA = getSupportFragmentManager().findFragmentByTag("fragA");
            Log.d(TAG, "runOnUiThread after onResume(): FragA: " + (fragA.isVisible() ? "visible" : "not visible"));
        }
    });
}

@Override
public void onClick(View v) {
    Fragment fragmentA = getSupportFragmentManager().findFragmentByTag("fragA");
    Log.d(TAG, "onClick(): FragA: " + (fragmentA.isVisible() ? "visible" : "not visible"));
}

}

I initially thought that perhaps it is because the main thread has not had the chance to run yet and the FragmentTransaction does not fully and properly commit until a later point. However, calling runOnUiThread does not change the return value of isVisible().

I am attaching the log for reference.

03-15 17:22:34.978 14094-14094/ D/HideFragmentOnChange: onCreate: Before FragmentTransaction FragA: not visible
03-15 17:22:34.990 14094-14094/ D/HideFragmentOnChange: onCreate: After FragmentTransaction FragA: not visible
03-15 17:22:34.991 14094-14094/ D/HideFragmentOnChange: runOnUiThread after onCreate(): FragA: not visible
03-15 17:22:34.996 14094-14094/ D/HideFragmentOnChange: onResume: FragA: not visible
03-15 17:22:34.996 14094-14094/ D/HideFragmentOnChange: runOnUiThread after onResume(): FragA: not visible
03-15 17:22:56.683 14094-14094/ D/HideFragmentOnChange: onClick(): FragA: visible

Why does Fragment.isVisible() seem to return the correct value with such a big delay?

I am using support library 25.2 and support library Fragments although native fragments produced the same behavior.

like image 692
Chris Balavessov Avatar asked Mar 15 '17 15:03

Chris Balavessov


People also ask

What does the onCreateView () method return if a fragment doesn't have any?

onCreateView() : The system calls this callback when it's time for the fragment to draw its user interface for the first time. To draw a UI for your fragment, you must return a View component from this method that is the root of your fragment's layout. You can return null if the fragment does not provide a UI.

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

userVisibleHint = false to mark that fragment is not visible to user.

Which method is called once fragment is visible?

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

How do you know if a fragment is destroyed?

Since all fragments are destroyed if the activity is destroyed, a simple answer could be calling getActivity(). isDestroyed() returning true if the activity is destroyed, therefore the fragment is destroyed.


2 Answers

There is a method for Fragments :

     getUserVisibleHint();

You can find more information in official document.

It gives "true" when fragment is visible to user and "false" when it is invisible.

Enjoy!

like image 106
dcanbatman Avatar answered Oct 10 '22 10:10

dcanbatman


You can use setUserVisibleHint

Form the Documentation

Set a hint to the system about whether this fragment's UI is currently visible to the user. This hint defaults to true and is persistent across fragment instance state save and restore.

To use it:

    private static boolean isVisible;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) { 
    super.setUserVisibleHint(isVisibleToUser);
    isVisible = isVisibleToUser;

    if (isVisible) { 
        Log.d("TAG", "this fragment is visible");
    } else {  
        Log.d("TAG", "this fragment is invisible");
    }
}
like image 42
rafsanahmad007 Avatar answered Oct 10 '22 08:10

rafsanahmad007