I created tool tip in swiftui, but when I use it with overlay - frame is break.
import SwiftUI
struct HintBox: View {
@State private var showTooltip = true
var body: some View {
VStack {
Text("Here text")
TooltipView(text: "it's hint! it's hint! it's hint! it's hint! it's hint! it's hint!", isVisible: $showTooltip)
.frame(maxWidth: .infinity)
.onTapGesture {
showTooltip.toggle()
}
}
}
}
struct TooltipView: View {
var text: String
@Binding var isVisible: Bool
var body: some View {
ZStack(alignment: .top) {
if isVisible {
Text(text)
.padding()
.background(Color.gray)
.foregroundColor(.white)
.cornerRadius(8)
Triangle()
.fill(Color.gray)
.frame(width: 20, height: 10)
.offset(y: 0)
}
}
}
}
struct Triangle: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.midX - 10, y: rect.minY))
path.addLine(to: CGPoint(x: rect.midX, y: rect.minY - 10))
path.addLine(to: CGPoint(x: rect.midX + 10, y: rect.minY))
path.closeSubpath()
return path
}
}
I need to make it so that I can determine exactly where the triangle will be (bottom or top), in the middle, or left or right. and also, it must be above other views. i.e. point with a triangle at the view to which I will attach it. and when you click on it, it should stop being displayed
You might find that a
popovergives you the functionality you want, without having to re-invent it. However, on an iPhone, a popover is shown as a sheet.Otherwise, one way to implement this is to show the hint as an overlay over the source view. An overlay automatically adopts the size of the underlying view and using a
GeometryReaderyou can find the size of the source view in this way.You want the hint to be able to break out of the bounds of the source footprint. This is done by using
.fixedSize(). However, this means, the overlay is no longer centered, so you have to apply an offset to bring it back to center.Then, to align the hint above, below, before or after the source view, you need to know the size of the hint itself. Here you can use the same technique again, setting an overlay over a hidden version of the hint and using another
GeometryReaderto find its size.Here is an attempt to show it working:
EDIT: Updated to take a closure as parameter. If the hint consists of long text then the caller can set a sensible width for it.