与UIViewControllerAnimatedTransitioning不一致的行为

时间:2015-10-06 09:44:27

标签: ios animation uicollectionview transition

我正在使用UIViewControllerAnimatedTransitioning进行自定义动画以这种方式工作:在collectionView中,用户点击一个单元格(照片),然后逐渐增加fedding,直到它到达某个帧另一个控制器当用户点击最后一个控制器中的关闭按钮时,转换会返回(从最后一个控制器到collectionView单元格)。

第一步正常工作,而第二步工作并不总是正常。有时它会回到集合视图的右边框架,有时候不会,它会偏离其他地方。

下面我将代码放在一些打印之间,以了解框架的行为:

import UIKit

class AccessPlanTransition : NSObject, UIViewControllerAnimatedTransitioning {

 var presenting = false
 var index: NSIndexPath?

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

if presenting {
  if let fromControllerList = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? PlansListViewController,
    let toControllerHome = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? HomeTableViewController,
    let container = transitionContext.containerView()

  {
    let duration = transitionDuration(transitionContext)

    let index = (fromControllerList.collectionView?.indexPathsForSelectedItems()!.first)!

      if let cell = fromControllerList.collectionView(fromControllerList.collectionView!, cellForItemAtIndexPath: index) as? PlanInListCollectionViewCell {

        let cellImageViewSnapShot = cell.image.snapshotViewAfterScreenUpdates(true)
        cellImageViewSnapShot.frame = container.convertRect(cell.image.frame, fromView: cell.image.superview)
        print("presenting cellImageViewSnapShot cell.image.frame \(cell.image.frame) cell.image.superview  \(cell.image.superview)")

        cell.image.hidden = true
        print("presenting cellImageViewSnapShot.frame \(cellImageViewSnapShot.frame)")

        toControllerHome.view.frame = transitionContext.finalFrameForViewController(toControllerHome)
        print("presenting toControllerHome.view.frame \(toControllerHome.view.frame)")
        toControllerHome.view.alpha = 0.0
        toControllerHome.travelImage.hidden = true

        container.addSubview(toControllerHome.view)
        container.addSubview(cellImageViewSnapShot)

        UIView.animateWithDuration(duration, animations: {
          toControllerHome.view.alpha = 1.0
          let frame = container.convertRect(toControllerHome.travelImage.frame, fromView: toControllerHome.view)
          print("presenting frame  \(frame)")
          print("presenting = container.convertRect toControllerHome.travelImage.frame \(toControllerHome.travelImage.frame) toControllerHome.view  \(toControllerHome.view)")
          cellImageViewSnapShot.frame = frame
          print("presenting cellImageViewSnapShot.frame \(cellImageViewSnapShot.frame)")
          }, completion: { finished in
            toControllerHome.travelImage.hidden = false
            cell.image.hidden = false
            cellImageViewSnapShot.removeFromSuperview()

            transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
        })
    }
  }
} else {
  if let fromControllerHome = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? HomeTableViewController,
    let toControllerList = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? PlansListViewController,
    let container = transitionContext.containerView()
  {
    let duration = transitionDuration(transitionContext)

    let imageSnopshot = fromControllerHome.travelImage.snapshotViewAfterScreenUpdates(false)

    if let index = fromControllerHome.index {

    if let cell = toControllerList.collectionView(toControllerList.collectionView!, cellForItemAtIndexPath: index) as? PlanInListCollectionViewCell {

      cell.image.hidden = true

      toControllerList.view.frame = transitionContext.finalFrameForViewController(toControllerList)
      print("BACK toControllerList.view.frame \(toControllerList.view.frame)")

      imageSnopshot.frame = fromControllerHome.travelImage.frame
      print("BACK imageSnopshot.frame \(imageSnopshot.frame)")

      container.insertSubview(toControllerList.view, belowSubview: fromControllerHome.view)
      container.addSubview(imageSnopshot)

      UIView.animateWithDuration(duration, animations:  {
        fromControllerHome.view.alpha = 0.0
        print(index.row)
        imageSnopshot.frame = container.convertRect(cell.image.frame, fromView: cell.image.superview)
        print("BACK imageSnopshot.frame \(imageSnopshot.frame)")
        print("BACK container.convertRect cell.image.frame \(cell.image.frame) fromView: cell.image.superview \(cell.image.superview)")
        }, completion: { finished in
          imageSnopshot.removeFromSuperview()
          fromControllerHome.travelImage.hidden = false
          cell.image.hidden = false

          transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
      })
      }
    }
  }
}
 }

func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.5
}

}

这是控制台的结果。我在同一个地方的同一个collectionView单元上进行了几次点击,每次控制台结果都相同时效果不好:

好工作

