Search code examples
androidandroid-scrollview

using View.isShown shows flickering


I coded as below in overriden onScroll method in order to show "New" icon.

public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    if (user.hasNewPost && !imageViewNew.isShown())
        imageViewNew.setVisibility(View.VISIBLE);
    else   
        imageViewNew.setVisibility(View.INVISIBLE);
}

I hardly understand why imageViewNew is flickering when I use isShown() method. I removed isShown() method and it gave stable visibility during onScroll event.

I printed Log.d(TAG, String.valueOf(imageViewNew.isShown())); and it really gave true/false accordingly at every scroll event as below.

07-06 22:47:10.132    6831-6831/com.sample D/TestViewFragment﹕ false
07-06 22:47:10.192    6831-6831/com.sample D/TestViewFragment﹕ true
07-06 22:47:10.242    6831-6831/com.sample D/TestViewFragment﹕ false
07-06 22:47:10.302    6831-6831/com.sample D/TestViewFragment﹕ true

How can it be happened?
Note that it occured from 2.3.6 to 5.0.1, so might be device independent issue.

Below code is View.isShown() method in android.view.

public boolean isShown() {
    View current = this;
    //noinspection ConstantConditions
    do {
        if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
            return false;
        }
        ViewParent parent = current.mParent;
        if (parent == null) {
            return false; // We are not attached to the view root
        }
        if (!(parent instanceof View)) {
            return true;
        }
        current = (View) parent;
    } while (current != null);

    return false;
}

I cannot check which line returns false as my Android Studio does not apply breakpoint on the source.


Solution

  • "I hardly understand why imageViewNew is flickering when I use isShown() method"

    onScroll method is called several and several times in a row, so let's see the processing "stack":

    onScroll -> !isShown == true -> 
                  setVisibility(View.VISIBLE); // next call !isShow will be false
    onScroll -> !isShown == false -> 
                  setVisibility(View.INVISIBLE); // next call !isShow will be true
    onScroll -> !isShown == true -> 
                  setVisibility(View.VISIBLE); // next call !isShow will be false
    onScroll -> !isShown == false -> 
                  setVisibility(View.INVISIBLE); // next call !isShow will be true
    

    on each call you're changing the final value for the comparison. It seems pretty logical to be that it will be flickering.

    Maybe you want to call this code in a different method, one that doesn't called several times again and again.