动画期间错误的帧值

Wrong frame values during animation

我想制作一个类似 iOS 主屏幕文件夹的动画。我在主视图控制器中有一个容器视图,在容器视图中,我使用动画在两个视图控制器之间切换。
这是主视图控制器的代码 Class:

class MainContainerViewController: UIViewController {

    @IBOutlet weak var containerView: UIView!

    let duration = 1.0
    var presenting = true
    var originFrame = CGRect.zero
    var indexPathSelectedCell: IndexPath?

    var dismissCompletion: (()->())?


    func cycle(fromViewController: UIViewController, toViewController: UIViewController) {

        let folderViewC = (presenting ? fromViewController : toViewController) as! ViewController
        let projectViewC = (presenting ? toViewController : fromViewController) as! ProjectViewController

        let cellView = (presenting ? (folderViewC.folderCollectionView.cellForItem(at: folderViewC.folderCollectionView.indexPathsForSelectedItems!.first!) as! FolderCollectionViewCell).folderView : projectViewC.containerView)!
        let cellSnapshot = cellView.snapshotView(afterScreenUpdates: false)!
        let cellFrame = containerView.convert(cellView.frame, from: cellView.superview)
        cellSnapshot.frame = cellFrame
        cellView.isHidden = true

        toViewController.view.frame = self.containerView.frame
        toViewController.view.layoutIfNeeded()
        toViewController.view.alpha = 0


        presenting ? (projectViewC.containerView.isHidden = true) : ((folderViewC.folderCollectionView.cellForItem(at: self.indexPathSelectedCell!) as! FolderCollectionViewCell).folderView.isHidden = true)

        fromViewController.willMove(toParentViewController: nil)
        self.addChildViewController(toViewController)
        self.containerView.addSubview(toViewController.view)
        self.containerView.addSubview(cellSnapshot)

        UIView.animate(withDuration: duration, animations: {


            toViewController.view.alpha = 1.0

            let finalFrame = self.presenting ? projectViewC.containerView.frame : self.containerView.convert((folderViewC.folderCollectionView.cellForItem(at: self.indexPathSelectedCell!) as! FolderCollectionViewCell).folderView.frame, from: (folderViewC.folderCollectionView.cellForItem(at: self.indexPathSelectedCell!) as! FolderCollectionViewCell).folderView.superview)

            cellSnapshot.frame = finalFrame
        }) { (_) in

            if !self.presenting {
                self.dismissCompletion?()
            }

            self.presenting ? (projectViewC.containerView.isHidden = false) : ((folderViewC.folderCollectionView.cellForItem(at: self.indexPathSelectedCell!) as! FolderCollectionViewCell).folderView.isHidden = false)

            cellSnapshot.removeFromSuperview()
            fromViewController.view.removeFromSuperview()
            fromViewController.removeFromParentViewController()
            toViewController.didMove(toParentViewController: nil)

        }

    }

}

let finalFrame = self.presenting ? projectViewC.containerView.frame : self.containerView.convert((folderViewC.folderCollectionView.cellForItem(at: self.indexPathSelectedCell!) as! FolderCollectionViewCell).folderView.frame, from: (folderViewC.folderCollectionView.cellForItem(at: self.indexPathSelectedCell!) as! FolderCollectionViewCell).folderView.superview)finalFrame 设置为错误值外,所有代码均正常工作:

let finalFrame = self.presenting ? projectViewC.containerView.frame : self.containerView.convert((folderViewC.folderCollectionView.cellForItem(at: self.indexPathSelectedCell!) as! FolderCollectionViewCell).folderView.frame, from: (folderViewC.folderCollectionView.cellForItem(at: self.indexPathSelectedCell!) as! FolderCollectionViewCell).folderView.superview) 行是这样工作的:

这是整个项目:https://github.com/ale00/OnteamAnon

由于您在 projectViewController 中对 containerView 的大小使用自动布局,因此您需要在这部分代码之后在 self.containerView 上调用 layoutIfNeeded()

self.addChildViewController(toViewController)
self.containerView.addSubview(toViewController.view)
self.containerView.addSubview(cellSnapshot)

所以变成:

self.addChildViewController(toViewController)
self.containerView.addSubview(toViewController.view)
self.containerView.addSubview(cellSnapshot)
self.containerView.layoutIfNeeded()