iOS Swift:UIViewControllerAnimatedTransitioning 结束帧位置错误 [英] iOS Swift: UIViewControllerAnimatedTransitioning end frame in wrong position
问题描述
我有一个 Swift 项目,正在学习天气 API 并试图更好地处理 AnimatedTransitions.我有一个 UITableView
使用带有图像和文本的自定义 UITableViewCell
.点击 tableView 中的一个单元格会转换为一个新的 UIViewController
作为 Show(推送),整个内容嵌入在 UINavigationController
中.
I have a Swift project, learning a weather API and also trying to get a better handle on the AnimatedTransitions. I have a UITableView
using a custom UITableViewCell
with images and text. Tapping a cell in the tableView transitions to a new UIViewController
as a Show (push), with the whole thing embedded in a UINavigationController
.
当调用转换时,单元格中的图像应该移动到目标 viewController 上 UIImageView
的最终位置.然而,它所做的是在过渡完成和视图发生变化之前移过那个点到屏幕的远端,使图像看起来会回到视图的中心.
When the transition is invoked, the image from the cell is supposed to move to the final location of the UIImageView
on the destination viewController. However, what it does is move past that point to the far side of the screen before the transition completes and the view changes, making the image appear to snap back to the center of the view.
我已经阅读了很多试图解决这个问题的教程,也阅读了很多 StackOverflow,但都没有弄清楚.有人可以向我指出我错过了什么吗?我快疯了,在这里.
I have read a lot of tutorials trying to fix this and have read a lot of StackOverflow but have failed to figure it out. Can someone point out to me what I have missed, please? I'm going crazy, here.
在原始 ViewController 中调用转换的 segue:
The segue that invokes the transition, in the original 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!)
And here's the animateTransition code from the UIViewControllerAnimatedTransitioning object (EDIT: solution code edited into code block, thanks @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)
}
}
推荐答案
这很难说,但这是我的猜测:您正在使用大小类,以任意/任意大小进行设计,并且当您将其框架用于动画时,您的 to view 控制器中的图像仍然居中,使其向右太远.转换完成后,会发生布局传递并进行更正.
It's hard to say, but here's my guess: you're using size classes, designing at the any/any size, and the image in your to view controller is still centered in respect of that when you get its frame to use for your animation, making it too far to the right. Once the transition is complete, a layout pass happens and it gets corrected.
修复,在你设置到视图控制器的框架后,强制布局传递:
To fix, after you set the frame of the to view controller, force a layout pass:
toViewController.view.setNeedsLayout()
toViewController.view.layoutIfNeeded()
在进行上述更改之前,您可以先通过检查动画前的图像视图的帧来确认是否是这个问题.
Before making the above change, you can first confirm if this is the issue by checking the image view's frame before the animation.
这篇关于iOS Swift:UIViewControllerAnimatedTransitioning 结束帧位置错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!