2014-10-04 82 views
8

我需要侦听确切的全局布局事件才能初始设置正确的滚动位置。在搜索了一下为什么我对scrollTo(x,y)的调用似乎被忽略后,我发现只有在整个布局已知时才能以有意义的方式调用这些调用。所以我正在注册一个GlobalLayoutListener并将我的电话推迟到scrollTo()从ViewTreeObserver中删除侦听器

问题是,我只想这样做滚动一次。所以我想我可以简单地拨打removeGlobalOnLayoutListener()来停止收听。这导致了一个例外:IllegalStateException: This ViewTreeObserver is not alive, call getViewTreeObserver() again。所以我觉得我很好,如果Observer不活跃,它不会触发任何事件。但不幸的是它确实如此:每当布局以某种方式更改时,我的视图都会滚动。

我目前的代码迭代看起来像这样。我可以更改哪些内容以确保仅对scrollToGridPos()致电一次?我知道我可以在本地场mHasFired只是增加了内部类,但是这似乎是很肮脏的黑客我...

final ViewTreeObserver vto = mLayout.getViewTreeObserver(); 
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
    public void onGlobalLayout() { 
     scrollToGridPos(getCenterPoint(), false); 
     if (vto.isAlive()) { 
      vto.removeGlobalOnLayoutListener(this); 
     } 
    } 
}); 
+0

它对我来说看起来并不像一个黑客。另外,如果你可以覆盖它,你也可以在'View.onLayout'中做同样的事情。这看起来更像是对我的做法。 – 2014-10-04 12:20:29

回答

23

你应该只在onGlobalLayout()使用mLayout.getViewTreeObserver(),而不是试图访问一。例如。

mLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
    public void onGlobalLayout() { 
     scrollToGridPos(getCenterPoint(), false); 
     mLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);   
    } 
}); 
+0

看起来不错,但'removeGlobalOnLayoutListener'已弃用。是否有任何其他解决方案来删除侦听器? – GA1 2017-09-29 14:07:39

+0

我正在使用removeOnGlobalLayoutListener() – musterjunk 2017-12-10 17:25:16