在项目中有这样一个需求,我的某一个控件需要根据其他控件的高度来确定自己的高度,以达到适配的效果。因此,我需要在整个视图完成布局之后,就获得这些高度的参数,在网上搜索了资料后发现,ViewTreeObserver可以完成这样的功能任务。
ViewTreeObserver是一个视图树的观察者,只要视图发生且不局限于以下几个方面的变化时,都会有回调:整个视图树的布局变化,开始绘制视图,触摸模式改变等等。
ViewTreeObserver里面有很多内部类,大都是针对于不同情况变化的回调接口,我们这里要说的interface ViewTreeObserver.OnGlobalFocusChangeListener就是其中的一个内部接口。当视图的布局发生改变的时候,就会调用OnGlobalFocusChangeListener这个回调监听。
我们通过去ViewTreeObserver获取视图实际高度的时候,代码如下:
private void initOnLayoutListener() {
final ViewTreeObserver viewTreeObserver = this.getWindow().getDecorView().getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
root_h = root_layout.getMeasuredHeight();
actionbar_h = myactionbar.getMeasuredHeight();
tabs_h = tabs.getMeasuredHeight();
line_h = line.getMeasuredHeight();
int height0 = root_h - actionbar_h - tabs_h - line_h;
android.widget.RelativeLayout.LayoutParams param_map0 =
new android.widget.RelativeLayout.LayoutParams
(android.widget.RelativeLayout.LayoutParams.MATCH_PARENT, height0);
param_map0.addRule(RelativeLayout.BELOW, R.id.actionbar_layout);
frame.setLayoutParams(param_map0);
Log.i(TAG, "root_h:"+root_h);
Log.i(TAG, "line_h:"+line_h);
handler.sendEmptyMessage(0x1);
// 移除GlobalLayoutListener监听
MainActivity.this.getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
//一般都是在oncreate()方法里面去注册该监听
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
ninit();
initOnLayoutListener();
}
需要注意的是,OnGlobalLayoutListener可能会被多次回调,因此,我们在获得了实际高度数据后,记得把监听注销掉。