自定义视图过渡(如新的App Store)

现在,我已经完成了故事板的设置,我创建了一个名为PokemonCell的新文件,并将其设置如下:

 导入UIKit 
 类PokemonCell:UICollectionViewCell { 
  @IBOutlet弱var pokemonNameLabel:UILabel! 
  @IBOutlet弱var pokemonImage:UIImageView! 
  func updateWithImage(image:UIImage?){ 
 如果让imageToDisplay = image { 
  pokemonImage.image = imageToDisplay 
  }其他{ 
  pokemonImage.image =无 
  } 
  } 
 覆盖func awakeFromNib(){ 
  super.awakeFromNib() 
  updateWithImage(image:nil) 
  } 
 覆盖func prepareForReuse(){ 
  super.prepareForReuse() 
  updateWithImage(image:nil) 
  } 
  } 

连接您的插座,并将收集单元设置为PokemonCell。 在ViewController.swift文件中,设置数据源和集合视图的委托:

  collectionView.dataSource =自我 
  collectionView.delegate =自我 

并设置您的DataSource和Delegate方法:

扩展ViewController:UICollectionViewDataSource { 
  func numberOfSections(在collectionView:UICollectionView中)-> Int { 
 返回1 
  } 
  func collectionView(_ collectionView:UICollectionView,numberOfItemsInSection部分:Int)-> Int { 
 返回myPokemon.count 
  } 
  func collectionView(_ collectionView:UICollectionView,cellForItemAt indexPath:IndexPath)-> UICollectionViewCell { 
 让pokemonCell = collectionView.dequeueReusableCell(withReuseIdentifier:“ pokemonCell”,for:indexPath)为! 宠物小精灵细胞 
  pokemonCell.pokemonNameLabel.text = myPokemon [indexPath.row] .pokemonName 
  pokemonCell.updateWithImage(图像:UIImage(名称:myPokemon [indexPath.row] .pokemonImage)) 
 返回pokemonCell 
  } 
  } 
 扩展ViewController:UICollectionViewDelegate { 
  } 

现在已完成所有设置,在Main.storyboard设置中创建一个新的ViewController,其中包含一些值以捕获您的神奇宝贝数据,我的最终结果如下所示:

