You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:05:04