You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Wear OS Compose onResume时ScalingLazyColumn滚动到顶部实现方案

解决方案

核心思路是把「回到页面触发onResume」和「页面重组」两个场景的逻辑拆开处理:

  • 列表滚动状态用rememberScalingLazyListState()正常持有,重组时Compose会自动缓存该状态,不会重置位置
  • 单独监听页面生命周期,仅在收到ON_RESUME事件时主动触发列表滚动到顶部,重组时不做任何列表位置干预

具体实现代码

直接使用Compose官方自带的生命周期、协程API即可,不需要引入第三方库,修改后的代码如下:

import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import kotlinx.coroutines.launch

@Composable
fun WearApp(weatherVM: WeatherViewModel, application: Application) {
    WearAppTheme {
        val weather = weatherVM.weather.observeAsState(initial = null)
        val listState = rememberScalingLazyListState()
        val coroutineScope = rememberCoroutineScope()

        // 仅监听onResume生命周期事件,触发回到页面的滚动归位
        val lifecycleOwner = LocalLifecycleOwner.current
        DisposableEffect(lifecycleOwner) {
            val observer = LifecycleEventObserver { _, event ->
                if (event == Lifecycle.Event.ON_RESUME) {
                    coroutineScope.launch {
                        // 需要平滑滚动用animateScrollToItem,不需要动画直接替换为scrollToItem(0)
                        listState.animateScrollToItem(index = 0, scrollOffset = 0)
                    }
                }
            }
            lifecycleOwner.lifecycle.addObserver(observer)
            onDispose {
                lifecycleOwner.lifecycle.removeObserver(observer)
            }
        }

        Scaffold(
            positionIndicator = {
                PositionIndicator(
                    scalingLazyListState = listState
                )
            }
        ) {
            ScalingLazyColumn(
                modifier = Modifier.fillMaxSize(),
                autoCentering = AutoCenteringParams(itemIndex = 0),
                state = listState
            ) {
                item {
                    // 原有首屏/列表项内容保持不变
                }
                item {
                    // 原有列表项内容保持不变
                }
                // 其余原有列表逻辑无需修改
            }
        }
    }
}

避坑说明

  • 不要给rememberScalingLazyListState()传入任何和页面状态(比如weather返回值)绑定的key,否则对应状态变化触发重组时,列表状态会被重新初始化,直接丢失滚动位置
  • 滚动方法必须放在协程中调用,animateScrollToItem/scrollToItem都是挂起函数,直接在主线程同步调用会抛异常
  • 不要在Composable函数的非副作用域里直接调用滚动方法,否则每次重组都会触发滚动归位,不符合需求

内容的提问来源于stack exchange,提问作者GDefender

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 02:24:20