创建一个新的DetailViewController以使用您的集合视图信息:

 导入UIKit 
 类DetailViewController:UIViewController { 
  @IBOutlet弱var pokemonDetailLabel:UILabel! 
  @IBOutlet弱var pokemonNameLabel:UILabel! 
  @IBOutlet弱var pokemonImageView:UIImageView! 
  var pokemonName:字符串=“” 
  var pokemonDetails:String =“” 
  var pokemonImageName:String =“” 
 覆盖func viewDidLoad(){ 
  super.viewDidLoad() 
  view.addGestureRecognizer(UITapGestureRecognizer(target:self,action:#selector(actionClose(_ :)))) 
  pokemonNameLabel.text = pokemonName 
  pokemonDetailLabel.text =宠物小精灵详细信息 
  pokemonImageView.image = UIImage(名称:pokemonImageName) 
  } 
  @objc func actionClose(_ tap:UITapGestureRecognizer){ 
  presentingViewController?.dismiss(动画:true,完成:nil) 
  } 
  } 

好的,现在我们可以开始实际开始本博客文章的主题! 好吧,我会说实话,在这一点上我已经完全迷路了。 我已经准备好了所有这些好的设置,但是不知道如何弄清楚从哪里开始。 幸运的是,我知道它与转换视图有关,因此我在Google上进行了快速搜索,并发现了该帖子https://www.raywenderlich.com/146692/ios-animation-tutorial-custom-view-controller-presentation-transitions- 2

按照它的指导,我创建了TransitionAnimator.swift文件:

 导入UIKit 
 类TransitionAnimator:NSObject,UIViewControllerAnimatedTransitioning { 
 令durationExpanding = 0.75 
 让durationClosing = 0.5 
  var presenting = true 
  var originFrame = CGRect.zero 
  var dismissCompletion:(()-> Void)? 
  func transitionDuration(使用transitionContext:UIViewControllerContextTransitioning?)-> TimeInterval { 
 如果出示{ 
 返回持续时间 
  } 
 返回持续时间 
  } 
  func animateTransition(使用transitionContext:UIViewControllerContextTransitioning){ 
 让containerView = transitionContext.containerView 
 守护让toView = transitionContext.view(forKey:.to),让detailView =呈现?  toView:transitionContext.view(forKey:.from)else { 
 返回 
  } 
 让initialFrame =呈现吗?  originFrame:detailView.frame 
 让finalFrame =呈现吗?  detailView.frame:originFrame 
 让xScaleFactor =呈现?  initialFrame.width / finalFrame.width:finalFrame.width / initialFrame.width 
 让yScaleFactor =呈现?  initialFrame.height / finalFrame.height:finalFrame.height / initialFrame.height 
 让scaleTransform = CGAffineTransform(scaleX:xScaleFactor, 
  y:yScaleFactor) 
 如果出示{ 
  detailView.transform = scaleTransform 
  detailView.center = CGPoint(x:initialFrame.midX,y:initialFrame.midY) 
  detailView.clipsToBounds = true 
  } 
  containerView.addSubview(toView) 
  containerView.bringSubview(toFront:detailView) 
 如果出示{ 
  //更新开始动画 
  UIView.animate(withDuration:durationExpanding,delay:0.0, 
  usingSpringWithDamping:1.0,initialSpringVelocity:0.0,//给它一些反弹,使过渡看起来比没有默认值时更整洁 
 动画:{ 
  detailView.transform = CGAffineTransform.identity 
  detailView.center = CGPoint(x:finalFrame.midX,y:finalFrame.midY) 
  }, 
 完成时间:{_ 
  transitionContext.completeTransition(true) 
  } 
  }其他{ 
  //更新结束动画 
  UIView.animate(withDuration:durationClosing,delay:0.0,options:.curveLinear, 
 动画:{ 
  detailView.transform = scaleTransform 
  detailView.center = CGPoint(x:finalFrame.midX,y:finalFrame.midY) 
  }, 
 完成时间:{_ 
 如果!self.presenting { 
  self.dismissCompletion?() 
  } 
  transitionContext.completeTransition(true) 
  } 
  } 
  } 
  } 

您可以根据需要随意修改和更改上述动画,但是出于我的目的,我使用了一些基本动画。 然后在您的ViewController中,设置CollectionViewDelegate和UIViewControllerTransitioningDelegate,如下所示:

 扩展ViewController:UICollectionViewDelegate { 
  func collectionView(_ collectionView:UICollectionView,didSelectItemAt indexPath:IndexPath){ 
  selectedCell = collectionView.cellForItem(at:indexPath)as! 宠物小精灵细胞 
 让pokemonDetailViewController = storyboard!.instantiateViewController(withIdentifier:“ DetailViewController”)为!  DetailViewController 
  pokemonDetailViewController.pokemonName = myPokemon [indexPath.row] .pokemonName 
  pokemonDetailViewController.pokemonImageName = myPokemon [indexPath.row] .pokemonImage 
  pokemonDetailViewController.pokemonDetails = myPokemon [indexPath.row] .pokemonDetails 
  pokemonDetailViewController.transitioningDelegate =自我 
  present(pokemonDetailViewController,动画:true,完成:无) 
  } 
  } 
 扩展ViewController:UIViewControllerTransitioningDelegate { 
  func animationController(forPresented提出:UIViewController,提出:UIViewController,来源:UIViewController)-> UIViewControllerAnimatedTransitioning?  { 
 后卫让originFrame = selectedCell.superview?.convert(selectedCell.frame,改为:nil)否则{ 
 返回过渡 
  } 
  transition.originFrame = originFrame 
  transition.presenting = true 
  selectedCell.isHidden = true 
 返回过渡 
  } 
  func animationController(forDismissed被解雇:UIViewController)-> UIViewControllerAnimatedTransitioning?  { 
  transition.presenting =假 
 返回过渡 
  } 
  } 

结果应如下所示:

回购到该项目:

https://github.com/EricADockery/ViewTransitionMediumPost

Interesting Posts