macOS下如何关闭遵循TipViewStyle的自定义Tip视图?
一、正确关闭Tip视图的方式
你当前用自定义参数控制显示的方式虽能生效,但不符合TipKit的原生设计逻辑。TipKit内置了complete()方法与didComplete状态来管理Tip的显示,无需手动维护布尔变量,优化后的实现如下:
优化代码
import TipKit struct ShortcutTip: Tip { var title: Text { Text("Pro Tip!!") } // 规则:仅当Tip未完成时显示 var rules: [Rule] { #Rule { $0.didComplete == false } } var actions: [Action] { Action(id: "ok") { // 标记Tip为已完成,触发规则自动隐藏Tip self.complete() } label: { Text("OK") } } }
原理说明
- TipKit会自动维护
didComplete状态,调用complete()后该状态变为true,规则$0.didComplete == false不再满足,Tip会自动隐藏。 - 该状态默认会被持久化存储,重启App后已完成的Tip不会再次显示。
- 若需手动强制关闭Tip,可直接调用:
TipManager.shared.dismiss(ShortcutTip.self)
二、添加鼠标悬停显示的关闭按钮
默认TipViewStyle未自带悬停关闭按钮,可通过自定义TipViewStyle或扩展Tip内容实现:
方案1:自定义TipViewStyle全局替换样式
struct HoverCloseTipViewStyle: TipViewStyle { func makeBody(configuration: Configuration) -> some View { VStack(alignment: .leading, spacing: 8) { HStack { configuration.title Spacer() // 悬停时显示关闭按钮 Button(action: { configuration.tip.complete() }) { Image(systemName: "xmark.circle") .foregroundColor(.secondary) } .opacity(configuration.isHovered ? 1 : 0) .animation(.easeInOut(duration: 0.2), value: configuration.isHovered) } configuration.message // 若Tip有message可保留 configuration.actions } .padding() .background(.background) .cornerRadius(8) .shadow(radius: 4) } } // 使用方式 TipView(ShortcutTip()) .tipViewStyle(HoverCloseTipViewStyle())
方案2:在单个Tip中嵌入悬停按钮
如果不想全局替换样式,可直接在Tip的标题区域添加按钮:
struct ShortcutTip: Tip { var title: some View { HStack { Text("Pro Tip!!") Spacer() Button(action: { self.complete() }) { Image(systemName: "xmark.circle") .foregroundColor(.secondary) } .opacity(TipView.isHovered ? 1 : 0) .animation(.easeInOut(duration: 0.2), value: TipView.isHovered) } } var rules: [Rule] { #Rule { $0.didComplete == false } } var actions: [Action] { Action(id: "ok") { self.complete() } label: { Text("OK") } } }
注意事项
TipView.isHovered是TipKit提供的环境变量,可直接读取判断Tip是否处于悬停状态。- 关闭按钮点击逻辑统一调用
complete(),确保状态与Tip的显示规则保持一致。
内容的提问来源于stack exchange,提问作者Kaunteya
相关产品推荐
相关产品推荐

