Ole*_*ann 19 animation uiviewanimation ios uicollectionview
我想UICollectionView
将与动画单元格插入一起运行的动画中的a的帧大小更改为performBatchUpdates:completion:
块内的同一集合视图.
这是触发单元格插入的代码:
[collectionView performBatchUpdates:^{
indexPathOfAddedCell = ...;
[collectionView insertItemsAtIndexPaths:@[ indexPathOfAddedCell ]];
} completion:nil];
Run Code Online (Sandbox Code Playgroud)
因为单元格插入导致集合视图contentSize
发生变化,所以我尝试KVO注册对该属性的更改,然后从KVO处理程序触发集合视图框架更新.
这种方法的问题在于KVO触发器contentSize
触发太晚了:当时单元插入动画已经完成(实际上,KVO在performBatchUpdates:completion:
被调用的完成处理程序之前触发,但是在动画在UI中播放之后).
我没有使用自动布局.
编辑:我放了一个示例项目来演示我在GitHub上的问题.
编辑2:我应该提到我需要这个我正在写的一个组件(OLEContainerScrollView
)应该100%独立于集合视图.因此,我不能对集合视图布局进行子类化,也不会影响触发单元格动画的代码.理想情况下,解决方案也适用UITableView
,它表现出相同的行为.
Leo*_*ica 10
我查看了集合视图和表视图如何更新其内容插入,实际上,滚动视图的内容大小仅在动画完成后才更新.如果不使用私有API,似乎没有一种非常好的方法来监听未来的内容大小,但它是可能的.
对于表视图,动画启动的触发器是-[UITableView _endCellAnimationsWithContext:]
.此方法设置所需的所有动画(仅用于将来的可见单元格),执行它们并设置最终调用的完成块-[UITableView _updateContentSize]
._updateContentSize
使用内部-[UITableView _contentSize]
方法设置正确的滚动视图内容大小.由于_endCellAnimationsWithContext:
仅处理动画,因此表视图后面的数据已经更新,因此调用_contentSize
(或使用valueForKey:@"_contentSize"
)会返回正确的大小.
它与集合视图非常相似.触发器是-[UICollectionView _endItemAnimations]
,它为每个单元格,页眉和页脚启动许多动画,并且当所有动画完成时,-[UICollectionView _updateAnimationDidStop:finished:context:]
设置正确的内容大小.由于这是一个集合视图,因此其集合视图布局实际上知道目标内容大小,因此您可以调用-[UICollectionViewLayout collectionViewContentSize]
以获取更新的内容大小.
这些都不是在app商店中使用的好选择.我可以想到的一个选项是添加每个滚动视图子类的ISA调度,并包装所有可动画的入口点,跟踪它们是否被批处理,并且在批处理结束时或在独立动画操作结束时,使用获取目标内容大小的相应方法(-[UITableView _contentSize]
和-[UICollectionViewLayout collectionViewContentSize]
).
原始答案,以防您想要了解自己的集合视图中集合视图大小的更改:
对集合视图布局进行子类化(如果尚未使用),并使用通知中心或委托方法,请通知on prepareForAnimatedBoundsChange:
其他动画.它们将被添加到动画块中.
从文档:
您还可以使用此方法执行其他动画.您创建的任何动画都会添加到用于处理插入,删除和边界更改的动画块中.
您可能需要确定更改的内容,并仅通知插入动画.
我查看了你的演示项目,我认为不需要KVO.如果你想在插入新单元格时用动画更改集合视图的框架,那么我认为你可以这样做:
#import "ViewController.h"
@interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
@property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
@property (weak, nonatomic) IBOutlet UIView *otherView;
@property (nonatomic) NSInteger numberOfItemsInCollectionView;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.numberOfItemsInCollectionView = 1; // This is our model
}
- (IBAction)addItem:(id)sender
{
// Change the model
self.numberOfItemsInCollectionView += 1;
[UIView animateWithDuration:0.24 animations:^{
NSIndexPath *indexPathOfInsertedCell = [NSIndexPath indexPathForItem:self.numberOfItemsInCollectionView - 1 inSection:0];
[self.collectionView insertItemsAtIndexPaths:@[ indexPathOfInsertedCell ]];
CGRect collectionViewFrame = self.collectionView.frame;
collectionViewFrame.size.height = (self.numberOfItemsInCollectionView * 40) + 94;
self.collectionView.frame = collectionViewFrame;
}];
}
#pragma mark - UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.numberOfItemsInCollectionView;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell" forIndexPath:indexPath];
return cell;
}
@end
Run Code Online (Sandbox Code Playgroud)
或者如果你想要淡化效果:
- (IBAction)addItem:(id)sender
{
// Change the model
self.numberOfItemsInCollectionView += 1;
CATransition *transition = [CATransition animation];
transition.type = kCATransitionFade;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.fillMode = kCAFillModeForwards;
transition.duration = 0.5;
[[self.collectionView layer] addAnimation:transition forKey:@"UICollectionViewInsertRowAnimationKey"];
NSIndexPath *indexPathOfInsertedCell = [NSIndexPath indexPathForItem:self.numberOfItemsInCollectionView - 1 inSection:0];
[self.collectionView insertItemsAtIndexPaths:@[ indexPathOfInsertedCell ]];
CGRect collectionViewFrame = self.collectionView.frame;
collectionViewFrame.size.height = (self.numberOfItemsInCollectionView * 40) + 94;
self.collectionView.frame = collectionViewFrame;
}
Run Code Online (Sandbox Code Playgroud)
我已经用你的演示项目检查了这个,它对我有用.请尝试这个并评论它是否也适合你.
归档时间: |
|
查看次数: |
4132 次 |
最近记录: |