SwiftUI:如何在悬停时显示工具提示/提示?

And*_*rew 9 tooltip swiftui

如何在某些视图上显示工具提示/提示?例如,在按钮上。

在此处输入图片说明

Asp*_*eri 14

SwiftUI 2.0

就这么简单

   Button("Action") { }
     .help("Just do something")

   Button("Action") { }
     .help(Text("Just do something"))
Run Code Online (Sandbox Code Playgroud)

  • 对于运行 11.0 和 Xcode 12.3 部署目标的 macOS 应用程序,我可以正常工作。 (3认同)

And*_*rew 10

2020 | SwiftUI 1 和 2

在 swiftUI 2 中:

Toggle("...", isOn: $isOn)
    .help("this is tooltip")
Run Code Online (Sandbox Code Playgroud)

在 swiftUI 1 中,实际上没有创建工具提示的原生方式。但这里也有一个解决方案:

import Foundation
import SwiftUI

public extension View {
    /// Overlays this view with a view that provides a Help Tag.
    func toolTip(_ toolTip: String) -> some View {
        self.overlay(TooltipView(toolTip).allowsHitTesting(false))
    }
}

private struct TooltipView: NSViewRepresentable {
    let toolTip: String

    init(_ toolTip: String?) {
        if let toolTip = toolTip {
            self.toolTip = toolTip
        }
        else
        {
            self.toolTip = ""
        }
    }
    
    func makeNSView(context: NSViewRepresentableContext<TooltipView>) -> NSView {
        NSView()
    }

    func updateNSView(_ nsView: NSView, context: NSViewRepresentableContext<TooltipView>) {
        nsView.toolTip = self.toolTip
    }
}
Run Code Online (Sandbox Code Playgroud)


Fre*_*man 7

感谢AndrewSorin提供的解决方案指导。所提出的解决方案大部分都有效,但当我使用它们时,它们完全搞乱了布局。事实证明,工具提示有自己的大小、框架等,不会自动匹配内容。

理论上,我可以通过使用固定框架等来解决这些问题,但这对我来说似乎不是正确的方向。

我提出了以下(稍微复杂一些)但易于使用的解决方案,它没有这些缺点。

extension View {
    func tooltip(_ tip: String) -> some View {
        background(GeometryReader { childGeometry in
            TooltipView(tip, geometry: childGeometry) {
                self
            }
        })
    }
}

private struct TooltipView<Content>: View where Content: View {
    let content: () -> Content
    let tip: String
    let geometry: GeometryProxy

    init(_ tip: String, geometry: GeometryProxy, @ViewBuilder content: @escaping () -> Content) {
        self.content = content
        self.tip = tip
        self.geometry = geometry
    }

    var body: some View {
        Tooltip(tip, content: content)
            .frame(width: geometry.size.width, height: geometry.size.height)
    }
}

private struct Tooltip<Content: View>: NSViewRepresentable {
    typealias NSViewType = NSHostingView<Content>

    init(_ text: String?, @ViewBuilder content: () -> Content) {
        self.text = text
        self.content = content()
    }

    let text: String?
    let content: Content

    func makeNSView(context _: Context) -> NSHostingView<Content> {
        NSViewType(rootView: content)
    }

    func updateNSView(_ nsView: NSHostingView<Content>, context _: Context) {
        nsView.rootView = content
        nsView.toolTip = text
    }
}
Run Code Online (Sandbox Code Playgroud)

我已将 a 添加GeometryReader到工具提示的内容,然后限制工具提示的大小以匹配内容的大小。

使用方法:

Toggle("...", isOn: $isOn)
   .tooltip("This is my tip")
Run Code Online (Sandbox Code Playgroud)

2023 年 1 月添加

最新版本的 SwiftUI 需要对tooltip方法进行一些小的更改。我注意到快速重画问题。通过添加一个ZStack可以解决这个问题:

extension View {
    func tooltip(_ tip: String) -> some View {
        ZStack {
            background(GeometryReader { childGeometry in
                TooltipView(tip, geometry: childGeometry) {
                    self
                }
            })
            // self
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

2023年2月:我删除了第二个自己。有了额外的自我,父母身上就会焕发出光芒。