你如何设置UICollectionView动画时间?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你如何设置UICollectionView动画时间?相关的知识,希望对你有一定的参考价值。
我有一个自定义流布局时被插入并与以下两个功能从的CollectionView删除他们这是调整细胞的属性,但我无法弄清楚你将如何调整默认的动画时间。
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
// Assign the new layout attributes
attributes.transform3D = CATransform3DMakeScale(0.5, 0.5, 0.5);
attributes.alpha = 0;
return attributes;
}
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
// Assign the new layout attributes
attributes.transform3D = CATransform3DMakeScale(0.5, 0.5, 0.5);
attributes.alpha = 0;
return attributes;
}
为了不那是你可以继承UICollectionViewLayoutAttributes与新的物业answer by gavrix,比用合适的时间创建自定义转换,并将其分配给CABasicAnimation *transformAnimation
属性initialLayoutAttributesForAppearingItemAtIndexPath
提出破解解决问题,那么在UICollectionViewCell根据需要应用的属性:
@interface AnimationCollectionViewLayoutAttributes : UICollectionViewLayoutAttributes
@property (nonatomic, strong) CABasicAnimation *transformAnimation;
@end
@implementation AnimationCollectionViewLayoutAttributes
- (id)copyWithZone:(NSZone *)zone
{
AnimationCollectionViewLayoutAttributes *attributes = [super copyWithZone:zone];
attributes.transformAnimation = _transformAnimation;
return attributes;
}
- (BOOL)isEqual:(id)other {
if (other == self) {
return YES;
}
if (!other || ![[other class] isEqual:[self class]]) {
return NO;
}
if ([(( AnimationCollectionViewLayoutAttributes *) other) transformAnimation] != [self transformAnimation]) {
return NO;
}
return YES;
}
@end
在布局类
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
AnimationCollectionViewLayoutAttributes* attributes = (AnimationCollectionViewLayoutAttributes* )[super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
transformAnimation.duration = 1.0f;
CGFloat height = [self collectionViewContentSize].height;
transformAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, 2*height, height)];
transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, attributes.bounds.origin.y, 0)];
transformAnimation.removedOnCompletion = NO;
transformAnimation.fillMode = kCAFillModeForwards;
attributes.transformAnimation = transformAnimation;
return attributes;
}
+ (Class)layoutAttributesClass {
return [AnimationCollectionViewLayoutAttributes class];
}
然后在UICollectionViewCell应用属性
- (void) applyLayoutAttributes:(AnimationCollectionViewLayoutAttributes *)layoutAttributes
{
[[self layer] addAnimation:layoutAttributes.transformAnimation forKey:@"transform"];
}
改变的CALayer的速度
@implementation Cell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.layer.speed =0.2;//default speed is 1
}
return self;
}
对@罗塔瓦的回答大厦,您可以暂时使用集合视图的批量更新设置动画速度:
[self.collectionView performBatchUpdates:^{
[self.collectionView.viewForBaselineLayout.layer setSpeed:0.2];
[self.collectionView insertItemsAtIndexPaths: insertedIndexPaths];
} completion:^(BOOL finished) {
[self.collectionView.viewForBaselineLayout.layer setSpeed:1];
}];
UICollectionView
启动所有动画内部使用一些硬编码值。但是,你总是可以覆盖该值,直到动画承诺。在一般情况下,过程是这样的:
- 开始动画
- 获取所有布局属性
- 将属性应用于意见(UICollectionViewCell的)
- 提交动画
应用属性是每个UICollectionViewCell下完成的,你可以在适当的方法来覆盖animationDuration。问题是,UICollectionViewCell具有公共方法applyLayoutAttributes:
但它的默认的实现是空的!基本上,UICollectionViewCell有其它的私有方法称为_setLayoutAttributes:
这种私有方法被称为UICollectionView这种私有方法在结束通话applyLayoutAttributes:
。默认布局属性,像帧,位置与当前的animationDuration
施加变换applyLayoutAttributes:
被调用之前。这就是说,你在私有方法animationDuration
覆盖_setLayoutAttributes:
- (void) _setLayoutAttributes:(PSTCollectionViewLayoutAttributes *)layoutAttributes
{
[UIView setAnimationDuration:3.0];
[super _setLayoutAttributes:layoutAttributes];
}
这显然不是的AppleStore安全。您可以使用这些运行黑客的一个安全地覆盖这个私有方法。
在没有成功布局过程的每一个可能的相位试图[CATransaction setAnimationDuration:]
和[UIView setAnimationDuration:]
后,我想出了一个有点哈克的方式来改变由不依赖于私有API的UICollectionView
创建细胞动画的持续时间。
您可以使用CALayer
的speed
属性来改变给定层上进行动画的相对的媒体时间。对于这个与UICollectionView
工作,你可以layer.speed
改变细胞的层上的东西小于1。显然,这不是伟大的,有细胞的层始终有一个非统一动画的速度,所以其中一个方案是派遣细胞动画制作时NSNotification
,你的细胞的认同,这将改变层的速度,然后再改回来在适当的时间之后,动画完成。
我不推荐使用这种方法作为一个长期的解决方案,这是很迂回,但它确实工作。希望苹果将暴露在未来UICollectionView动画更多的选择。
您可以设置图层的速度属性(如在Rotoava's Answer)改变控制动画的速度。问题是你正在使用任意值,因为你不知道插入动画的实际工期。
使用this post你可以找出默认的动画时间是什么。
newAnimationDuration = (1/layer.speed)*originalAnimationDuration
layer.speed = originalAnimationDuration/newAnimationDuration
如果你想使动画400ms的长,你的布局你会:
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes* attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:indexPath];
//set attributes here
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
CGFloat originalAnimationDuration = [CATransaction animationDuration];
CGFloat newAnimationDuration = 0.4f;
cell.layer.speed = originalAnimationDuration/newAnimationDuration;
return attributes;
}
在我来说,我有可能被拖出屏幕细胞,我想改变删除动画的基础上,泛手势的速度持续时间。
在手势识别(这应该是您的收藏视图的一部分):
- (void)handlePanGesture:(UIPanGestureRecognizer *)sender
{
CGPoint dragVelocityVector = [sender velocityInView:self.collectionView];
CGFloat dragVelocity = sqrt(dragVelocityVector.x*dragVelocityVector.x + dragVelocityVector.y*dragVelocityVector.y);
switch (sender.state) {
...
case UIGestureRecognizerStateChanged:{
CustomLayoutClass *layout = (CustomLayoutClass *)self.collectionViewLayout;
layout.dragSpeed = fabs(dragVelocity);
...
}
...
}
然后在您的customLayout:
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes* attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:indexPath];
CGFloat animationDistance = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
CGFloat originalAnimationDuration = [CATransaction animationDuration];
CGFloat newAnimationDuration = animationDistance/self.dragSpeed;
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
cell.layer.speed = originalAnimationDuration/newAnimationDuration;
return attributes;
}
没有子分类:
[UIView animateWithDuration:2.0 animations:^{
[self.collection reloadSections:indexSet];
}];
因为forBaselineLayout到@AshleyMills更新已过时
这工作
self.collectionView.performBatchUpdates({ () -> Void in
let indexSet = IndexSet(0...(numberOfSections - 1))
self.collectionView.insertSections(indexSet)
self.collectionView.forFirstBaselineLayout.layer.speed = 0.5
}, completion: { (finished) -> Void in
self.collectionView.forFirstBaselineLayout.layer.speed = 1.0
})
你可以改变UICollectionView layout.speed财产,应改变布局的动画时长...
以上是关于你如何设置UICollectionView动画时间?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用持续时间为单个 UICollectionView 单元格设置动画
使用 UIDynamics Swift 为 UICollectionView 设置动画
如何更改自定义 UICollectionView 布局引擎中的默认布局动画曲线?