返回

布局绘制检测的三种方法:哪种最适合你?

Android

如何检测布局何时被绘制?

作为一名经验丰富的程序员,在开发过程中我遇到了一个挑战:需要检测自定义视图何时被绘制到屏幕上,以便初始化。由于在 onCreate 和 onResume 函数期间布局尚未绘制,直接获取其像素大小会返回 0,导致程序崩溃。

为了解决这个问题,我使用了三种不同的方法:

1. ViewTreeObserver

ViewTreeObserver 提供了 onGlobalLayout() 方法,它会在视图树发生布局变更后调用。我们可以将监听器添加到 ViewTreeObserver ,以便在布局发生变化时接收通知。

ViewTreeObserver viewTreeObserver = myLayout.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // 布局已绘制
    }
});

2. 重写 onDraw() 方法

我们可以重写 onDraw() 方法,它会在布局每次需要重新绘制时调用。这种方法提供了最大的灵活性,但我们也需要处理视图的绘制。

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    
    // 布局已绘制
}

3. 使用 invalidate() 方法

我们可以使用 invalidate() 方法来强制视图重新绘制。当调用 invalidate() 时,视图会被标记为“脏”,并会在下次绘制循环中重新绘制。

myLayout.invalidate();

选择哪种方法?

根据我们的具体需求,这三种方法中的任何一种都可以用来检测布局何时被绘制。

  • ViewTreeObserver 提供了一个简单的方法来监听布局更改,它不依赖于视图的实际绘制。
  • 重写 onDraw() 方法 提供了最大的灵活性,但它也需要我们处理视图的绘制。
  • 使用 invalidate() 方法 是一种强制视图重新绘制的简单方法,但它不会提供有关布局更改的任何其他信息。

示例

以下是如何使用 ViewTreeObserver 检测布局何时被绘制的示例代码:

ViewTreeObserver viewTreeObserver = myLayout.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        int measuredHeight = myLayout.getMeasuredHeight();
        
        // 使用测得的高度初始化自定义视图
    }
});

常见问题解答

1. 如何确定布局是否已经绘制?

我们可以使用 ViewTreeObserveronGlobalLayout() 方法或重写 onDraw() 方法来检测布局何时被绘制。

2. 为什么要检测布局是否被绘制?

在某些情况下,我们需要在布局绘制后执行某些操作,例如初始化自定义视图或获取其像素大小。

3. invalidate() 方法会立即重新绘制视图吗?

不会,invalidate() 方法只是标记视图为“脏”,视图会在下次绘制循环中重新绘制。

4. 使用哪种方法检测布局被绘制更好?

这取决于我们的具体需求,ViewTreeObserver 提供了一种简单的方法,而重写 onDraw() 方法提供了最大的灵活性。

5. 有没有其他方法可以检测布局被绘制?

我们可以使用 requestLayout() 方法来请求重新布局,然后监听 onLayout() 方法,但这可能效率较低。