点击时如何在 UICollectionViewCell 中制作此动画?

Posted

技术标签:

【中文标题】点击时如何在 UICollectionViewCell 中制作此动画?【英文标题】:How I could make this animation in a UICollectionViewCell when tapped? 【发布时间】:2016-03-29 11:28:14 【问题描述】:

我正在尝试制作一个类似的动画,当您选择一个时,它会制作这些 UICollectionViewCell。我的意思是他们做的好像他们起床一样,但不知道如何得到它。我显然应该在方法中完成:

CollectionView ( CollectionView : UICollectionView , didSelectItemAtIndexPath indexPath : NSIndexPath ) 

我留下了一段 YouTube 视频,它显示了我所说的话 https://www.youtube.com/watch?v=gFWiyOERVBg

谢谢

【问题讨论】:

看到这个对你有帮助的时候***.com/questions/13657883/… 【参考方案1】:

didSelectItemAtIndexPath 可以用作触发器,但在此无关紧要。

如果我要尝试重现这一点,我会采取以下方法:

首先,集合视图中的所有单元格都受到影响,检索一组可见项并对每个单元格应用变换。

变换看起来好像分两个阶段进行,首先是 y 轴旋转变换,其值应用于 .m34 处的变换矩阵以改变视角。其次,具有足够大的负 x 值以将单元格移出屏幕的平移变换。将这些变换放在一个基本动画组中,我怀疑你会非常接近所需的效果。

最后的观察是,这似乎是一个过渡,因此您可以将其作为 UIViewControllerAnimation 的一部分来实现。

编辑

今天早上我有一些时间,所以我为你整理了一些代码。

仔细查看动画后,我注意到向左移动实际上是旋转动画的一部分,x 轴上的锚点设置为 0。因此,我们需要的只是一个旋转和淡入淡出的动画——所有这些都以 x = 0 为中心。

要做到这一点,最简单的方法是为集合列表中的每个单元添加一个 CALayer,并在单元“嫁接”到新层后为添加的层设置动画。

  - (void)processVisibleItems
      NSArray *visibleItems = [self.collectionView indexPathsForVisibleItems];

      for (NSIndexPath *p in visibleItems) 
         // create a layer which will contain the cell for each of the visibleItems
         CALayer *containerLayer = [CALayer layer];
         containerLayer.frame = self.collectionView.layer.bounds;
         containerLayer.backgroundColor = [UIColor clearColor].CGColor;

         // we need to change the anchor point which will offset the layer - adjust accordingly 
         CGRect containerFrame = containerLayer.frame;
         containerFrame.origin.x  -= containerLayer.frame.size.width/2;
         containerLayer.frame = containerFrame;
         containerLayer.anchorPoint = CGPointMake(0.0f, 0.5f);
         [self.collectionView.layer addSublayer:containerLayer];

         //add the cell to the new layer - change MyCollectionViewCell to your cell's class
          MyCollectionViewCell *cell = (MyCollectionViewCell*)[self.collectionView cellForItemAtIndexPath:p];
          cell.frame = [containerLayer convertRect:cell.frame fromLayer:cell.superview.layer];
          [containerLayer addSublayer:cell.layer];
          //add the animation to the layer
          [self addAnimationForLayer:containerLayer];
      
  

  - (void)addAnimationForLayer:(CALayer*)layerToAnimate
      // fade-out animation
      CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
      [fadeOutAnimation setToValue:@0.0];

      //rotation Animation
      CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
      CATransform3D tfm = CATransform3DMakeRotation((65.0f * M_PI) / 180.0f, 0.0f, -1.0f, 0.0f);
      //add perspective - change to your liking
      tfm.m14 = -0.002f;
      rotationAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
      rotationAnimation.toValue = [NSValue valueWithCATransform3D:tfm];

      //group the animations and add to the new layer
      CAAnimationGroup *group = [CAAnimationGroup animation];
      group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
      group.fillMode =  kCAFillModeForwards;
      group.removedOnCompletion = NO;
      group.duration = 0.35f;
      [group setAnimations:@[rotationAnimation, fadeOutAnimation]]; 

      [layerToAnimate addAnimation:group forKey:@"rotateAndFadeAnimation"];
  
  //To trigger on cell click simply call [self processVisibleItems] in didSelectItemAtIndexPath

