我想制作一个像iOS主屏幕文件夹一样的动画。我在主视图 Controller 中有一个容器 View ,在容器 View 中我用动画在两个 View Controller 之间切换。
这是主视图 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)
线路的工作方式如下:
- 检查是否显示
- 如果正在呈现,则将常量设置为最终文件夹 View 的帧值
- 如果关闭,则从该folderView的 super View 中转换所选 Collection View 单元格的folderView的frame值
最佳答案
由于您在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()
关于ios - 动画期间的帧值错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39021786/