SwiftUI:移除NavigationLink遮罩以显示列表项原始颜色
问题说明
在iOS 15+和iOS 16+系统中,给列表项添加NavigationLink后,列表项的原始颜色会被一层系统默认遮罩覆盖,使用.buttonStyle(PlainButtonStyle())无法解决该问题。
解决方案
方案1:将颜色设置为列表行背景(推荐)
把原本放在NavigationLink label中的颜色视图,改为设置为列表行的背景色,彻底避开遮罩影响:
var colors: [Color] = [.red, .blue, .yellow] var body: some View { VStack { List { ForEach(colors, id: \.self) { color in NavigationLink { // 跳转目标详情页 } label: { // 这里放你的自定义内容,比如文本、图标等 Text("") // 若无需额外内容可留空 } .listRowBackground(color) .listRowInsets(EdgeInsets()) } } .listStyle(PlainListStyle()) } .padding(.horizontal) }
方案2:强制保持Label的不透明度
如果必须在NavigationLink的label中放置颜色视图,可以通过强制设置不透明度并配合样式调整来消除遮罩:
var colors: [Color] = [.red, .blue, .yellow] var body: some View { VStack { List { ForEach(colors, id: \.self) { color in NavigationLink { // 跳转目标详情页 } label: { color .opacity(1) // 强制保持原始不透明度 } .buttonStyle(PlainButtonStyle()) .listRowInsets(EdgeInsets()) .listRowBackground(Color.clear) // 避免行背景干扰 } } .listStyle(PlainListStyle()) } .padding(.horizontal) }
方案3:改用Button+NavigationDestination组合
使用iOS 16+支持的navigationDestination,配合普通Button实现跳转,完全规避NavigationLink的默认样式:
@State private var selectedColor: Color? var colors: [Color] = [.red, .blue, .yellow] var body: some View { VStack { List { ForEach(colors, id: \.self) { color in Button { selectedColor = color } label: { color } .buttonStyle(PlainButtonStyle()) .listRowInsets(EdgeInsets()) } } .listStyle(PlainListStyle()) } .padding(.horizontal) .navigationDestination(item: $selectedColor) { color in // 跳转目标详情页 Text("选中颜色:\(color.description)") } }
原因解释
NavigationLink作为列表项时,系统会默认给其label添加一层半透明遮罩,用于提供点击交互的视觉反馈,即使使用PlainButtonStyle也无法完全移除这层遮罩。上述方案通过改变颜色的放置位置、强制不透明度或替换跳转组件的方式,绕过了这一默认行为,从而让原始颜色正常显示。
内容的提问来源于stack exchange,提问作者Zhou Haibo
相关产品推荐
相关产品推荐

