IT学习网 - 爱学习 - 最具影响力综合资讯网站 -- 中国IT界的领航者!
热门关键字:      88888  as  xxx
站外
广告
站外
广告

IOS实现碎片化动画详解

发布时间:2016-08-24 17:09文章来源:网络整理文章作者: 学习网点击次数:
在网上看到一个惊艳的碎片化动画,于是实现之后拿来讲解一下,有需要的小伙伴们可以参考学习哦。

碎片化效果图

遮罩视图

在UIView中有一个maskView属性,这个属性是我们今天实现动画的最重要的变量。这个属性在iOS8之后开始使用,用来表示视图的遮罩。什么是遮罩呢?我想了很久都没有找到合适的比喻来介绍这个。简单来说,一个UIView的对象,可以通过设置alpha来改变这个视图的透明度,遮罩的实现效果也是一样的。唯一的差别在于前者是通过修改0~1之间的值来改变透明效果,作为遮罩的视图对象的backgroundColoralphatransform等等属性都会影响到被遮盖的视图的透明效果。

例如下面这段代码:

UIView * viewContainer = [[UIView alloc] initWithFrame: CGRectMake(0, 0, 200, 200)];
viewContainer.backgroundColor = [UIColor blueColor];

UIView * contentView = [[UIView alloc] initWithFrame: CGRectMake(20, 20, 160, 160)];
contentView.backgroundColor = [UIColor redColor];
[viewContainer addSubview: contentView];

UIView * maskView = [[UIView alloc] initWithFrame: CGRectMake(100, 100, 35, 80)];
maskView.backgroundColor = [UIColor yellowColor];
contentView.maskView = maskView;

遮罩视图决定了视图的显示内容

上面的代码小小的改动一下,我们分别修改一下maskViewcontentView的透明度,看看在遮罩透明度改变之后红色的视图会发生什么变化:


修改透明度.png

通过实验我们可以看到修改视图自身的透明度或者修改maskView的透明度达成的效果是一样的。换句话说,遮盖视图对于视图自身的影响直接决定在透明度和显示尺寸这两个可视的属性。

那么,遮盖视图除了alpha属性外,还有什么属性影响了视图本身的显示效果呢?

颜色

上面的透明度效果得出了一个结论。视图本身的显示效果取决于maskView的透明程度。在颜色不含透明空间的时候,视图是不存在透明效果的。但是假设我们设置遮罩视图的颜色透明度时:

maskView.backgroundColor = [UIColor colorWithWhite: 1 alpha: 0.5]; //任意颜色

显示的效果跟直接设置alpha = 0.5的效果是一样的。在绘制像素到屏幕上中可以获知颜色渲染和alpha属性存在的关联

maskView的子视图

maskView.backgroundColor = [UIColor clearColor];
UIView * sub1 = [[UIView alloc] initWithFrame: CGRectMake(0, 0, 20, 34)];
sub1.backgroundColor = [UIColor blackColor];
UIView * sub2 = [[UIView alloc] initWithFrame: CGRectMake(15, 18, 33, 40)];
sub2.backgroundColor = [UIColor blackColor];
[maskView addSubview: sub1];
[maskView addSubview: sub2];

要了解maskView的子视图对遮罩效果的影响,我们需要排除遮罩视图自身的干扰,因此maskView的背景颜色要设置成透明色


子视图对于遮罩的影响

可以看到,在遮罩自身透明的情况下,子视图也可以实现部分遮罩视图的效果。因此如果我们改变这些子视图的透明度的时候,遮罩效果也同样会发生改变

动画实现

回到上面展示的动画效果,我们可以看到图片被分割成多个长方形的小块逐渐消失。其中,垂直方向分为上下两份,横向大概有15份左右。因此我们需要现在maskView上面添加2*15个子视图,均匀分布。为了保证在动画的时候我们能依次实现子视图的隐藏,我们需要给子视图加上标识:

UIView * maskView = [[UIView alloc] initWithFrame: contentView.bounds];
const NSInteger horizontalCount = 15;
const NSInteger verticalCount = 2;
const CGFloat fadeWidth = CGRectGetWidth(maskView.frame) / horizontalCount;
const CGFloat fadeHeight = CGRectGetHeight(maskView.frame) / verticalCount;

for (NSInteger line = 0; line < horizontalCount; line ++) {
  for (NSInteger row = 0; row < verticalCount; row++) {
    CGRect frame = CGRectMake(line*fadeWidth, row*fadeHeight, fadeWidth, fadeHeight);
    UIView * fadeView = [[UIView alloc] initWithFrame: frame];
    fadeView.tag = [self viewTag: line*verticalCount+row];
    fadeView.backgroundColor = [UIColor whiteColor];
    [maskView addSubview: fadeView];
  }
}
contentView.maskView = maskView;

那么在动画开始的时候,我们需要依次遍历maskView上面的所有子视图,并且让他们依次执行动画:

for (NSInteger line = 0; line < horizontalCount; line ++) {
  for (NSInteger row = 0; row < verticalCount; row++) {
    NSInteger idx = line*verticalCount+row;
    UIView * fadeView = [contentView.maskView viewWithTag: [self viewWithTag: idx];
    [UIView animateWithDuration: fadeDuration delay: interval*idx options: UIViewAnimationOptionCurveLinear animations: ^{
      fadeView.alpha = 0;
    } completion: nil];
  }
}

我们在实现动画的同时,都应该考虑如何把动画封装出来方便以后复用。上面的碎片化动画完全可以作为UIViewcategory进行封装,以此来降低入侵性,实现低耦合的要求:

#define LXDMAXDURATION 1.2
#define LXDMINDURATION .2
#define LXDMULTIPLED .25

@interface UIView (LXDFadeAnimation)

/*!
 * @brief 视图是否隐藏
 */
@property (nonatomic, assign, readonly) BOOL isFade;
/*!
 * @brief 是否处在动画中
 */
@property (nonatomic, assign, readonly) BOOL isFading;
/*!
 * @brief 垂直方块个数。默认为3
 */
@property (nonatomic, assign) NSInteger verticalCount;
/*!
 * @brief 水平方块个数。默认为18
 */
@property (nonatomic, assign) NSInteger horizontalCount;
/*!
 * @brief 方块动画之间的间隔0.2~1.2。默认0.7
 */
@property (nonatomic, assign) NSTimeInterval intervalDuration;
/*!
 * @brief 每个方块隐藏的动画时间0.05~0.3,最多为动画时长的25%。默认为0.175
 */
@property (nonatomic, assign) NSTimeInterval fadeAnimationDuration;

- (void)configurateWithVerticalCount: (NSInteger)verticalCount horizontalCount: (NSInteger)horizontalCount interval: (NSTimeInterval)interval duration: (NSTimeInterval)duration;

- (void)reverseWithComplete: (void(^)(void))complete;
- (void)animateFadeWithComplete: (void(^)(void))complete;
- (void)reverseWithoutAnimate;

@end

IOS实现碎片化动画详解
本文由 IT学习网 整理,转载请注明“转自IT学习网”,并附上链接。
原文链接:http://www.ourlove520.com/Programming/others/418917.html

标签分类:

上一篇:上一篇:iOS开发之级联界面(推荐界面)搭建原理
下一篇: 下一篇:IOS实现展开二级列表效果
无觅关联推荐,快速提升流量