iOS: UILabel не центрируется при расширении представления с помощью UIViewControllerTransitioningDelegate - PullRequest
1 голос
/ 07 июня 2019

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

Вот мой код:

Расширяемая база

class ExpandableBase: UIViewController {

    var senderFrame: CGRect = .zero    
    @IBOutlet weak var fullScreenPopupView: UIView?

    @IBAction func dismiss() {
        self.dismiss(animated: true, completion: nil)
    }

}

Расширение переходного делегата

extension ExpandableBase: UIViewControllerTransitioningDelegate {

    public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return ExpandableBasePresenter()
    }

    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return ExpandableBaseDismisser()
    }

}  

private final class ExpandableBasePresenter: NSObject, UIViewControllerAnimatedTransitioning {

    public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.8
    }

    public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let toViewController: ExpandableBase = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as! ExpandableBase
        let duration = self.transitionDuration(using: transitionContext)
        let containerView = transitionContext.containerView
        toViewController.view.frame = containerView.frame
        containerView.addSubview(toViewController.view)
        let finishFrame = toViewController.fullScreenPopupView?.frame
        toViewController.fullScreenPopupView?.frame = toViewController.senderFrame
        UIView.animate(withDuration: duration, delay: 0.3, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.0, options: .layoutSubviews, animations: {
            toViewController.fullScreenPopupView?.frame = finishFrame!
        }) { result in
            transitionContext.completeTransition(result)
        }
    }

}

private final class ExpandableBaseDismisser: NSObject, UIViewControllerAnimatedTransitioning {

    public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.4
    }

    public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let fromViewController: ExpandableBase = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as! ExpandableBase
        let duration = self.transitionDuration(using: transitionContext)
        UIView.animate(withDuration: duration, delay: 0.1, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.0, options: .layoutSubviews, animations: {
            fromViewController.fullScreenPopupView?.frame = fromViewController.senderFrame
        }) { result in
            transitionContext.completeTransition(result)
        }
    }

}

Простое представление с использованиемэто, представляя этикетку и кнопку отклонения:

final class ExpandableSimpleView: ExpandableBase {

    init(from initialFrame: CGRect) {
        super.init(nibName: "ExpandableSimpleView", bundle: .main)
        self.senderFrame = initialFrame
        self.transitioningDelegate = self
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("NOPE")
    }

    static func present(fromInitialFrame initialFrame: CGRect) {
        let expandableSimpleView = ExpandableSimpleView(from: initialFrame)
        expandableSimpleView.modalPresentationStyle = .overCurrentContext  
        AppDelegateTopMostViewController.present(expandableSimpleView, animated: true, completion: nil)
        //AppDelegateTopMostViewController is a global reference to the top-most view controller of the app            
    }

}

Вот соответствующий XIB:

enter image description here

И как я представляюэто из родительского контроллера представления:

@IBAction func openSimpleView(_ sender: UIButton) {
    ExpandableSimpleView.present(fromInitialFrame: sender.frame)
}

И вот несколько скриншотов, показывающих, как расширяется это представление:

enter image description here

Хотяпредставление расширяется нормально, метка не центрирована, как должно быть.Я не понимаю, почему.

Спасибо за вашу помощь.

РЕДАКТИРОВАТЬ : следуя ответу Мэтта, я внес следующие изменения в докладчика animateTransition,

    toViewController.fullScreenPopupView!.transform = 

    toViewController.fullScreenPopupView!.transform.scaledBy(x: toViewController.senderFrame.width / toViewController.view.bounds.width, y: toViewController.senderFrame.height / toViewController.view.bounds.height)
    UIView.animate(withDuration: duration, delay: 0, options: [.allowUserInteraction], animations: {
        toViewController.fullScreenPopupView!.transform = .identity
    }, completion: nil)

Теперь анимация в порядке, но я столкнулся с другой проблемой: кнопка в представлении больше не активируется.

Ответы [ 2 ]

0 голосов
/ 09 июня 2019

Нет ничего плохого в уменьшении или увеличении родительского представления.

Вам не нужно анимировать фактические виды. Вы можете создавать и удалять временные представления. Скрыть фактический вид и показать его во время удаления.

Я предлагаю вам оживить UILabel отдельно. Это не должно уменьшаться или расти. Он просто должен оставаться неподвижным. Поместите временную UILabel поверх оригинала, скройте оригинал и выполните анимацию. Обратный процесс во время разборки.

0 голосов
/ 08 июня 2019

Ваша анимация неправильная.Не начинайте с маленькой рамки и анимируйте расширение рамки.Начните с небольшого преобразования (например, значения шкалы x и y, равного 0,1) и расширьте преобразование (до .identity).

...