【参考链接】
View类提供了getViewTreeObserver()方法来获取一个ViewTreeObserver对象
通过给这个对象add各种Listener,可以实现相关情况的回调,并且在使用完成以后remove()掉。
是一个观察者模式的实现。
不过实验的时候,调用view的scrollTo()/scrollBy()并未触发onScrollChangedListener.
需要注意的是
1、 在视图树中的任何View使用getViewTreeObserver(),获取到的都是同一个ViewTreeObserver对象
2、在使用ViewTreeObserver对象前最好通过isAlive()方法进行判断其是否还alive
以如下代码为例
final
ViewTreeObserver viewTreeObserver =
tv.getViewTreeObserver();
if (viewTreeObserver.isAlive())
viewTreeObserver.addOnTouchModeChangeListener(new
ViewTreeObserver.OnTouchModeChangeListener(){
@Override
public void
onTouchModeChanged(boolean
b) {
Log.e("ViewTreeObserverX",
"onTouchModeChanged()");
}
});
if (viewTreeObserver.isAlive())
viewTreeObserver.addOnGlobalFocusChangeListener(new
ViewTreeObserver.OnGlobalFocusChangeListener(){
@Override
public void
onGlobalFocusChanged(View view,
View view1) {
Log.e("ViewTreeObserverX",
"onGlobalFocusChanged()");
}
});
if (viewTreeObserver.isAlive())
viewTreeObserver.addOnGlobalLayoutListener(new
ViewTreeObserver.OnGlobalLayoutListener(){
@Override
public void
onGlobalLayout() {
Log.e("ViewTreeObserverX",
"onGlobalLayout()");
}
});
if (viewTreeObserver.isAlive())
viewTreeObserver.addOnPreDrawListener(new
ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean
onPreDraw() {
Log.e("ViewTreeObserverX",
"onPreDraw()");
if(viewTreeObserver.isAlive())
viewTreeObserver.removeOnPreDrawListener(this);
else
tv.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
if (viewTreeObserver.isAlive())
viewTreeObserver.addOnScrollChangedListener(new
ViewTreeObserver.OnScrollChangedListener(){
@Override
public void
onScrollChanged() {
Log.e("ViewTreeObserverX",
"onScrollChanged()");
}
});
在整个流程中的调用时机如下
以onGlobalLayout()为例,可以在其中去获取View的长宽的和位置