IOS实现碎片化动画详解

2020-01-15 17:30:45于海丽

由于每次图片碎片化动画执行完成之后,都需要再次执行相同的碎片动画代码。而动画结束是通过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开发频道。