ios - 在 SwiftUI 中更改弹出窗口大小

标签 ios swift swiftui

我正在尝试为弹出窗口设置特定大小或使其适应其内容

我试图从弹出窗口更改 View 的框架,但它似乎不起作用

Button("Popover") {
        self.popover7.toggle()
}.popover(isPresented: self.$popover7, arrowEdge: .bottom) {
         PopoverView().frame(width: 100, height: 100, alignment: .center)
}

我想实现我在 iPad 的日历应用程序中发现的这种行为

enter image description here

最佳答案

@ccwasden 的解决方案非常有效。我通过在 SwiftUI 方面使其更“自然”来扩展他的工作。此外,此版本使用 sizeThatFits 方法,因此您不必指定弹出内容的大小。

struct PopoverViewModifier<PopoverContent>: ViewModifier where PopoverContent: View {
    @Binding var isPresented: Bool
    let onDismiss: (() -> Void)?
    let content: () -> PopoverContent

    func body(content: Content) -> some View {
        content
            .background(
                Popover(
                    isPresented: self.$isPresented,
                    onDismiss: self.onDismiss,
                    content: self.content
                )
            )
    }
}

extension View {
    func popover<Content>(
        isPresented: Binding<Bool>,
        onDismiss: (() -> Void)? = nil,
        content: @escaping () -> Content
    ) -> some View where Content: View {
        ModifiedContent(
            content: self,
            modifier: PopoverViewModifier(
                isPresented: isPresented,
                onDismiss: onDismiss,
                content: content
            )
        )
    }
}

struct Popover<Content: View> : UIViewControllerRepresentable {
    @Binding var isPresented: Bool
    let onDismiss: (() -> Void)?
    @ViewBuilder let content: () -> Content

    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self, content: self.content())
    }

    func makeUIViewController(context: Context) -> UIViewController {
        return UIViewController()
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        context.coordinator.host.rootView = self.content()
        if self.isPresented, uiViewController.presentedViewController == nil {
            let host = context.coordinator.host
            host.preferredContentSize = host.sizeThatFits(in: CGSize(width: Int.max, height: Int.max))
            host.modalPresentationStyle = UIModalPresentationStyle.popover
            host.popoverPresentationController?.delegate = context.coordinator
            host.popoverPresentationController?.sourceView = uiViewController.view
            host.popoverPresentationController?.sourceRect = uiViewController.view.bounds
            uiViewController.present(host, animated: true, completion: nil)
        }
    }

    class Coordinator: NSObject, UIPopoverPresentationControllerDelegate {
        let host: UIHostingController<Content>
        private let parent: Popover

        init(parent: Popover, content: Content) {
            self.parent = parent
            self.host = UIHostingController(rootView: content)
        }

        func presentationControllerWillDismiss(_ presentationController: UIPresentationController) {
            self.parent.isPresented = false
            if let onDismiss = self.parent.onDismiss {
                onDismiss()
            }
        }

        func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
            return .none
        }
    }
}

关于ios - 在 SwiftUI 中更改弹出窗口大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58834809/

相关文章:

IOS Swift 使用 URL 加载(本地)图像

iphone - 使用 setVolumeRampFromStartVolume 淡入淡出保存音频在 iOS 中不起作用

ios - iPhone 5 上的 SceneKit 和 CoreMotion "lagging"但在 iPhone 6 上正常

swift - 如何在检测到首次启动后打开首次启动页面?

ios - 适用于 iOS 14.5 的 SwiftUI NavigationLink 无法正常工作

ios - 获取请求 "unrecognized selector"错误

ios - 我是否需要将AWS S3或EC2用于我的iOS应用程序的后端?

ios - Xcode 和 Cocoapods 警告中的 EMBEDDED_CONTENT_CONTAINS_SWIFT

ios - 最近更新后 SwiftUI ForEach 不工作

ios - Objective-C 错误 "Expected identifier or ' (' "