注意-

您需要进行一些更改才能使其看起来与视频中的动画完全相同:

    随机化包含可见项目列表的数组。就目前而言,这些项目将按顺序触发或根据可见项目数组触发。 随机化组动画的持续时间,或者至少在动画之间引入一个小的延迟(将持续时间随机化在 0.35(Apple 的默认时间)之间,假设 0.6 应该可以正常工作)。 可能随机化旋转动画的角度 - 介于 50 到 85 度之间的任何值都可以(在上面的示例中当前设置为 65);

这就是它的全部......享受!

【讨论】:

是的,我认为这是关键。我会试试的,虽然我是动画菜鸟不知道能不能搞定。谢谢 感谢您提供如此详细的解释。我设法使用swift实现了它。过渡效果与视频中的完全一样。【参考方案2】:

您可以使用didSelectItemAtIndexPath 中的这一行来获取 UICollectionViewCell,

let cell = collectionView.cellForItemAtIndexPath(indexPath)

使用单元格引用,您可以使用animateWithDuration 或任何其他方法为单元格内的对象设置动画。

【讨论】:

是的,我知道,我的具体问题是如何制作视频的动画,我知道的任何动画都可以。感谢您的回答 嗯,我不确定它到底使用了动画,但是看看这个教程,它对这个主题有很多见解,objc.io/issues/12-animations/collectionview-animations【参考方案3】:

如果 MDB983 可以为某人服务,我会翻译它以快速响应

func processVisibleItems()
    let visibleItems = self.collectionView?.indexPathsForVisibleItems()
    for p in visibleItems! as [NSIndexPath]
        // create a layer which will contain the cell for each of the visibleItems
        let containerLayer = CALayer()
        containerLayer.frame = (self.collectionView?.layer.bounds)!
        containerLayer.backgroundColor = UIColor.clearColor().CGColor

        // we need to change the anchor point which will offset the layer - adjust accordingly
        var containerFrame:CGRect! = containerLayer.frame
        containerFrame.origin.x -= containerLayer.frame.size.width/2
        containerLayer.frame = containerFrame
        containerLayer.anchorPoint = CGPointMake(0.0, 0.5)
        self.collectionView?.layer.addSublayer(containerLayer)

        //add the cell to the new layer 
        let cell = self.collectionView?.cellForItemAtIndexPath(p) as! NewspaperImageCollectionViewCell
        cell.frame = containerLayer .convertRect(cell.frame, fromLayer: cell.superview!.layer)
        containerLayer.addSublayer(cell.layer)
        addAnimationForLayer(containerLayer)
     


func addAnimationForLayer(layerToAnimate: CALayer)
    // fade-out animation
    let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
    fadeOutAnimation.toValue = 0.0

    //rotation Animation
    let rotationAnimation = CABasicAnimation(keyPath: "transform")
    var tfm = CATransform3D()
    tfm = CATransform3DMakeRotation((65.0 * CGFloat(M_PI) )/180.0, 0.0, -1.0, 0.0)
    tfm.m14 = -0.002
    rotationAnimation.fromValue = NSValue(CATransform3D:CATransform3DIdentity)
    rotationAnimation.toValue = NSValue(CATransform3D:tfm)

    //group the animations and add to the new layer
    let group = CAAnimationGroup()
    group.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    group.fillMode = kCAFillModeForwards
    group.removedOnCompletion = false
    group.duration = 0.35
    group.animations = [rotationAnimation,fadeOutAnimation]
    layerToAnimate.addAnimation(group, forKey: "rotateAndFadeAnimation")
 

【讨论】:

以上是关于点击时如何在 UICollectionViewCell 中制作此动画?的主要内容,如果未能解决你的问题,请参考以下文章

当用户点击地图上的(商业)地点时如何获取点击事件

配置 UICollectionView 以保持相同的单元格视图

带有 UIScrollView 的 UICollectionViewCell 取消了 didSelectItemAtIndexPath

如何在点击外部关闭 QDialog 并在点击子小部件时关闭?

如何触发集合视图的 didSelectItemAtIndexPath: 在滚动时点击?

Swift - 同时设置cornerRadius和阴影