iOS:使用UIViewControllerTransitioningDelegate扩展视图时,UILabel没有居中

时间:2019-06-07 19:49:30

标签: ios autolayout uiviewanimationtransition

我试图在点击按钮时以模态形式显示视图,该视图最初与按钮具有相同的帧,然后展开以全屏显示,所有这些都使用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 :(得分:0)

您的动画是错误的。不要从小框架开始,而要为框架的扩展动画。从一个小的 transform 开始(例如x和y比例值为0.1),然后扩展该转换(扩展为.identity)。

答案 1 :(得分:0)

缩小或扩大父视图没有错。

您不必设置实际视图的动画。您可以创建和删除临时视图。隐藏实际视图并在下架时显示。

我建议您分别为UILabel设置动画。它不必缩小或增长。它仅需保持静止。将临时UILabel放置在原件上,隐藏原件,然后执行动画。在下架过程中逆转该过程。