Android post块内修改ConstraintLayout高度不生效问题咨询
问题现象
尝试在post代码块内修改ConstraintLayout控件的高度,实现代码如下:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) changeHeight() } private fun changeHeight() { val layoutView = findViewById<ConstraintLayout>(R.id.block1) layoutView.post { Log.d("222", "1===========") layoutView.run { Log.d("222", "2===========") layoutParams.height = 1000 setBackgroundColor(Color.BLUE) } Log.d("222", "3===========") } } }
实际运行表现:
- 高度修改逻辑完全不生效,但日志可正常打印,设置背景为蓝色的逻辑可正常执行
- 移除
layoutView.post的包裹后,高度修改逻辑可正常生效 - 将
changeHeight()方法移到按钮点击监听器中执行,排除View未挂载等挂载阶段问题后,问题依旧存在
根本原因
核心是post任务的执行时序和View布局流程存在时序差,叠加LayoutParams修改的生效逻辑特性导致的:
- 无post包裹时,
changeHeight在onCreate阶段执行,此时布局仅完成inflate加载,还未启动首次测量(measure)->布局(layout)->绘制(draw)流程。此时修改layoutParams.height,后续系统触发首次布局遍历时会直接读取修改后的参数计算尺寸,不需要额外操作就能生效。 - 加了post包裹时,
view.post()提交的任务会被加入主线程消息队列,执行时机排在当前待执行的首次布局遍历任务之后。等post内的代码运行时,系统已经完成首次布局计算,ConstraintLayout的尺寸已经按照旧的LayoutParams确定完成。 - 直接修改已有
LayoutParams对象的height字段,不会自动触发View的requestLayout()标记,系统不会主动发起新一轮的布局测量流程,新的高度值不会被应用。而setBackgroundColor方法内部会自动调用invalidate()触发重绘流程,不需要重新测量布局就能生效,因此会出现背景色修改正常、高度不更新的现象。 - 按钮点击场景下问题复现的逻辑一致:按钮点击事件触发时,View早已完成首次布局,此时通过post提交的任务执行时同样处于布局流程结束的状态,只改参数不触发重新布局,高度修改自然不会生效。
修复方案
修改LayoutParams参数后主动触发布局请求即可:
private fun changeHeight() { val layoutView = findViewById<ConstraintLayout>(R.id.block1) layoutView.post { Log.d("222", "1===========") layoutView.run { Log.d("222", "2===========") layoutParams.height = 1000 setBackgroundColor(Color.BLUE) // 主动标记需要重新布局 requestLayout() } Log.d("222", "3===========") } }
内容的提问来源于stack exchange,提问作者William Hu
相关产品推荐
相关产品推荐

