Android:在activity一启动就获取View的宽高

问题:在onCreate、onStart或者onResume方法中无法正确获取某个View的宽高
  原因是View的measure过程和Activity的生命周期方法不是同步执行的,因此无法保证Activity执行了onCreate、onStart、onResume时某个View已经测量完毕了,如果View没有测量完毕,那么获得的宽高就是0。
这里给出以下三种方法来解决这个问题:
1. Activity/View的onWindowFocusChanged
  onWindowFocusChanged这个方法的含义是:View已经初始化完毕,宽高已经准备好了,这个时候去获取宽高是没有问题的。需要注意的是,onWindowFocusChanged会被调用多次,当Activity的窗口得到焦点和失去焦点的时候都会被调用一次。

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        int width = view.getMeasuredWith();
        int height = view.getMeasuredHeight();
    }
}

2. view.post(runnable)
  通过post可以将一个runnable投递到消息队列的尾部,然后等待Looper调用此runnable的时候,View也已经初始化好了。

@Override
protected void onStart() {
    super.onStart();
    view.post(new Runnable() {
        @Override
        public void run() {
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
        }
    });
}

3. ViewTreeObserver
  使用ViewTreeObserver的众多回调接口也可以,比如使用OnGlobalLayoutListener这个接口,当View树的状态发生改变或者View树内部的View的可见性发生改变的时候,onGlobalLayout方法将被回调,因此这是获取View的宽高一个很好的机会。值得注意的是,伴随着View树的状态改变等,onGlobalLayout会被多次调用。

@Override
protected void onStart() {
    super.onStart();
    ViewTreeObserver observer = tv.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            tv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            int width = tv.getMeasuredWidth();
            int height = tv.getMeasuredHeight();
        }
    });
}

你可能感兴趣的:(Android:在activity一启动就获取View的宽高)