我试图在点击按钮时以模态形式显示视图,该视图最初与按钮具有相同的帧,然后展开以全屏显示,所有这些都使用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:
以及我如何从父视图控制器中呈现此内容:
@IBAction func openSimpleView(_ sender: UIButton) {
ExpandableSimpleView.present(fromInitialFrame: sender.frame)
}
以下是显示此视图如何扩展的一些屏幕截图:
尽管视图可以很好地扩展,但标签并未居中对齐。我不明白为什么。
谢谢您的帮助。
编辑:根据马特的回答,我对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)
现在动画很好,但我面临另一个问题:视图中的按钮不再可单击。
答案 0 :(得分:0)
您的动画是错误的。不要从小框架开始,而要为框架的扩展动画。从一个小的 transform 开始(例如x和y比例值为0.1),然后扩展该转换(扩展为.identity
)。
答案 1 :(得分:0)
缩小或扩大父视图没有错。
您不必设置实际视图的动画。您可以创建和删除临时视图。隐藏实际视图并在下架时显示。
我建议您分别为UILabel设置动画。它不必缩小或增长。它仅需保持静止。将临时UILabel放置在原件上,隐藏原件,然后执行动画。在下架过程中逆转该过程。