外观
什么时候能拿到 View 宽高?onResume 时已经显示了吗?
标准回答
View 完成本轮布局后,才能按布局结果可靠读取 getWidth / getHeight。Activity 的 onResume 表示生命周期进入相应状态,不承诺布局、GPU 渲染和屏幕展示都已经完成。
如果计算依赖控件尺寸,可以在自定义 View 的 onSizeChanged 中更新,或使用布局变化回调。OnPreDraw 在一次绘制开始前回调,适合在测量布局之后、绘制之前做轻量检查,但它仍然不是“已经上屏”的通知。
View.post 常被用于稍后执行,但它本质上是任务投递,不是专门证明本轮布局完成的契约。对于异步 Inflate、再次 requestLayout 或视图尚未接入窗口等情况,应直接观察需要的布局阶段。
如果目标是测首帧响应,尺寸大于 0 只能证明几何信息可用,onPreDraw 只能证明走到绘制前。真正的展示终点仍需要目标帧的显示证据。
关键机制
- OnLayoutChangeListener 可以观察布局边界变化;仅使用一次时及时移除,长期使用也要管理生命周期。
- onSizeChanged 针对尺寸变化,适合缓存圆心、路径等几何信息,避免每次 onDraw 重算。
- OnPreDraw 返回 false 会取消当前这次绘制;不要无意长期阻止页面出帧。
通俗例子
异步布局回调在 onResume 之后才返回完全可能;这不是生命周期乱序,而是页面进入生命周期与内容准备好采用了不同进度。
追问与回答
有没有简单的 Java 写法?
下面的回调读取下一次绘制前的尺寸,并立即移除自己。它适合做一次轻量的布局结果检查;不是上屏计时器,也不应在其中执行 IO。若 View 不再进入绘制阶段,回调也不会凭空执行。
易混淆点
onWindowFocusChanged 和 IdleHandler 也不是通用的首帧实际展示证明。
参考资料
内容来源
- Android 技术札记 · 原条目
view-first-size