presenting cellImageViewSnapShot cell.image.frame (0.0, 0.0, 250.0, 400.0) cell.image.superview  Optional(<_UISnapshotWindow: 0x7fe910771000; frame = (1125 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fe91076e290>; layer = <UIWindowLayer: 0x7fe910761530>>)
**presenting cellImageViewSnapShot.frame (1125.0, 0.0, 250.0, 400.0)**
presenting toControllerHome.view.frame (0.0, 0.0, 375.0, 667.0)
presenting frame  (0.0, 0.0, 600.0, 470.0)
presenting = container.convertRect toControllerHome.travelImage.frame (0.0, 0.0, 600.0, 470.0) toControllerHome.view  <UITableView: 0x7fe91203a600; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; tintColor = UIDeviceRGBColorSpace 1 1 1 1; gestureRecognizers = <NSArray: 0x7fe9106ae3c0>; animations = { opacity=<CABasicAnimation: 0x7fe912861510>; }; layer = <CALayer: 0x7fe9105ea920>; contentOffset: {0, 0}; contentSize: {375, 13093}>
presenting cellImageViewSnapShot.frame (0.0, 0.0, 600.0, 470.0)
BACK toControllerList.view.frame (0.0, 0.0, 375.0, 667.0)
BACK imageSnopshot.frame (0.0, 0.0, 375.0, 470.0)
**BACK imageSnopshot.frame (61.0, 144.0, 250.0, 400.0)**
BACK container.convertRect cell.image.frame (0.0, 0.0, 250.0, 400.0) fromView: cell.image.superview Optional(<UIView: 0x7fe9104b9920; frame = (0 0; 250 400); gestureRecognizers = <NSArray: 0x7fe910608300>; layer = <CALayer: 0x7fe9104b7d90>>)

糟糕的工作

presenting cellImageViewSnapShot cell.image.frame (0.0, 0.0, 250.0, 400.0) cell.image.superview  Optional(<_UISnapshotWindow: 0x7fe9107ab970; frame = (1125 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fe912932150>; layer = <UIWindowLayer: 0x7fe910784a90>>)
**presenting cellImageViewSnapShot.frame (1125.0, 0.0, 250.0, 400.0)**
presenting toControllerHome.view.frame (0.0, 0.0, 375.0, 667.0)
presenting frame  (0.0, 0.0, 600.0, 470.0)
presenting = container.convertRect toControllerHome.travelImage.frame (0.0, 0.0, 600.0, 470.0) toControllerHome.view  <UITableView: 0x7fe9108bf400; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; tintColor = UIDeviceRGBColorSpace 1 1 1 1; gestureRecognizers = <NSArray: 0x7fe912892220>; animations = { opacity=<CABasicAnimation: 0x7fe9107adff0>; }; layer = <CALayer: 0x7fe912827d90>; contentOffset: {0, 0}; contentSize: {375, 13093}>
presenting cellImageViewSnapShot.frame (0.0, 0.0, 600.0, 470.0)
BACK toControllerList.view.frame (0.0, 0.0, 375.0, 667.0)
BACK imageSnopshot.frame (0.0, 0.0, 375.0, 470.0)
**BACK imageSnopshot.frame (65.0, 34.0, 250.0, 400.0)**
BACK container.convertRect cell.image.frame (0.0, 0.0, 250.0, 400.0) fromView: cell.image.superview Optional(<UIView: 0x7fe912958590; frame = (0 0; 250 400); gestureRecognizers = <NSArray: 0x7fe910797f90>; layer = <CALayer: 0x7fe9129322a0>>)

正如我们所看到的,**标记的线条是偏离右边框架的线条。

你有什么理由以这种方式行事吗?

1 个答案:

答案 0 :(得分:0)

在更改Alpha值后尝试调用[view layoutifneeded](这将是您正在更改其Alpha值的视图)。

希望这对你有所帮助!如果没有,请告诉我,我已经完成了这种过渡。

这是我的转换代码段

UIViewController<DataSource> *fromVC = (UIViewController<DataSource> *) [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController<DataSource> *toVC   = (UIViewController<DataSource> *) [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

UIView *containerView = [transitionContext containerView];

UIView *fromView = [fromVC sharedView];
UIView *toView = [toVC sharedView];

// Take Snapshot of fomView=
UIView *snapshotView = [fromView snapshotViewAfterScreenUpdates:NO];
snapshotView.frame = [containerView convertRect:fromView.frame fromView:fromView.superview];
fromView.hidden = YES;

// Setup the initial view states
toVC.view.frame = [transitionContext finalFrameForViewController:toVC];

if (self.presenting) {
    toVC.view.alpha = 0;
    [toVC.view layoutIfNeeded];
    toVC.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
    [containerView addSubview:toVC.view];
}else{
    [containerView insertSubview:toVC.view belowSubview:fromVC.view];
}
toView.hidden = YES;
[containerView addSubview:snapshotView];


[UIView animateWithDuration:0.3f animations:^{

    if(self.presenting){
        toVC.view.alpha = 1.0; // Fade in
    }else{
        fromVC.view.alpha = 0.0; // Fade out
    }
    // Move the SnapshotView
    snapshotView.frame = [containerView convertRect:toView.frame fromView:toView.superview];
    toVC.view.center = fromVC.view.center;
    [toVC.view layoutIfNeeded];

} completion:^(BOOL finished) {

    // Clean up
    toView.hidden = NO;
    fromView.hidden = NO;
    [snapshotView removeFromSuperview];

    // Declare that we've finished
    [transitionContext completeTransition:!transitionContext.transitionWasCancelled];

}];

希望这能帮到你!