Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does setVisibility() not fire onVisibilityChanged() in a view?

Tags:

I have a problem where in a specific situation when I call setVisibility(GONE) inside my custom view, its onVisibilityChanged method doesn't get called and it actually doesn't hide the view although getVisibility() returns 8 (or GONE) afterwards.

Here is how I know the visibility changes but onVisibilityChanged is not called.

@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
    Log.i(LOG_TAG, "onVisibilityChanged: " + visibility);
    super.onVisibilityChanged(changedView, visibility);
}

@Override
public void setVisibility(int visibility) {
    super.setVisibility(visibility);
    Log.i(LOG_TAG, "setVisibility: " + visibility);
}

public void hide(){
    Log.i(LOG_TAG, "before hide visibility: " + getVisibility());
    setVisibility(GONE);
    Log.i(LOG_TAG, "after hide visibility: " + getVisibility());
}

Normally when I call hide() I see these lines in the log:

before hide visibility: 0

onVisibilityChanged: 8

setVisibility: 8

after hide visibility: 8

But in a spicific situation when I call hide() I get these lines in the log and the view isn't hidden afterwards although getVisibility() returns 8:

before hide visibility: 0

setVisibility: 8

after hide visibility: 8

So when in general does this happen? When does setVisibility not call onVisibilityChanged?

Don't ask what my specific situation is. But please provide every general situation where this might happen.

like image 964
Arash Rohani Avatar asked Sep 21 '18 15:09

Arash Rohani


1 Answers

It is called only when the view is attached in the hierarchy.

The call to setVisibility looks like this:

public void setVisibility(@Visibility int visibility) {
    setFlags(visibility, VISIBILITY_MASK);
}

The setFlags method is a long one where a bunch of different view properties are changed and handled, but the noticable part is this:

 if ((changed & VISIBILITY_MASK) != 0) {
      // if visiblity changed...
      ...
      if (mAttachInfo != null) { // true if attached in view hierarchy
            dispatchVisibilityChanged(this, newVisibility); // onVisibilityChanged is called from here 
            ...

So you will see your described behaviour on a view that's not attached to a fragment or activity.

like image 151
RobCo Avatar answered Oct 11 '22 17:10

RobCo