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

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)行以这种方式工作:
  • 检查是否正在显示
  • (如果存在)将常量设置为最终文件夹视图的帧值
  • (如果不存在)从此文件夹的 super 视图中转换所选Collection View单元的folderView的folderView的帧值View

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

    最佳答案

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

    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()
    

    10-08 06:12