iOS Swift:UIViewControllerAnimatedTransitioning 结束帧位置错误 [英] iOS Swift: UIViewControllerAnimatedTransitioning end frame in wrong position

查看:21
本文介绍了iOS Swift:UIViewControllerAnimatedTransitioning 结束帧位置错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