iOS Swift: UIViewControllerAnimatedTransitioning 结束帧位置错误
iOS Swift: UIViewControllerAnimatedTransitioning end frame in wrong position
我有一个 Swift 项目,学习天气 API 并试图更好地处理 AnimatedTransitions。我有一个 UITableView
使用带有图像和文本的自定义 UITableViewCell
。在 tableView 中点击一个单元格转换为一个新的 UIViewController
作为显示(推送),整个内容嵌入到 UINavigationController
.
调用转换时,单元格中的图像应该移动到目标 viewController 上 UIImageView
的最终位置。然而,它所做的是在过渡完成之前移动到屏幕的另一边,视图发生变化,使图像看起来像回到视图的中心。
我阅读了很多试图解决这个问题的教程,也阅读了很多 Whosebug,但都没有弄明白。有人可以向我指出我错过了什么吗?我要疯了,在这里。
调用转换的segue,原ViewController:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("SHOW_DETAIL", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SHOW_DETAIL" {
let detailVC = segue.destinationViewController as DetailViewController
let indexPathForForecast = self.tableView.indexPathForSelectedRow() as NSIndexPath!
let detailForecast = self.forecasts?[indexPathForForecast.row]
let cell = self.tableView.cellForRowAtIndexPath(indexPathForForecast) as WeatherCell
let image = cell.forecastImage.image
detailVC.forecastForDetail = detailForecast
detailVC.forecastDetailImage = image
}
}
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if fromVC == self && toVC.isKindOfClass(DetailViewController) {
let transitionVC = AnimateToDetailVCController()
return transitionVC
} else {
return nil
}
}
这是来自 UIViewControllerAnimatedTransitioning 对象的 animateTransition 代码(编辑:解决方案代码已编辑到代码块中,感谢@jrturton!)
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as ViewController
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as DetailViewController
let containerView = transitionContext.containerView()
let duration = self.transitionDuration(transitionContext)
let selectedRow = fromViewController.tableView.indexPathForSelectedRow()
let cell = fromViewController.tableView.cellForRowAtIndexPath(selectedRow!) as WeatherCell
let weatherSnapshot = cell.forecastImage.snapshotViewAfterScreenUpdates(false)
weatherSnapshot.frame = containerView.convertRect(cell.forecastImage.frame, fromView: fromViewController.tableView.cellForRowAtIndexPath(selectedRow!)?.superview)
cell.forecastImage.hidden = true
toViewController.view.frame = transitionContext.finalFrameForViewController(toViewController)
toViewController.view.alpha = 0
toViewController.detailImageView.hidden = true
containerView.addSubview(toViewController.view)
containerView.addSubview(weatherSnapshot)
var toFrame = toViewController.locationIs
UIView.animateWithDuration(duration, animations: { () -> Void in
// EDIT: This solved the issue, thanks JRTurton!
toViewController.view.setNeedsLayout() // Solution: This is where it was needed
toViewController.view.layoutIfNeeded() // Solution: This is where it was needed
toViewController.view.alpha = 1.0
var endRect = containerView.convertRect(toViewController.detailImageView.frame, fromView: toViewController.view)
weatherSnapshot.frame = endRect
}) { (finished) -> Void in
toViewController.detailImageView.hidden = false
cell.forecastImage.hidden = false
weatherSnapshot.removeFromSuperview()
transitionContext.completeTransition(true)
}
}
这很难说,但这是我的 猜测: 您使用的尺寸 类,设计尺寸 any/any,图像在当您将其框架用于动画时,您的视图控制器仍然居中,使其太靠右。转换完成后,将进行布局传递并进行更正。
要修复,在设置视图控制器的框架后,强制进行布局传递:
toViewController.view.setNeedsLayout()
toViewController.view.layoutIfNeeded()
在进行上述更改之前,您可以先通过检查动画前图像视图的帧来确认这是否是问题所在。
我有一个 Swift 项目,学习天气 API 并试图更好地处理 AnimatedTransitions。我有一个 UITableView
使用带有图像和文本的自定义 UITableViewCell
。在 tableView 中点击一个单元格转换为一个新的 UIViewController
作为显示(推送),整个内容嵌入到 UINavigationController
.
调用转换时,单元格中的图像应该移动到目标 viewController 上 UIImageView
的最终位置。然而,它所做的是在过渡完成之前移动到屏幕的另一边,视图发生变化,使图像看起来像回到视图的中心。
我阅读了很多试图解决这个问题的教程,也阅读了很多 Whosebug,但都没有弄明白。有人可以向我指出我错过了什么吗?我要疯了,在这里。
调用转换的segue,原ViewController:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("SHOW_DETAIL", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SHOW_DETAIL" {
let detailVC = segue.destinationViewController as DetailViewController
let indexPathForForecast = self.tableView.indexPathForSelectedRow() as NSIndexPath!
let detailForecast = self.forecasts?[indexPathForForecast.row]
let cell = self.tableView.cellForRowAtIndexPath(indexPathForForecast) as WeatherCell
let image = cell.forecastImage.image
detailVC.forecastForDetail = detailForecast
detailVC.forecastDetailImage = image
}
}
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if fromVC == self && toVC.isKindOfClass(DetailViewController) {
let transitionVC = AnimateToDetailVCController()
return transitionVC
} else {
return nil
}
}
这是来自 UIViewControllerAnimatedTransitioning 对象的 animateTransition 代码(编辑:解决方案代码已编辑到代码块中,感谢@jrturton!)
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as ViewController
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as DetailViewController
let containerView = transitionContext.containerView()
let duration = self.transitionDuration(transitionContext)
let selectedRow = fromViewController.tableView.indexPathForSelectedRow()
let cell = fromViewController.tableView.cellForRowAtIndexPath(selectedRow!) as WeatherCell
let weatherSnapshot = cell.forecastImage.snapshotViewAfterScreenUpdates(false)
weatherSnapshot.frame = containerView.convertRect(cell.forecastImage.frame, fromView: fromViewController.tableView.cellForRowAtIndexPath(selectedRow!)?.superview)
cell.forecastImage.hidden = true
toViewController.view.frame = transitionContext.finalFrameForViewController(toViewController)
toViewController.view.alpha = 0
toViewController.detailImageView.hidden = true
containerView.addSubview(toViewController.view)
containerView.addSubview(weatherSnapshot)
var toFrame = toViewController.locationIs
UIView.animateWithDuration(duration, animations: { () -> Void in
// EDIT: This solved the issue, thanks JRTurton!
toViewController.view.setNeedsLayout() // Solution: This is where it was needed
toViewController.view.layoutIfNeeded() // Solution: This is where it was needed
toViewController.view.alpha = 1.0
var endRect = containerView.convertRect(toViewController.detailImageView.frame, fromView: toViewController.view)
weatherSnapshot.frame = endRect
}) { (finished) -> Void in
toViewController.detailImageView.hidden = false
cell.forecastImage.hidden = false
weatherSnapshot.removeFromSuperview()
transitionContext.completeTransition(true)
}
}
这很难说,但这是我的 猜测: 您使用的尺寸 类,设计尺寸 any/any,图像在当您将其框架用于动画时,您的视图控制器仍然居中,使其太靠右。转换完成后,将进行布局传递并进行更正。
要修复,在设置视图控制器的框架后,强制进行布局传递:
toViewController.view.setNeedsLayout()
toViewController.view.layoutIfNeeded()
在进行上述更改之前,您可以先通过检查动画前图像视图的帧来确认这是否是问题所在。