Search code examples
androidandroid-layoutandroid-viewandroid-4.0-ice-cream-sandwichandroid-2.3-gingerbread

Why ViewTreeObserver > OnScrollChangedListener not called on Android 2.x if it set in onCreate()?


I discovered that OnScrollChangedListener on Android 2.x won't be ever fired if it was added before the first time layout draw. For example, when you add a scroll listener in methods like onCreate/onResume/onAttachedToWindow:

public class MainActivity extends AppCompatActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        View myView = findViewById(R.id.MyView);

        System.out.println(myView.getViewTreeObserver().isAlive()); // true

        myView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                // will never fire
            }
        });
    }
}

So, anybody knows the reason of this problem?


PS: Seems like the problem sometime happens on API<=15 (Android 4.0.3)


Solution

  • So, it seems like a bug. And here is a simple workaround:

    To make OnScrollChangedListener work on old devices (apparently API<=15), you should add it either in onWindowFocusChanged(true), or after the layout is measured (use GlobalLayoutListener).

    And don't to forget to create a flag like isScrollListenerAdded to avoid repeated listener attaching.

    Something like this:

    myView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (!isScrollListenerAdded) {
                isScrollListenerAdded = true;
                // add OnScrollChangedListener here
            }
        }
    });
    

    Details are available in this blog post about OnScrollChangedListener (Rus; Kotlin)