外观
ScrollToTopButton — 回到顶部
长列表右下角那个圆形箭头按钮。全站唯一实现。
基本用法
显示与否交给调用方 —— 本组件只管长什么样:
kotlin
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()
Box(Modifier.fillMaxSize()) {
LazyColumn(state = listState) { /* … */ }
AnimatedVisibility(
visible = listState.canScrollBackward,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(end = 16.dp, bottom = 24.dp),
) {
ScrollToTopButton(
onClick = { scope.launch { listState.animateScrollToItem(0) } }
)
}
}参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
onClick | () -> Unit | — | 点击回调。滚动动作由调用方实现,组件不持有任何滚动状态 |
modifier | Modifier | Modifier | 修饰符。定位与间距都在这里给(align / padding) |
colors | ScrollToTopButtonColors | ScrollToTopButtonDefaults.colors() | 配色 |
ScrollToTopButtonColors
| 字段 | 默认值 | 说明 |
|---|---|---|
containerColor | MaterialTheme.colorScheme.primary | 圆形底色 |
contentColor | MaterialTheme.colorScheme.onPrimary | 箭头颜色 |
kotlin
ScrollToTopButton(
onClick = { /* … */ },
colors = ScrollToTopButtonDefaults.colors(
containerColor = MaterialTheme.colorScheme.inverseSurface,
),
)要点
- 显隐由调用方判断。 组件内部不会自己决定「该不该出现」。用
listState.canScrollBackward配AnimatedVisibility,别用firstVisibleItemIndex > 0—— 后者在「刚滚一点点又滚回来」时会来回抖。 - 尺寸固定 52dp,别覆写。 它是悬浮在内容之上的圆形按钮,
modifier.size()会破掉圆形比例和箭头的内留白。 - 图标是
Phosphor.ArrowUp(22dp)。 别换方向 —— 「回到顶部」用上箭头,不是表示「返回」的左箭头。 - 触控区就是这个 52dp 的圆,已经超过 48dp 的最小标准,不需要再包一层
IconButton。 - 它没有阴影(本体是
Box+background+clip,不带 elevation)。想让它更浮起来,自己在modifier上补shadow()。
说明
- 为什么统一成实心近黑圆形:以前首页和搜索页各写了一个 —— 首页是黑色圆形 + 淡入,搜索页是浅灰药丸 +
FloatingActionButton的缩放动画。同一个动作在相邻两页长得不一样,用户会以为是两个不同的东西。现在统一成实心近黑圆形:它是无风险的导航动作,不需要抢视线,但必须一眼可辨;用主色(近黑)保证在任何表面色上都够醒目。 - 为什么不用
FloatingActionButton:FAB 自带 elevation 和「强调主操作」的语义,而「回到顶部」不是主操作。这里用裸Box+clickable,不带阴影、也不受 FAB 的尺寸约束。 - 和
AnimatedVisibility的分工:滚动监听、显隐动画、位置全在调用方;组件只保证「长什么样」在任何页面都一致。