如何让ScrollView中的NavigationLink实现List式点击高亮效果?
问题描述
我发现List和Form的功能无法满足需求,只能在ScrollView里构建传统UI。在List中使用NavigationLink时,点击链接会在跳转前展示整个单元格的动画高亮效果,但在ScrollView里用NavigationLink时做不到这点:
- 必须用
.contentShape()才能让整个单元格可点击,而不是只有内容区域 - 点击高亮只作用于单元格内的Text、Image等内容,整个单元格背景不会变化
点击前:
点击时:(注意单元格背景无变化)
核心问题:如何让ScrollView中的NavigationLink实现List单元格样式的点击动画效果?
原代码:
struct TestCellView: View { var body: some View { ScrollView { GroupBox { NavigationLink(destination: Text("Some detail view")) { HStack { Text("FAQ") Spacer() Image(systemName: "chevron.right") .foregroundColor(.secondary) } .contentShape(Rectangle()) // Required to make whole button tappable. } .buttonStyle(.plain) // Remove system tinting on the Text and Image. } } .padding() .navigationTitle("Test") .navigationBarTitleDisplayMode(.inline) } } #Preview { NavigationStack { TestCellView() .preferredColorScheme(.dark) } }
解决方案
要实现List单元格的点击高亮效果,可以通过以下方式修改代码:
- 让NavigationLink的内容容器占满整个单元格空间,确保点击区域覆盖全部范围
- 自定义按钮样式,模拟List单元格的点击高亮动画
修改后的代码:
struct TestCellView: View { var body: some View { ScrollView { GroupBox { NavigationLink(destination: Text("Some detail view")) { HStack { Text("FAQ") Spacer() Image(systemName: "chevron.right") .foregroundColor(.secondary) } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) .padding() } .buttonStyle(ListCellButtonStyle()) } } .padding() .navigationTitle("Test") .navigationBarTitleDisplayMode(.inline) } } // 自定义按钮样式,模拟List单元格的点击高亮 struct ListCellButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .background(configuration.isPressed ? Color(.systemGray5) : Color.clear) .cornerRadius(8) } } #Preview { NavigationStack { TestCellView() .preferredColorScheme(.dark) } }
关键说明:
.frame(maxWidth: .infinity, maxHeight: .infinity)让内容容器占满GroupBox的全部空间,无需额外设置.contentShape()就能实现全单元格点击- 自定义
ListCellButtonStyle在按钮按下时切换背景色,还原List单元格的高亮动画逻辑 - 移除
.buttonStyle(.plain),通过自定义样式控制点击状态,同时保留原有内容的视觉样式
内容的提问来源于stack exchange,提问作者Womble
相关产品推荐
相关产品推荐

