如何自定义NavigationLink中View的按压样式并禁用默认灰色状态
要实现自定义按压样式并在ScrollView滚动时自动恢复状态,只需通过以下几步修改代码:
1. 禁用NavigationLink默认按压样式
在NavigationLink上添加.buttonStyle(PlainButtonStyle()),完全移除系统默认的灰色高亮效果。
2. 用@GestureState管理按压状态
@GestureState是SwiftUI专门用于手势状态的属性包装器,当手势结束或被中断(比如ScrollView滚动)时,会自动将值重置为初始值,刚好满足滚动恢复的需求。
修改后的完整代码
struct Item: Identifiable { let id = UUID() let title: String } struct ContentView: View { let items = [Item(title: "One"), Item(title: "Two"), Item(title: "Three")] var body: some View { NavigationStack { ScrollView (showsIndicators: false) { ForEach(items) { item in NavigationLink { ItemDetailView(item: item) } label: { ItemView(item: item) } .buttonStyle(PlainButtonStyle()) // 禁用默认按压样式 } } } .padding() } } #Preview { ContentView() } struct ItemView: View { let item: Item @GestureState private var isPressed = false // 手势状态自动重置 var body: some View { HStack { Text(item.title) .foregroundStyle(.purple) .multilineTextAlignment(.leading) Spacer() } .frame(maxWidth: .infinity) .padding() .background(isPressed ? .blue : .green) .clipShape(RoundedRectangle(cornerRadius: 10)) .border(.red, width: isPressed ? 2 : 0) .padding(3) .simultaneousGesture( // 识别按压动作,最小距离0确保触摸即触发 DragGesture(minimumDistance: 0) .onChanged { _ in isPressed = true } .onEnded { _ in isPressed = false } ) } } struct ItemDetailView: View { let item: Item var body: some View { Text(item.title) } }
关键说明
.buttonStyle(PlainButtonStyle()):彻底关闭NavigationLink的默认按压高亮,避免与自定义样式冲突。@GestureState:替代普通@State,利用其手势中断自动重置的特性,无需额外监听ScrollView滚动事件,就能在用户开始滚动时恢复View的正常状态。simultaneousGesture:确保自定义手势与NavigationLink的原生点击手势并行工作,既保留跳转功能,又能实时更新按压状态。
内容的提问来源于stack exchange,提问作者soleil
相关产品推荐
相关产品推荐

