Ios 自定义UIViewController动画问题
我使用Ios 自定义UIViewController动画问题,ios,swift,animation,uiviewcontroller,Ios,Swift,Animation,Uiviewcontroller,我使用UIViewControllerAnimatedTransitioning为UIViewController创建了一个简单的自定义转换动画。一切正常,但当目标视图出现时,内容从右下角开始显示,当视图消失时,内容从左上角消失。我附上了gif的例子。这是我的代码: CustomViewAnimator.swift class CustomViewAnimator: NSObject, UIViewControllerAnimatedTransitioning { private le
UIViewControllerAnimatedTransitioning
为UIViewController
创建了一个简单的自定义转换动画。一切正常,但当目标视图出现时,内容从右下角开始显示,当视图消失时,内容从左上角消失。我附上了gif的例子。这是我的代码:
CustomViewAnimator.swift
class CustomViewAnimator: NSObject, UIViewControllerAnimatedTransitioning {
private let interval = 0.5
var forward = false
var originFrame: CGRect = .zero
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return interval
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
guard let toView = transitionContext.view(forKey: .to) else {return}
guard let fromView = transitionContext.view(forKey: .from) else {return}
let destinationView = forward ? toView : fromView
destinationView.alpha = forward ? 0 : 1
forward ? containerView.addSubview(toView) : containerView.insertSubview(toView, belowSubview: fromView)
forward ? (destinationView.frame = originFrame) : (destinationView.frame = fromView.frame)
UIView.animate(withDuration: interval, animations: {
self.forward ? (destinationView.frame = fromView.frame) : (destinationView.frame = self.originFrame)
destinationView.alpha = self.forward ? 1 : 0
}) { (finished) in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
}
MainViewController.self
class MainViewController: UIViewController {
private var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
@objc private func openView() {
let viewController = TargetViewController()
viewController.transitioningDelegate = self
navigationController?.pushViewController(viewController, animated: true)
}
}
extension MainViewController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animator = CustomViewAnimator()
animator.originFrame = button.frame
animator.forward = (operation == .push)
return animator
}
}
extension MainViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animator = CustomViewAnimator()
animator.forward = true
return animator
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animator = CustomViewAnimator()
animator.forward = false
return animator
}
}
TargetViewController.swift
class TargetViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
}
extension TargetViewController {
fileprivate func setup() {
view.backgroundColor = .orange
navigationItem.title = "Target view"
let label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Hello from target view :)"
label.textColor = .white
label.font = UIFont.boldSystemFont(ofSize: 18)
return label
}()
view.addSubview(label)
label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
}
有谁能告诉我如何解决这个问题,使TargetViewController中的标签(或任何其他内容)固定在它们的位置上
基本上,您的问题是因为混合了自动布局和框架。在带有约束的
ViewController
s视图中定位子视图(按钮和标签),但对于动画,使用帧更新。所以,正如我正确理解布局是如何工作的一样,标签约束在转换过程中并没有激活,或者至少布局引擎并没有使用它来计算标签的位置
因此,最好的建议是避免在转换中使用帧动画,并尝试为.from
和.to
视图创建适当的约束,并为约束的常量设置动画。这将需要更多的代码,但您可以确保不会混合两种不同的布局策略
更简单的解决方案是告诉containerView
计算约束,并在动画期间通过简单地将containerView.layoutifneedd()
添加到动画块来适当定位元素。因此,这将是:
UIView.animate(withDuration: interval, animations: {
self.forward ? (destinationView.frame = fromView.frame) : (destinationView.frame = self.originFrame)
destinationView.alpha = self.forward ? 1 : 0
containerView.layoutIfNeeded()
}) { (finished) in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
但这只会让事情顺利进行,并不能解决同时使用两种布局策略的主要问题。我同意其他答案中的讨论。我的建议是,不要设置UIView帧的动画,您可以如下所示设置目标视图的遮罩的动画。这应该是歌剧演员真正想要的效果 粗体部分与原始帖子不同。
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
guard let toView = transitionContext.view(forKey: .to) else {return}
guard let fromView = transitionContext.view(forKey: .from) else {return}
let destinationView = forward ? toView : fromView
destinationView.alpha = forward ? 0 : 1
让maskView=UIView.init(帧:前进?原始帧:fromView.frame)
maskView.backgroundColor=UIColor.white
destinationView.mask=maskView
自我推进?(destinationView.mask?frame=fromView.frame):(destinationView.mask?frame=self.originFrame)
你能展示TargetViewController,特别是它对标签的约束吗?@PeterTretyakov我通过添加TargetViewController编辑了我的帖子,我在另一个资源中发现了这一点。我用cabasicanition而不是UIView.animation修复了它
forward ? containerView.addSubview(toView) : containerView.insertSubview(toView, belowSubview: fromView)
forward ? (destinationView.frame = toView.frame) : (destinationView.frame = fromView.frame)
UIView.animate(withDuration: interval, animations: {
destinationView.alpha = self.forward ? 1 : 0
}) { (finished) in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}