能否使用协程替代Runnable实现ScrollView滚动逻辑?
问题根因
你之前写的协程不生效,和View.post()的运行逻辑有关:post提交的Runnable会被放到视图树的消息队列尾部,等当前所有视图测量、布局流程执行完成后才会运行,此时拿到的myAwesomeTextView.bottom是布局完成后的正确值。而你直接在主线程启动协程,执行时机大概率在视图布局完成之前,此时bottom值为0或者未更新的旧值,自然看不到滚动效果。
可行协程实现方案
方案1:使用AndroidX官方KTX扩展(推荐)
AndroidX core-ktx 提供了awaitLayout()协程扩展,专门用来等待视图完成布局,和post的效果完全一致,稳定性最高:
首先确保你的模块build.gradle已添加KTX依赖:
dependencies { implementation "androidx.core:core-ktx:1.12.0" }
业务代码如下:
// 优先用页面的lifecycleScope,避免页面销毁后协程泄漏 lifecycleScope.launch { // 等待滚动锚点控件完成布局,也可替换为scrollView.awaitLayout() myAwesomeTextView.awaitLayout() scrollView.smoothScrollTo(0, myAwesomeTextView.bottom) }
方案2:无依赖手动实现
如果不想引入KTX扩展,可以通过yield()主动让出主线程调度,等待布局完成:
lifecycleScope.launch(Dispatchers.Main) { // 循环等待控件完成布局,拿到正确的bottom值 while (myAwesomeTextView.bottom == 0 || myAwesomeTextView.isLayoutRequested) { yield() } scrollView.smoothScrollTo(0, myAwesomeTextView.bottom) }
不建议用固定时长的delay()实现,不同设备布局耗时不固定,很容易出现偶发失效问题。
内容的提问来源于stack exchange,提问作者skafle
相关产品推荐
相关产品推荐

