In iOS 16.4 we can now use .presentationCompactAdaptation(.none)
in our .popover
to achieve a true popover on iOS (compact screen sizes).
SomeView()
.popover(isPresented: $isPopoverOpen) {
Text("Hello world!")
.fixedSize(horizontal: false, vertical: true)
.padding()
.presentationCompactAdaptation(.none)
}
This will give us something like:
Great, it works as expected!
The issue arises when the Text()
in the popover spans multiple lines. For some reason, the popover height will only grow up to a certain height (~3 lines with non-dynamic .body
font). Here is an illustration of the issue using some Lorem Ipsum text. Notice how the end gets clipped off because the popover height is too short:
How can I make the popover fit the Text()
content? I can statically define the height but I would like the popover to perfectly fit the content.
You can get the height of the Text element using this approach.
For this, you get the height of the Text and set the height you received. This is how the code would look like
struct ContentLengthPreference: PreferenceKey {
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
struct ContentView: View {
@State private var isPopoverOpen = true
@State var textHeight: CGFloat = 0 // <-- this
var body: some View {
Text("Hello, World!")
.popover(isPresented: $isPopoverOpen) {
Text("""
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
"""
)
.overlay(
GeometryReader { proxy in
Color
.clear
.preference(key: ContentLengthPreference.self,
value: proxy.size.height) // <-- this
}
)
.onPreferenceChange(ContentLengthPreference.self) { value in // <-- this
DispatchQueue.main.async {
print (value)
self.textHeight = value
}
}
.fixedSize(horizontal: false, vertical: true)
.frame(height: textHeight)
.padding()
.presentationCompactAdaptation(.none)
}
}
}
Happy Coding!