I am trying to get a popover working on an iPad with swiftUI. The popover shows fine, however, when I rotate the device, the popover goes all over the place and does not anchor to its original place. Anybody a solution for this?
import SwiftUI
struct PopOver: View {
var body: some View {
Text("Hello world")
}
}
struct ContentView: View {
@State private var showPopover: Bool = false
var body: some View {
Button(action: {
self.showPopover = true
}) {
Text("Select")
}
.popover(
isPresented: self.$showPopover
) {
PopOver()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().previewDevice(PreviewDevice(rawValue: "iPad Pro (10.5-inch)"))
}
}
Workaround
show popover again, if it was shown before rotation
import SwiftUI import SwiftUI import UIKit import Combine struct PopOver: View { var body: some View { Text("Hello world") } } class Model: ObservableObject { @Published var show = false var handle: AnyCancellable? init() { handle = NotificationCenter.Publisher(center: .default, name: UIDevice.orientationDidChangeNotification).sink { (_) in print("orientation") if self.show { self.show = false DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.show = true } } } } deinit { handle?.cancel() handle = nil } } struct ContentView: View { @ObservedObject var popoverModel = Model() var body: some View { Button(action: { self.popoverModel.show.toggle() }) { Text("Select") } .popover( isPresented: self.$popoverModel.show ) { PopOver() } } }
WARNING!
if self.show { self.show = false DispatchQueue.main.asyncAfter(deadline: .now() + 1) { self.show = true } }
is very fragile, you better to find different way how to show popover not before the rotation transition finished.
Same as user3441734's answer, just more concise:
struct ContentView: View {
@State var show = false
var body: some View {
Button("Select") { self.show.toggle() }
.popover(isPresented: $show, content: {
PopOver()
})
.hideOnRotate(show: $show)
}
}
extension View {
func hideOnRotate(show: Binding<Bool>) -> some View {
onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification),
perform: { _ in show.wrappedValue = false })
}
}
If you want to try to re-show as in the other answer, just add logic in the perform
block.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.