由于每次图片碎片化动画执行完成之后,都需要再次执行相同的碎片动画代码。而动画结束是通过block执行,即我们需要在block中嵌套使用同一个block,因此首先我们需要把这段执行代码声明成一个block变量。另外,需要一个声明一个idx在每次碎片动画完成的时候更新图片,用__block修饰来让我们在回调中修改这个值:
- (void)fadeBanner
NSParameterAssert(self.superview);
UIImageView * tempBanner = [self associateTempBannerWithImage: [UIImage imageNamed: self.bannerImages[1]]];
self.stop = NO;
__block NSInteger idx = 0;
__weak typeof(self) weakSelf = self;
[self associatePageControlWithCurrentIdx: idx];
void (^complete)() = ^{
NSInteger updateIndex = [weakSelf updateImageWithCurrentIndex: ++idx tempBanner: tempBanner];
idx = updateIndex;
[weakSelf associatePageControlWithCurrentIdx: idx];
};
// 保存block并执行动画
objc_setAssociatedObject(self, kCompleteBlockKey, complete, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self animateFadeWithComplete: ^{
if (!self.stop) {
complete();
}
}];
}
// 更新展示的图片,并且返回下一次要展示的图片下标
- (NSInteger)updateImageWithCurrentIndex: (NSInteger)idx tempBanner: (UIImageView *)tempBanner
{
if (idx >= self.bannerImages.count) { idx = 0; }
self.image = [UIImage imageNamed: self.bannerImages[idx]];
[self reverseWithoutAnimate];
NSInteger nextIdx = idx + 1;
if (nextIdx >= self.bannerImages.count) { nextIdx = 0; }
tempBanner.image = [UIImage imageNamed: self.bannerImages[nextIdx]];
[self animateFadeWithComplete: ^{
if (!self.stop) {
void (^complete)() = objc_getAssociatedObject(self, kCompleteBlockKey);
complete();
}
}];
return idx;
}
代码中需要注意的是,我在上面使用objc_Associate的机制保存了这个完成回调的block,这个是必要的。假设你不喜欢把更新图片的代码封装出来,直接把这一步骤放到上面的complete声明中,依旧还是要动态保存起来,否则这个block执行到第三次图片碎片的时候就会被释放从而导致崩溃
别忘了在每次图片切换完成之后,将所有的子视图遮罩还原,并且更新图片显示
- (void)reverseWithoutAnimate
{
if (self.isFading) {
NSLog(@"It's animating!");
return;
}
for (UIView * subview in self.maskView.subviews) {
subview.alpha = 1;
}
}
总结
以上就是关于IOS实现碎片化动画的全部内容,希望本文的内容对大家开发IOS动画的时候能有所帮助。
注:相关教程知识阅读请移步到IOS开发频道。










