Как обновить frameOfPresentedViewInContainerView при использовании пользовательской модальной презентации?

Я использую собственный UIPresentationController для модального представления представления. После представления представления первое текстовое поле в представленном представлении становится первым ответчиком, и появляется клавиатура. Чтобы убедиться, что вид все еще виден, я перемещаю его вверх. Однако, когда я делаю это, frameOfPresentedViewInContainerView больше не соответствует фактическому кадру представления. Из-за этого, когда я нажимаю на представление, оно закрывается, потому что в фоновом представлении есть tapGestureRecogziner, который находится поверх представления представления. Как уведомить PresentingController об изменении кадра/позиции представленного представления?

В UIPresentationController:

    override var frameOfPresentedViewInContainerView: CGRect {
        var frame =  CGRect.zero
        let safeAreaBottom = self.presentingViewController.view.safeAreaInsets.bottom
        guard let height = presentedView?.frame.height else { return frame }
        if let containerBounds = containerView?.bounds {
            frame = CGRect(x: 0,
                           y: containerBounds.height - height - safeAreaBottom,
                           width: containerBounds.width,
                           height: height + safeAreaBottom)
        }
        return frame
    }

    override func presentationTransitionWillBegin() {
        if let containerView = self.containerView, let coordinator = presentingViewController.transitionCoordinator {
            containerView.addSubview(self.dimmedBackgroundView)
            self.dimmedBackgroundView.backgroundColor = .black
            self.dimmedBackgroundView.frame = containerView.bounds
            self.dimmedBackgroundView.alpha = 0
            coordinator.animate(alongsideTransition: { _ in
                self.dimmedBackgroundView.alpha = 0.5
            }, completion: nil)
        }
    }

Представление вида модально:

            let overlayVC = CreateEventViewController()

            overlayVC.transitioningDelegate = self.transitioningDelegate
            overlayVC.modalPresentationStyle = .custom
            self.present(overlayVC, animated: true, completion: nil)

Анимация при появлении клавиатуры (в представленном виде):

    @objc func animateWithKeyboard(notification: NSNotification) {
        let userInfo = notification.userInfo!
        guard let keyboardHeight = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height,
            let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double,
            let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt else {
                return
        }

        // bottomContraint is the constraint that pins content to the bottom of the superview.
        let moveUp = (notification.name == UIResponder.keyboardWillShowNotification)
        bottomConstraint.constant = moveUp ? (keyboardHeight) : originalBottomValue

        let options = UIView.AnimationOptions(rawValue: curve << 16)
        UIView.animate(withDuration: duration, delay: 0,
                       options: options,
                       animations: {
                        self.view.layoutIfNeeded()
        }, completion: nil)
    }

person Bjorn    schedule 17.07.2019    source источник


Ответы (1)


Из документации Apple:

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

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

person Lokesh SN    schedule 17.07.2019