点击时如何在 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 并在点击子小部件时关闭?