【参考链接】
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的长宽的和位置