简述为什么onCreate获取不到View的宽高 ?

在 Android 开发中,无法在 ActivityonCreate() 方法中直接获取视图(View)的宽高是一个常见问题。这主要是因为 onCreate() 方法是生命周期回调中设置布局和初始化界面元素的阶段,此时视图尚未被测量、布局完成,因此尺寸信息还未被确定。

生命周期和视图渲染过程

生命周期与视图的渲染:

  • onCreate():在这个方法中,你通常会调用 setContentView() 来加载布局文件,此时视图对象被创建。
  • onStart()onResume():这些方法调用之后,视图才开始进行布局过程,包括测量和布局。

视图渲染的三个阶段:

  1. 测量(Measure):在这个阶段,系统遍历视图树,调用每个视图的 measure() 方法来计算视图的尺寸。在 measure() 调用完成之前,你无法获取到精确的宽度和高度。
  2. 布局(Layout):系统再次遍历视图树,这次调用 layout() 方法,它决定每个视图在屏幕上的位置。
  3. 绘制(Draw):最后是绘制阶段,系统遍历视图树调用 draw() 方法来显示内容到屏幕上。

由于 onCreate() 在视图渲染过程的测量和布局之前被调用,所以在 onCreate() 中直接尝试获取视图的宽度和高度会得到0。

解决方法

为了在视图渲染完成后获取视图的尺寸,你可以采取以下几种方法:

  1. 使用 View.post() 方法
    final View view = findViewById(R.id.my_view);
    view.post(new Runnable() {
       @Override
       public void run() {
           int width = view.getWidth();
           int height = view.getHeight();
       }
    });
    
  2. 使用 ViewTreeObserver 监听器
    final View view = findViewById(R.id.my_view);
    ViewTreeObserver observer = view.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
       @Override
       public void onGlobalLayout() {
           view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
           int width = view.getWidth();
           int height = view.getHeight();
       }
    });
    
  3. 延迟到 onWindowFocusChanged() 方法中获取
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
       super.onWindowFocusChanged(hasFocus);
       if (hasFocus) {
           View view = findViewById(R.id.my_view);
           int width = view.getWidth();
           int height = view.getHeight();
       }
    }
    

通过以上方法,你可以在视图完全渲染后获取到准确的尺寸。这些方法确保了在视图的生命周期和渲染流程中正确地获取宽高信息。

发表评论

后才能评论