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.
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.
userVisibleHint = false to mark that fragment is not visible to user.
onStart()The onStart() method is called once the fragment gets visible. onResume()Fragment becomes active.
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.
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!
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");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With