我想制作一个类似于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)
行以这种方式工作:这是整个项目: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()