如何在SwiftUI中实现类似macOS菜单列表的按钮闪烁效果?
实现macOS菜单风格按钮点击闪烁效果
要实现点击释放后蓝色→透明→蓝色→消失的闪烁效果,核心是拆分悬停与点击的状态控制,并通过时序动画实现多步状态切换。你的原有代码问题在于用同一个变量同时控制悬停和点击动画,且未处理点击后的状态延迟切换,导致动画冲突且无闪烁效果。
解决方案代码
@State private var hovered = false @State private var isBlinking = false public func makeBody(configuration: Configuration) -> some View { configuration.label .background { // 显示优先级:点击闪烁 > 悬停高亮 if isBlinking { Color.accentColor } else if hovered { Color.accentColor } else { Color.clear } } .onHover { newValue in // 悬停状态即时切换,无动画(贴合macOS原生菜单体验) hovered = newValue } .onTapGesture { startBlinking() } } private func startBlinking() { // 第一步:立即显示蓝色 withAnimation(.easeOut(duration: 0.1)) { isBlinking = true } // 第二步:延迟0.1秒切换为透明 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { withAnimation(.easeOut(duration: 0.1)) { isBlinking = false } } // 第三步:延迟0.2秒再次显示蓝色 DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { withAnimation(.easeOut(duration: 0.1)) { isBlinking = true } } // 第四步:延迟0.3秒恢复透明,结束闪烁 DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { withAnimation(.easeOut(duration: 0.1)) { isBlinking = false } } }
关键说明
- 状态拆分:用
hovered控制悬停高亮,isBlinking控制点击后的闪烁效果,彻底避免状态冲突。 - 动画隔离:悬停状态切换无动画,保持原生菜单的即时反馈;点击闪烁的每一步状态切换单独绑定动画,确保仅闪烁过程有过渡效果。
- 时序控制:通过
DispatchQueue.main.asyncAfter实现精准的延迟切换,完美复刻蓝→透明→蓝→消失的闪烁节奏。 - 优先级处理:背景颜色判断优先响应
isBlinking状态,确保点击闪烁时覆盖悬停效果,符合交互逻辑。
内容的提问来源于stack exchange,提问作者Yiming Designer
相关产品推荐
相关产品推荐

