UIViewControllerRepresentable height слишком велик

Я пытаюсь добавить контекстное меню UIKit в представление SwiftUI, потому что контекстное меню SwiftUI довольно ограничено. Мне это удалось, но UIViewControllerRepresentable занимает больше места, чем нужно. Как я могу изменить его размер, чтобы он соответствовал содержимому внутри него? Вот мой код.

Скриншот

Код SwiftUI

      struct TrackerCard: View {
    var tracker: Tracker
    var body: some View {
        HStack {
            HStack {
               ...
            }
            .padding()
            .background(Color("Wrapper"))
            .cornerRadius(15)
        }
        .padding(.horizontal)
    }
}

struct TrackerCardView: View {
    var tracker: Tracker
    var body: some View {
        ContextMenuView(card: TrackerCard(tracker: tracker))
    }
}

Код UIKit

      class ContextMenuController : UIViewController, UIContextMenuInteractionDelegate {
    
    var card: TrackerCard?
    var hostingViewController: UIHostingController<TrackerCard>?
    
    func setViewController(_ controller : UIHostingController<TrackerCard>) {
        hostingViewController = controller
        self.addChild(controller)
        controller.view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = .init(white: 1, alpha: 1)
        view.addSubview(controller.view)
        controller.didMove(toParent: self)
        controller.view.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    }
    
    func setInteraction() {
        let interaction = UIContextMenuInteraction(delegate: self)
        hostingViewController?.view.addInteraction(interaction)
    }
    
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        return ...
}

struct ContextMenuView: UIViewControllerRepresentable {
    typealias UIViewControllerType = ContextMenuController
    var card: TrackerCard
    var controller : UIViewControllerType? = nil
    
    func makeUIViewController(context: Context) -> ContextMenuController {
        let contextMenuController = controller ?? ContextMenuController()
        contextMenuController.card = card
        return contextMenuController
    }

    func updateUIViewController(_ contextMenuController: ContextMenuController, context: Context) {
        contextMenuController.setViewController(UIHostingController(rootView: card))
        contextMenuController.setInteraction()
    }
}

1 ответ

Попробуй это. Во-первых, добавьте .fixedSizeв ваше представление SwiftUI:

      ContextMenuView(card: TrackerCard(tracker: tracker))
    .fixedSize(horizontal: false, vertical: true)

При этом представление не должно быть ограничено по горизонтали, но занимать столько места, сколько ему нужно по вертикали, в зависимости от его предпочтительного размера.

Но вы можете заметить, что с текущим макетом высота сжимается (вплоть до 0).

Чтобы исправить это, нам нужно установить preferredContentSizeвот так в UIViewController:

      override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let targetSize = CGSize(width: view.bounds.width, height: UIView.layoutFittingCompressedSize.height)
    self.preferredContentSize = view.systemLayoutSizeFitting(targetSize)
}

Дополнительную информацию об этом см. в сообщении блога Самоопределение дочерних представлений .

Но высота все еще может быть установлена ​​​​на 0. В моем случае мне пришлось добавить ограничение на высоту, чтобы предпочтительная высота вычислялась по желанию (не 0).

      controller.view.heightAnchor.constraint(lessThanOrEqualTo: view.heightAnchor).isActive = true

Надеюсь, это поможет. Если нет, было бы хорошо, если бы вы отредактировали свой ответ, включив в него минимальный рабочий пример с предварительным просмотром, показывающим проблему.

Другие вопросы по тегам