SwiftUI:如何在悬停时显示工具提示/提示?
SwiftUI : How do you display a tooltip / hint on hover?
如何在某些视图上显示工具提示/提示?
例如,在按钮上。
2020 | SwiftUI 1 和 2
在 swiftUI 2 中:
Toggle("...", isOn: $isOn)
.help("this is tooltip")
在 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
}
}
当叠加层不够好时,例如你想要接受鼠标事件的控件上的工具提示(并且覆盖不允许点击),例如 Toggle,一个解决方案可能是使用内部包含 NSHostingView 本身的主机视图 - 支持作为 AppKit 视图的工具提示- 最终在内部加载更多 SwiftUI 内容:
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: NSViewRepresentableContext<Tooltip<Content>>) -> NSViewType {
NSViewType(rootView: content)
}
func updateNSView(_ nsView: NSViewType, context: NSViewRepresentableContext<Tooltip<Content>>) {
nsView.rootView = content
nsView.toolTip = text
}
}
当与某些 SwiftUI 内容一起使用时,这确实有一些关于调整大小的注意事项(然后您可能希望使用 fixedSize() 或 frame(width:height:) 使其根据需要工作),但它在其他方面很容易使用:
Tooltip("A description") {
Toggle("...", isOn: $isOn)
}
感谢 Andrew and Sorin 两位的指导。所提供的解决方案大多有效,但当我使用它们时,它们完全弄乱了布局。事实证明,工具提示有自己的大小、框架等,不会自动匹配内容。
理论上我可以通过使用固定框架等来解决这些问题,但这对我来说似乎不是正确的方向。
我提出了以下(稍微复杂一些)但易于使用且没有这些缺点的解决方案。
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
}
}
我在工具提示的内容中添加了一个 GeometryReader
,然后将工具提示的大小限制为与内容的大小相匹配。
要使用它:
Toggle("...", isOn: $isOn)
.tooltip("This is my tip")
SwiftUI 2.0
就这么简单
Button("Action") { }
.help("Just do something")
Button("Action") { }
.help(Text("Just do something"))
struct TooltipText: View {
@State private var isActive = false
let text: String
let helpText: String
var body: some View {
Text(isActive ? helpText : text)
.padding( isActive ? 6 : 0)
.background(Color.white)
.overlay(
RoundedRectangle(cornerRadius: 3)
.stroke(Color.blue, lineWidth: isActive ? 1 : 0)
)
.animation(.easeOut(duration: 0.2) )
.gesture(DragGesture(minimumDistance: 0)
.onChanged( { _ in isActive = true } )
.onEnded( { _ in isActive = false } )
)
}
}
使用:
TooltipText(text: "sum of squares:", helpText: "sum of data (with mean subtracted) squared")
如何在某些视图上显示工具提示/提示? 例如,在按钮上。
2020 | SwiftUI 1 和 2
在 swiftUI 2 中:
Toggle("...", isOn: $isOn)
.help("this is tooltip")
在 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
}
}
当叠加层不够好时,例如你想要接受鼠标事件的控件上的工具提示(并且覆盖不允许点击),例如 Toggle,一个解决方案可能是使用内部包含 NSHostingView 本身的主机视图 - 支持作为 AppKit 视图的工具提示- 最终在内部加载更多 SwiftUI 内容:
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: NSViewRepresentableContext<Tooltip<Content>>) -> NSViewType {
NSViewType(rootView: content)
}
func updateNSView(_ nsView: NSViewType, context: NSViewRepresentableContext<Tooltip<Content>>) {
nsView.rootView = content
nsView.toolTip = text
}
}
当与某些 SwiftUI 内容一起使用时,这确实有一些关于调整大小的注意事项(然后您可能希望使用 fixedSize() 或 frame(width:height:) 使其根据需要工作),但它在其他方面很容易使用:
Tooltip("A description") {
Toggle("...", isOn: $isOn)
}
感谢 Andrew and Sorin 两位的指导。所提供的解决方案大多有效,但当我使用它们时,它们完全弄乱了布局。事实证明,工具提示有自己的大小、框架等,不会自动匹配内容。
理论上我可以通过使用固定框架等来解决这些问题,但这对我来说似乎不是正确的方向。
我提出了以下(稍微复杂一些)但易于使用且没有这些缺点的解决方案。
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
}
}
我在工具提示的内容中添加了一个 GeometryReader
,然后将工具提示的大小限制为与内容的大小相匹配。
要使用它:
Toggle("...", isOn: $isOn)
.tooltip("This is my tip")
SwiftUI 2.0
就这么简单
Button("Action") { }
.help("Just do something")
Button("Action") { }
.help(Text("Just do something"))
struct TooltipText: View {
@State private var isActive = false
let text: String
let helpText: String
var body: some View {
Text(isActive ? helpText : text)
.padding( isActive ? 6 : 0)
.background(Color.white)
.overlay(
RoundedRectangle(cornerRadius: 3)
.stroke(Color.blue, lineWidth: isActive ? 1 : 0)
)
.animation(.easeOut(duration: 0.2) )
.gesture(DragGesture(minimumDistance: 0)
.onChanged( { _ in isActive = true } )
.onEnded( { _ in isActive = false } )
)
}
}
使用:
TooltipText(text: "sum of squares:", helpText: "sum of data (with mean subtracted) squared")