Как обновить макет (положение) всплывающего окна, когда его исходный вид меняет свой вид в Swift?
Я хочу обновить макет поповера, я уже пытался использовать setNeedsLayout()
а также layoutIfNeeded()
методы, но не смогли найти решение.
У меня есть простой экран с 4 кнопками, которые вызывают поповер, в попопере есть 2 дополнительные кнопки:
- Кнопка -> скрывает button3 и перемещает button1 и button2 влево.
- 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.