首页
IT
登录
6mi
u
盘
搜
搜 索
IT
关于ViewTreeObserver的理解
关于ViewTreeObserver的理解
xiaoxiao
2021-12-14
16
作用:通过名字就可以知道它是View树的观察者,当View树的发生变化的时候会发出通知。ViewTreeObserver是不能被应用程序实例化的,因为它是由视图提供的,通过view.getViewTreeObserver()获取。 熟悉观察者模式的人应该很容易想到,为了能够相应的通知,我们肯定需要注册监听。下面来看看我们可以注册哪些监听。 1、当在一个视图树中的焦点状态或者可见性发生改变时调用OnGlobalFocusChangeListener的onGlobalFocusChanged()函数。 public void addOnGlobalFocusChangeListener (ViewTreeObserver.OnGlobalFocusChangeListener listener) 1 1 2、当在一个视图树中的焦点状态或者可见性发生改变时调用OnGlobalFocusChangeListener的onGlobalFocusChanged()函数。 public void addOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener listener) 1 1 3、当一个视图树将要绘制时调用OnPreDrawListener的onPreDraw()函数 public void addOnPreDrawListener (ViewTreeObserver.OnPreDrawListener listener) 1 1 4、当一个视图发生滚动时调用OnScrollChangedListener的onScrollChanged()函数 public void addOnScrollChangedListener (ViewTreeObserver.OnScrollChangedListener listener) 1 1 5、当一个触摸模式发生改变时调用OnTouchModeChangeListener的onTouchModeChanged()函数 public void addOnTouchModeChangeListener (ViewTreeObserver.OnTouchModeChangeListener listener) 1 1 6、当一个视图树绘制时调用OnDrawListener的onDraw()函数 addOnDrawListener(ViewTreeObserver.OnDrawListener listener) 1 1 7、当View树绑定到window上的时候回调OnWindowAttachListener的onWindowAttached() 函数,当它从window上解绑时调用OnWindowAttachListener的onWindowDetached() addOnWindowAttachListener(ViewTreeObserver.OnWindowAttachListener listener) 1 1 8、当window的焦点状态发生改变时,调用OnWindowFocusChangeListener的onWindowFocusChanged函数 addOnWindowFocusChangeListener(ViewTreeObserver.OnWindowFocusChangeListener listener) 1 1 对应这些注册的监听,还有相应的删除监听 public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) public void removeOnGlobalFocusChangeListener (ViewTreeObserver.OnGlobalFocusChangeListener victim) public void removeOnPreDrawListener (ViewTreeObserver.OnPreDrawListener victim) public void removeOnScrollChangedListener (ViewTreeObserver.OnScrollChangedListener victim) public void removeOnTouchModeChangeListener (ViewTreeObserver.OnTouchModeChangeListener victim) public void removeOnDrawListener(ViewTreeObserver.OnDrawListener victim) public void removeOnWindowAttachListener(ViewTreeObserver.OnWindowAttachListener victim) public void removeOnWindowFocusChangeListener(ViewTreeObserver.OnWindowFocusChangeListener victim) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 上面注册的监听都是View树发生变化的时候,会被自动触发回调,如果我们希望手动触发回调,可以调用下面函数 public final void dispatchOnGlobalLayout () 手动触发OnGlobalLayoutListener的onGlobalLayout()函数回调 public final boolean dispatchOnPreDraw () 手动触发OnPreDrawListener的onPreDraw()函数的回调 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 另外还是一个指示当前的ViewTreeObserver是否可用的函数。 public boolean isAlive () 当observer不可用时,任何方法的调用(除了这个方法)都将抛出一个异常。 1 2 3 1 2 3 应用场景1:获取View的宽高 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final MyImageView myImageView = (MyImageView) findViewById(R.id.imageview); int height = 0; int width = 0 ; ViewTreeObserver vto = myImageView.getViewTreeObserver(); vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { int height = myImageView.getMeasuredHeight(); int width = myImageView.getMeasuredWidth(); return true; } }); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 因为回调OnPreDrawListener的onPreDraw,表示这个View准备进行绘制,在绘制之前,这个View的宽高肯定是已经测量好了,所以这个时机是可以得到view的宽高的。 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final MyImageView myImageView = (MyImageView) findViewById(R.id.imageview); int height = 0; int width = 0 ; ViewTreeObserver vto = myImageView.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { myImageView.getViewTreeObserver().removeGlobalOnLayoutListener(this); int height = myImageView.getHeight(); int width = myImageView.getWidth(); } }); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 当view的可见状态发生变化的时候回调OnGlobalLayoutListener的onGlobalLayout()函数,这个时候View的宽高肯定也是已经测量好了,所以这个时机是可以得到view的宽高的。 应用场景2:Activity跳转动画 ViewTreeObserver还可以用来监听根布局,用来实现Activity跳转动画,核心代码如下: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); rootView = findViewById(R.id.root); if (savedInstanceState == null) { rootView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { rootView.getViewTreeObserver().removeOnPreDrawListener(this); startRootAnimation(); return true; } }); } } 因为在绘制之前会触发OnPreDrawListener的onPreDraw()函数,这个时候可以执行跳转动画。 应用场景3:测量软键盘状态和高度 ViewTreeObserver.OnGlobalLayoutListener mListener = new ViewTreeObserver .OnGlobalLayoutListener() { public void onGlobalLayout() { Rect r1 = new Rect(); root.getWindowVisibleDisplayFrame(r1); Log.e("TAG",r1.bottom+"") ; } }; root.getViewTreeObserver().addOnGlobalLayoutListener(mListener); 在根布局加入GlobalLayoutListener监听,通过getWindowVisibleDisplayFrame方法可以观察可见区域的变化,键盘打开后 会影响可见区域的大小,导致Rect的底部r1.bottom变小。
转载请注明原文地址: https://ju.6miu.com/read-964402.html
专利
最新回复
(
0
)