android 开发 在oncreate()中获取到控件的高度和宽度值为0解决办法

大家很多时候需要在activity或者fragment的oncreate()方法中获取声明的空间的高度或者宽度,进行位置移动或者其他操作,但是当调用view.getHeight()或者view.getWidth()获取的竟然为0。。。黑人问号。。。
其实很容易理解,在oncreate的时候,实际上控件只是声明了,并没有绘制完成,没有attach到window上,所以导致获取的高度和宽度为0,那么该怎么解决呢?

两种方法
1、使用下面的post方式:

view.post(new Runnable() {
     @Override
     public void run() {
         int height= view.getHeight() ;
      }
});

同理宽度改为下面的即可。

view.post(new Runnable() {
     @Override
     public void run() {
         int height= view.getWidth() ;
      }
});

原理:(1)View.post(Runnable) 内部会自动分两种情况处理,当 View 还没 attachedToWindow 时,会先将这些 Runnable 操作缓存下来;否则就直接通过 mAttachInfo.mHandler 将这些 Runnable 操作 post 到主线程的 MessageQueue 中等待执行。
(2)如果 View.post(Runnable) 的 Runnable 操作被缓存下来了,那么这些操作将会在 dispatchAttachedToWindow() 被回调时,通过 mAttachInfo.mHandler.post() 发送到主线程的 MessageQueue 中等待执行。

想了解更多请去查看源码。相信你可以更深层次的理解。

View.post() 中的操作执行时,View 的宽高已经计算完毕,所以可以在 Activity 的 onCreate() 里调用 View.post() 来解决获取 View 宽高为0的问题。

2、使用ViewTreeObserver 的方式:

ViewTreeObserver vto = view.getRabbit().getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
    public boolean onPreDraw() {
        if(vto.isAlive()){
            vto.removeOnDrawListener(this);
        }
        int height = view.getMeasuredHeight());
        return true;
    }
});

ViewTreeObserver 注册一个观察者来监听视图树,当视图树的布局、视图树的焦点、视图树将要绘制、视图树滚动等发生改变时,ViewTreeObserver都会收到通知。所以这个方法会调用很多次,如果要使用这种方法的话,要做好规避调用多次,记得移除监听;ViewTreeObserver不能被实例化,可以调用View.getViewTreeObserver()来获得。
3、还有一种不太推荐:

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

这个函数的含义是:view已经初始化完毕了,宽/高已经准备好了,这个时候去获取宽高是可以成功获取的。需要注意的是onWindowFocusChanged函数会被调用多次,当Activity的窗口得到焦点和失去焦点时均会被调用一次,如果频繁地进行onResume和onPause,那么onWindowFocusChanged也会被频繁地调用,不太适合处理一些复杂的业务逻辑。

好了,小伙伴,加油!

猜你喜欢

转载自blog.csdn.net/wjh823177094/article/details/80786654