Remove listener from ViewTreeObserver
Asked Answered
P

1

20

I need to listen for exact one global layouting event to initially set correct scrolling positions. After searching a little why my calls to scrollTo(x,y) seem to be ignored I discovered these can only be called in an meaningful way once the whole layout is known. So I am registering a GlobalLayoutListener and defer my call to scrollTo().

The problem is, that I only want to do this scrolling once. So I figured I could simply call removeGlobalOnLayoutListener() to stop listening. That resulted in a Exception: IllegalStateException: This ViewTreeObserver is not alive, call getViewTreeObserver() again. So I thought I am fine, if the Observer is not alive it won't fire any events. But unfortunately it does: My view is scrolled every time the layout somehow changes.

My current iteration of the code looks like this. What could I change to make sure the call to scrollToGridPos() only takes place once? I know I could just add a local field mHasFired to the inner class but that seems like very dirty hack to me ...

final ViewTreeObserver vto = mLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    public void onGlobalLayout() {
        scrollToGridPos(getCenterPoint(), false);
        if (vto.isAlive()) {
            vto.removeGlobalOnLayoutListener(this);
        }
    }
});
Pillory answered 4/10, 2014 at 12:11 Comment(1)
It does not seems like a hack to me. Alternatively you could also do the same inside View.onLayout if you can override it. This seems more the way to do it to me.Pyrosis
A
59

You should just be using mLayout.getViewTreeObserver() in onGlobalLayout(), rather than trying to access the old one. Eg.

mLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    public void onGlobalLayout() {
        scrollToGridPos(getCenterPoint(), false);
        mLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);        
    }
});
Abolish answered 4/10, 2014 at 14:22 Comment(3)
Looks great, but removeGlobalOnLayoutListener is deprecated. Is there any other solution for removing the listener?Yonah
I am using removeOnGlobalLayoutListener()Duelist
And usually they say what to use in case of deprecation, should be stated in Java docs.Piraeus

© 2022 - 2024 — McMap. All rights reserved.