I would like use .popover
with .presentationCompactAdaptation(.popover)
in an iPhone iOS 16+ app. This shows the popover not as sheet but as real popover not only on iPad but on iPhone as well.
While this works fine in general, the popover is not positioned correctly when coming close to the bottom screen edge.
In the following example the popover is positioned correctly to the top and side screen edges (buttons 1-3). Button 5 at the very bottom shows the popover above the button. However, the popover of button 4 is not shown above the button (although there is enough free space) but below the button. Since there is not enough space, the content is clipped.
This is quite strange, isn't it? Is this some bug or intended behavior? Can this be fixed?
struct PopoverTest: View {
var body: some View {
VStack {
HStack {
PopoverButton(text: "Button 1")
Spacer()
}
Spacer()
HStack {
Spacer()
PopoverButton(text: "Button 2")
}
Spacer()
HStack {
Spacer(minLength: 270)
PopoverButton(text: "Button 3")
Spacer()
}
PopoverButton(text: "Button 4")
.padding(.top, 300)
Spacer()
PopoverButton(text: "Button 5")
}
}
}
struct PopoverButton: View {
@State private var isPresented = false
var text: String
var body: some View {
Button(action: { isPresented = true }) {
Text(text)
}
.popover(isPresented: $isPresented) {
VStack {
Text("Some Line of Text 1")
Text("Some Line of Text 2")
Text("Some Line of Text 3")
Text("Some Line of Text 4")
Text("Some Line of Text 5")
Text("Some Line of Text 6")
Text("Some Line of Text 7")
Text("Some Line of Text 8")
Text("Some Line of Text 9")
}
.presentationCompactAdaptation(.popover)
}
}
}
I would like use .popover
with .presentationCompactAdaptation(.popover)
in an iPhone iOS 16+ app. This shows the popover not as sheet but as real popover not only on iPad but on iPhone as well.
While this works fine in general, the popover is not positioned correctly when coming close to the bottom screen edge.
In the following example the popover is positioned correctly to the top and side screen edges (buttons 1-3). Button 5 at the very bottom shows the popover above the button. However, the popover of button 4 is not shown above the button (although there is enough free space) but below the button. Since there is not enough space, the content is clipped.
This is quite strange, isn't it? Is this some bug or intended behavior? Can this be fixed?
struct PopoverTest: View {
var body: some View {
VStack {
HStack {
PopoverButton(text: "Button 1")
Spacer()
}
Spacer()
HStack {
Spacer()
PopoverButton(text: "Button 2")
}
Spacer()
HStack {
Spacer(minLength: 270)
PopoverButton(text: "Button 3")
Spacer()
}
PopoverButton(text: "Button 4")
.padding(.top, 300)
Spacer()
PopoverButton(text: "Button 5")
}
}
}
struct PopoverButton: View {
@State private var isPresented = false
var text: String
var body: some View {
Button(action: { isPresented = true }) {
Text(text)
}
.popover(isPresented: $isPresented) {
VStack {
Text("Some Line of Text 1")
Text("Some Line of Text 2")
Text("Some Line of Text 3")
Text("Some Line of Text 4")
Text("Some Line of Text 5")
Text("Some Line of Text 6")
Text("Some Line of Text 7")
Text("Some Line of Text 8")
Text("Some Line of Text 9")
}
.presentationCompactAdaptation(.popover)
}
}
}
Share
Improve this question
asked Mar 19 at 8:54
Andrei HerfordAndrei Herford
18.8k24 gold badges108 silver badges258 bronze badges
4
|
1 Answer
Reset to default 0Thanks so the hint of @DonMag and after some more digging, I was able to find a solution.
It seems that this is a <s>bug</s> intended behaviour in iOS 18+. The arrowEdge
is not use as a hint anymore (place the arrow here, if there is sufficient space) but as constraint (place the arrow here and clip content if necessary).
This can be solved with the following wrapper which uses different calls for iOS18 or below:
extension View {
@ViewBuilder func autoEdgePopover<Content: View>(
isPresented: Binding<Bool>,
attachmentAnchor: PopoverAttachmentAnchor = .rect(.bounds),
@ViewBuilder content: @escaping () -> Content
) -> some View {
if #available(iOS 18, *) {
self
.popover(isPresented: isPresented, attachmentAnchor: attachmentAnchor, content: content)
} else {
self
.popover(isPresented: isPresented, attachmentAnchor: attachmentAnchor, arrowEdge: .top, content: content)
}
}
}
arrowEdge
option with the popover guy. – El Tomato Commented Mar 19 at 9:57.bottom
the popover of Button1 does not show. With.leading
the popover of Button3 is clipped, etc. – Andrei Herford Commented Mar 19 at 11:32