Как обновить макет (положение) всплывающего окна, когда его исходный вид меняет свой вид в Swift?

Я хочу обновить макет поповера, я уже пытался использовать setNeedsLayout() а также layoutIfNeeded() методы, но не смогли найти решение.

У меня есть простой экран с 4 кнопками, которые вызывают поповер, в попопере есть 2 дополнительные кнопки:

  1. Кнопка -> скрывает button3 и перемещает button1 и button2 влево.
  2. reposition -> изменяет исходный вид всплывающего окна с button1/2/3/4 (отправитель) на button4. Изображение макета

У меня проблема в том, что я не могу обновить / обновить экран, а поповер продолжает указывать на прежнюю исходную позицию просмотра. Изображение поповера

Почему-то мне нужен метод, который обновляет мой взгляд и который сильнее, чем layoutIfNeeded() потому что если экран меняется с портретного / ландшафтного, всплывающее окно меняется автоматически. Здесь я сменил портрет / пейзаж / портрет

GitHub проекта. GitHub

Используемый код следующий:

class ViewController: UIViewController, ButtonDidDisappearDelegate {

    @IBOutlet weak var button1: UIButton!
    @IBOutlet weak var button2: UIButton!
    @IBOutlet weak var button3: UIButton!
    @IBOutlet weak var button4: UIButton!

    @IBOutlet weak var constrain2: NSLayoutConstraint!

    var popVC: PopVC?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func buttonPopover(_ sender: UIButton) {
        configureAndPresentPopover(from: sender)
    }

    func buttonDisappear() {
        self.constrain2.constant = 100
        self.button3.isHidden = !self.button3.isHidden

        if !self.button3.isHidden {
            self.constrain2.constant = 10
        }
    }

    func repositionPopover() {
        DispatchQueue.main.async {
            if let popVC = self.popVC {
                self.self.popoverPresentationController(popVC.popoverPresentationController!, willRepositionPopoverTo: self.button4.bounds, in: self.button4)
            }
            self.view.setNeedsLayout()
            self.view.layoutIfNeeded()
        }
    }
}

extension ViewController: UIPopoverPresentationControllerDelegate {

    func configureAndPresentPopover(from sender: UIButton) {

        popVC = storyboard?.instantiateViewController(withIdentifier: "popVC") as? PopVC

        guard let popVC = popVC else {
            return
        }

        popVC.popOverDelegate = self
        popVC.modalPresentationStyle = .popover

        let popOverVC = popVC.popoverPresentationController
        popOverVC?.delegate = self
        popOverVC?.sourceView = sender
        popOverVC?.sourceRect = sender.bounds
        popVC.preferredContentSize = CGSize(width: 300, height: 60)
        popOverVC?.permittedArrowDirections = .down

        self.present(popVC, animated: true)
    }

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

    func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController,
                                       willRepositionPopoverTo rect: CGRect,
                                       in view: UIView) {
        popoverPresentationController.sourceView = view
        popoverPresentationController.sourceRect = rect
    }
}

и контроллер поповера:

protocol ButtonDidDisappearDelegate: class {
    func configureAndPresentPopover(from sender: UIButton)
    func buttonDisappear()
    func repositionPopover()
}

class PopVC: UIViewController {

    weak var popOverDelegate: ButtonDidDisappearDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()
    }


    @IBOutlet weak var popoverButton: UIButton!

    @IBAction func popoverAction(_ sender: Any) {
        popOverDelegate?.buttonDisappear()
        DispatchQueue.main.async {
            self.view.setNeedsLayout()
            self.view.layoutIfNeeded()
        }
    }

    @IBAction func reposition(_ sender: Any) {
        popOverDelegate?.repositionPopover()
    }
}

1 ответ

Вам нужно указать новую позицию стрелки и запросить компоновку представления контроллера презентации, а не только представленного представления.

Пытаться:

func repositionPopover() {
    let popOverController = presentedViewController?.presentationController as? UIPopoverPresentationController
    popOverController?.sourceView = button4
    popOverController?.containerView?.setNeedsLayout()
    popOverController?.containerView?.layoutIfNeeded()
}

(Нет необходимости отправлять в основной поток, вы уже находитесь в этом потоке при использовании UIKit)

Вы можете попробовать еще раз установить исходный вид и исходный код. вызвать эту функцию при изменении границ sourcview.

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