在菜单和
contextMenu
中,你只能放置按钮。
对于你的问题,你可以使用这个扩展:
extension View {
@ViewBuilder
func IOSPopover<Content: View>(isPresented: Binding<Bool>, arrowDirection: UIPopoverArrowDirection, @ViewBuilder content: @escaping ()->Content)->some View {
self
.background {
PopOverController(isPresented: isPresented, arrowDirection: arrowDirection, content: content())
}
}
}
使用这个:
struct PopOverController<Content: View>: UIViewControllerRepresentable {
@Binding var isPresented: Bool
var arrowDirection: UIPopoverArrowDirection
var content: Content
@State private var alreadyPresented: Bool = false
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
func makeUIViewController(context: Context) -> some UIViewController {
let controller = UIViewController()
controller.view.backgroundColor = .clear
return controller
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
if alreadyPresented {
if !isPresented {
uiViewController.dismiss(animated: true) {
alreadyPresented = false
}
}
} else {
if isPresented {
let controller = CustomHostingView(rootView: content)
controller.view.backgroundColor = .systemBackground
controller.modalPresentationStyle = .popover
controller.popoverPresentationController?.permittedArrowDirections = arrowDirection
controller.presentationController?.delegate = context.coordinator
controller.popoverPresentationController?.sourceView = uiViewController.view
uiViewController.present(controller, animated: true)
}
}
}
class Coordinator: NSObject,UIPopoverPresentationControllerDelegate{
var parent: PopOverController
init(parent: PopOverController) {
self.parent = parent
}
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
func presentationControllerWillDismiss(_ presentationController: UIPresentationController) {
parent.isPresented = false
}
func presentationController(_ presentationController: UIPresentationController, willPresentWithAdaptiveStyle style: UIModalPresentationStyle, transitionCoordinator: UIViewControllerTransitionCoordinator?) {
DispatchQueue.main.async {
self.parent.alreadyPresented = true
}
}
}
}
还有这个:
class CustomHostingView<Content: View>: UIHostingController<Content>{
override func viewDidLoad() {
super.viewDidLoad()
preferredContentSize = view.intrinsicContentSize
}
}
我用以下代码进行了测试:
@State private var openMenu: Bool = false
@State private var selection: Date = Date()
var body: some View {
VStack {
Text(stringDate(date: selection))
.padding(8)
.background(Color.white.opacity(0.6).shadow(radius: 3))
.cornerRadius(10)
.onTapGesture {
openMenu.toggle()
}
.IOSPopover(isPresented: $openMenu, arrowDirection: .down, content: {
DatePicker("", selection: $selection, displayedComponents: .date)
.datePickerStyle(.wheel)
})
}
}
func stringDate(date: Date) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "MMM d, YYYY"
return formatter.string(from: date)
}
这是结果:
请告诉我这是否有帮助!
var content: Content
呢? 如果IOSPopover块有变量,它不会更新。 - undefined