更改 SwiftUI 中的弹出窗口大小

Sor*_*ica 4 ios swift swiftui

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

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

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

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

在此输入图像描述

Kou*_*iga 12

@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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


ccw*_*den 7

我让它在 iOS 上使用自定义的UIViewRepresentable. 用法如下:

struct Content: View {
    @State var open = false
    @State var popoverSize = CGSize(width: 300, height: 300)

    var body: some View {
        WithPopover(
            showPopover: $open,
            popoverSize: popoverSize,
            content: {
                Button(action: { self.open.toggle() }) {
                    Text("Tap me")
                }
        },
            popoverContent: {
                VStack {
                    Button(action: { self.popoverSize = CGSize(width: 300, height: 600)}) {
                        Text("Increase size")
                    }
                    Button(action: { self.open = false}) {
                        Text("Close")
                    }
                }
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

是一个要点及其来源WithPopover