iOS Swift:UIViewControllerAnimatedTransitioning结束帧位置错误

时间:2015-01-17 06:31:29

标签: ios swift uiviewcontroller uiviewanimation

我有一个Swift项目,学习天气API,并试图更好地处理AnimatedTransitions。我使用带有图片和文字的自定义UITableView UITableViewCell。点击tableView中的单元格转换为新的UIViewController作为Show(推送),整个事物嵌入UINavigationController

调用转换时,单元格中的图像应移动到目标viewController上UIImageView的最终位置。但是,它的作用是在转换完成并且视图发生变化之前移过该点到屏幕的远端,使图像看起来像是快照回到视图的中心。

screenshots

我已经阅读了很多教程试图解决这个问题,并且已经阅读了大量的StackOverflow,但未能弄明白。有人可以向我指出我错过了什么吗?我疯了,在这里。

在原始ViewController中调用转换的segue:

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

}

1 个答案:

答案 0 :(得分:17)

很难说,但这是我的猜测:你正在使用大小类,以任意/任何大小进行设计,而你查看控制器中的图像仍然是关于当你得到它的框架用于动画时,使它太远了。转换完成后,将发生布局传递并进行更正。

要修复,在设置视图控制器的框架后,强制布局传递:

toViewController.view.setNeedsLayout()
toViewController.view.layoutIfNeeded()

在进行上述更改之前,您可以先通过在动画前检查图像视图的帧来确认这是否是问题。