标签:
代码:https://github.com/xufeng79x/ViewBaseAnimation
1.简介
Animation,源于拉丁语,意为给无生命的物体注入灵魂。
动画可以为app应用增色不少,提高用户体验。
我们一般使用UIKit框架的UIView自带的动画功能就可以满足大部分场景。但是如果要实现layer层的动画则需要使用Core Animation框架了。本文我们着重学习 UIView的自带动画功能。
2.可动画参数
在UIView中并不是所有的属性变化都可以转换成动画。只有下表中7个属性具有动画资格。
Property |
Changes you can make |
---|---|
Modify this property to change the view’s size and position relative to its superview’s coordinate system. (If the |
|
Modify this property to change the view’s size. |
|
Modify this property to change the view’s position relative to its superview’s coordinate system. |
|
Modify this property to scale, rotate, or translate the view relative to its center point. Transformations using this property are always performed in 2D space. (To perform 3D transformations, you must animate the view’s layer object using Core Animation.) |
|
Modify this property to gradually change the transparency of the view. |
|
Modify this property to change the view’s background color. |
|
Modify this property to change the way the view’s contents are stretched to fill the available space. |
单个view的动画效果
1.触发动画
如果我们单纯的改变以上的参数并不会产生任何动画效果,或者理解为并不会产生变化前到变换后的“慢动作”效果。在iOS4以及之后的版本中我们通常使用如下UIView的类方法进行基于block的动画驱动:
以上方法都是类方法,所以我们可以在一个block进行多个view的参数修改已达到多个view同时产生动画的效果。
如下我们先来实现一个简单的透明度的效果:
-(void)simpleAnimation { [UIView animateWithDuration:2.0 animations:^{ self.blueView.alpha = 0.0; self.redView.alpha = 0.0; }]; }
上述代码中将在2秒内缓慢的将两个view的透明度将为0,既不可见。
结果:
上述例子中我们仅仅使用最简单的类方法实现了动画,如果想要实现更多的效果则我们需要使用如下方法
animateWithDuration:delay:options:animations:completion:
上述方法能够代码如下效果:
The type of timing curve to use during the animation
The number of times the animation should repeat
Whether the animation should reverse itself automatically when it reaches the end
Whether touch events are delivered to views while the animations are in progress
Whether the animation should interrupt any in-progress animations or wait until those are complete before starting
以下为此方法的详细参数说明
duration |
The total duration of the animations, measured in seconds. If you specify a negative value or 动画总共持续时间,单位为秒。如果你传入负数或者0的时候将不会产生动画效果 |
delay |
The amount of time (measured in seconds) to wait before beginning the animations. Specify a value of 动画执行延迟时间,单位为秒,如果你传入0,则动画将立即执行。 |
options |
A mask of options indicating how you want to perform the animations. For a list of valid constants, see 动画执行选项。可参考 enum { UIViewAnimationOptionLayoutSubviews = 1 << 0, UIViewAnimationOptionAllowUserInteraction = 1 << 1, UIViewAnimationOptionBeginFromCurrentState = 1 << 2, UIViewAnimationOptionRepeat = 1 << 3, UIViewAnimationOptionAutoreverse = 1 << 4, UIViewAnimationOptionOverrideInheritedDuration = 1 << 5, UIViewAnimationOptionOverrideInheritedCurve = 1 << 6, UIViewAnimationOptionAllowAnimatedContent = 1 << 7, UIViewAnimationOptionShowHideTransitionViews = 1 << 8, UIViewAnimationOptionOverrideInheritedOptions = 1 << 9, UIViewAnimationOptionCurveEaseInOut = 0 << 16, UIViewAnimationOptionCurveEaseIn = 1 << 16, UIViewAnimationOptionCurveEaseOut = 2 << 16, UIViewAnimationOptionCurveLinear = 3 << 16, UIViewAnimationOptionTransitionNone = 0 << 20, UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20, UIViewAnimationOptionTransitionFlipFromRight = 2 << 20, UIViewAnimationOptionTransitionCurlUp = 3 << 20, UIViewAnimationOptionTransitionCurlDown = 4 << 20, UIViewAnimationOptionTransitionCrossDissolve = 5 << 20, UIViewAnimationOptionTransitionFlipFromTop = 6 << 20, UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20, }; typedef NSUInteger UIViewAnimationOptions;
|
animations |
A block object containing the changes to commit to the views. This is where you programmatically change any animatable properties of the views in your view hierarchy. This block takes no parameters and has no return value. This parameter must not be block对象,其内容即为动画内容。此block无参数,无返回值不能为null |
completion |
A block object to be executed when the animation sequence ends. This block has no return value and takes a single Boolean argument that indicates whether or not the animations actually finished before the completion handler was called. If the duration of the animation is 0, this block is performed at the beginning of the next run loop cycle. This parameter may be block对象,当动画执行完毕的时候会调用此block。没有返回值,有一个布尔类型的参数用于监控当前动画是否已经执行完毕。如果duration参数为0的时候,此block将会在下一次runloop的周期开始时候出发。此参数可谓nil,以为不需要事后处理任何东西。 |
上述例子中的我们使用animateWithDuration:animations:方法来实现了动画,其实内部依然是调用了animateWithDuration:delay:options:animations:completion:只是有些参数使用了默认值而已。如下面的代码等价于上述例子:
-(void)simpleAnimation { // [UIView animateWithDuration:2.0 animations:^{ // self.blueView.alpha = 0.0; // self.redView.alpha = 0.0; // }]; [UIView animateWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{ self.blueView.alpha = 0.0; self.redView.alpha = 0.0; } completion:nil]; }
2.高级-动画block的嵌套
我们可以在一个动画的block中启动另外一个动画如
-(void) nestAnimationDefault { [UIView animateWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{ self.blueView.alpha = 0.0; [UIView animateWithDuration:5.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{ self.redView.alpha = 0.0; } completion:nil]; } completion:nil]; }
结果:
你可能已经注意到,在嵌套代码中红色view的动画被指定为持续5秒,但是在结果中却依然和蓝色view持续一样的时间。
原因为嵌套动画的参数要继承其父动画的参数,当然我们也可以在嵌套动画中覆盖重写自己的参数,但是需要在选项参数中指定UIViewAnimationOptionOverrideInheritedCurve
和 UIViewAnimationOptionOverrideInheritedDuration
上述代码修改为:
-(void) nestAnimationDefault { [UIView animateWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{ self.blueView.alpha = 0.0; [UIView animateWithDuration:5.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone|UIViewAnimationOptionOverrideInheritedCurve | UIViewAnimationOptionOverrideInheritedDuration animations:^{ self.redView.alpha = 0.0; } completion:nil]; } completion:nil]; }
结果:
3.高级-动画重复
有时候我们需要某个动画按照指定的变化重复多次,如何做呢?
-(void)repeatAnimation { [UIView animateWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone animations:^{ [UIView setAnimationRepeatCount:3]; self.blueView.alpha = 0.0; self.redView.alpha = 0.0; } completion:nil]; }
上述动画中通过setAnimationRepeatCount:方法设定了当前动画被执行3此,需要注意的是此方法只影响当前动画。
结果:
4.高级-动画反转变化
类似呼吸的效果,一吐一吸。需要指定UIViewAnimationOptionAutoreverse选项。
-(void)reverseAnimation { [UIView animateWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone |UIViewAnimationOptionAutoreverse animations:^{ [UIView setAnimationRepeatCount:3.0]; self.blueView.alpha = 0.0; self.redView.alpha = 0.0; } completion:nil]; }
结果:
我们可以看到view从有到无一共发生4次,最有一次突然间消失,为什么会发生4次,最后一次为什么会突然消失呢?
这是因为原本一次的动画当执行为反转动画的时候,一次即代表【有到无】和【无到有】算一次,既【有到无】为0.5次,【无到有】为0.5次。
所以当repeat指定为三次的时候最后一次为【无到有】,但是按照block的参数变化指定来说需要将其变为【无】,所以最后一次就突然的消失了以遵守这个约束。
所以要想顺畅的让其变化三次并顺滑的过渡到参数变化的约束值,repeat需要为[X.5],此例子中我们可以将repeat指定为2.5次。
[UIView setAnimationRepeatCount:2.5];
最终的效果为:
多个view之间的过度动画效果
当你在view层级中增加,删除,隐藏和显示某个view的时候使用过度动画效果使得这种变化更加顺滑。使用view级别的过度动画时你可以实现以下两种效果:
就如一个view钟只能有7个参数具可动画效果,在此场景中也只有上述红色标出的动作具有专场动画效果。
对于多个view之间的关联过度动画可以使用如下类方法进行操作:
transitionWithView:duration:options:animations:completion:
+ (void)transitionWithView:(UIView *)view
duration:(NSTimeInterval)duration
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion
view |
The container view that performs the transition. 发生动画的效果的view,通常选取参与变化的view的共有父view作为此参数值。 |
duration |
The duration of the transition animation, measured in seconds. If you specify a negative value or 过度动画持续时间,单位为秒。如果指定为负值或者0的时候,将不会产生动画效果。 |
options |
A mask of options indicating how you want to perform the animations. For a list of valid constants, see 过度动画的选项指定,可以参考 typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) { UIViewAnimationOptionLayoutSubviews = 1 << 0, UIViewAnimationOptionAllowUserInteraction = 1 << 1, // turn on user interaction while animating UIViewAnimationOptionBeginFromCurrentState = 1 << 2, // start all views from current value, not initial value UIViewAnimationOptionRepeat = 1 << 3, // repeat animation indefinitely UIViewAnimationOptionAutoreverse = 1 << 4, // if repeat, run animation back and forth UIViewAnimationOptionOverrideInheritedDuration = 1 << 5, // ignore nested duration UIViewAnimationOptionOverrideInheritedCurve = 1 << 6, // ignore nested curve UIViewAnimationOptionAllowAnimatedContent = 1 << 7, // animate contents (applies to transitions only) UIViewAnimationOptionShowHideTransitionViews = 1 << 8, // flip to/from hidden state instead of adding/removing UIViewAnimationOptionOverrideInheritedOptions = 1 << 9, // do not inherit any options or animation type UIViewAnimationOptionCurveEaseInOut = 0 << 16, // default UIViewAnimationOptionCurveEaseIn = 1 << 16, UIViewAnimationOptionCurveEaseOut = 2 << 16, UIViewAnimationOptionCurveLinear = 3 << 16, UIViewAnimationOptionTransitionNone = 0 << 20, // default UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20, UIViewAnimationOptionTransitionFlipFromRight = 2 << 20, UIViewAnimationOptionTransitionCurlUp = 3 << 20, UIViewAnimationOptionTransitionCurlDown = 4 << 20, UIViewAnimationOptionTransitionCrossDissolve = 5 << 20, UIViewAnimationOptionTransitionFlipFromTop = 6 << 20, UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20, } NS_ENUM_AVAILABLE_IOS(4_0);
|
animations |
A block object that contains the changes you want to make to the specified view. This block takes no parameters and has no return value. This parameter must not be block对象,内容为过度动画。无参数无返回值,但是不能为NULL。 |
completion |
A block object to be executed when the animation sequence ends. This block has no return value and takes a single Boolean argument that indicates whether or not the animations actually finished before the completion handler was called. If the duration of the animation is 0, this block is performed at the beginning of the next run loop cycle. This parameter may be block对象,让过度动画结束的时候会执行这个block。有一个布尔类型的参数用于监控过度动画是否结束。如果duration被指定为0,这个block将会在下一次的runloop周期中被执行,此参数可以为NULL。 |
1.例子-改变view的子view
代码:
- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [UIView transitionWithView:self.containerView duration:1.0 options:UIViewAnimationOptionTransitionCurlUp animations:^{ self.currentView.hidden = YES; self.swapView.hidden = NO;
self.swapView.alpha = 0.0;
} completion:^(BOOL finished){ UIView* temp = self.currentView; self.currentView = self.swapView; self.swapView = temp;
self.currentView.alpha = 1.0;
}];
}
上述代码中我们在一个名为containerView上的两个子view做影藏和显示的替换效果。
结果:
上述代码实现基于self.view的过度动画,但是如下这个效果并没有实现,按照代码应该在专场过程中,当前的view会附件透明。
self.swapView.alpha = 0.0;
原因为上述动画在实际实现过程中,只是内部生成了两个快照图片,在发生过度动画期间只是在这两个图片之间切换而已。
如果我们要在过度动画进行中实现内部内容的动画效果需要加上 UIViewAnimationOptionAllowAnimatedContent
操作选项。
加上后的效果为:
2.例子--在view层级中替换某个view
View的替换可以快速的controller的不变的情况下动态更改view层级,从而实现不同的界面展现。
通常我们使用如下方法进行这一个操作,
transitionFromView:toView:duration:options:completion:
+ (void)transitionFromView:(UIView *)fromView
toView:(UIView *)toView
duration:(NSTimeInterval)duration
options:(UIViewAnimationOptions)options
completion:(void (^)(BOOL finished))completion
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [UIView transitionFromView:(self.displayingPrimary ? self.primaryView : self.secondaryView) toView:(self.displayingPrimary ? self.secondaryView : self.primaryView) duration:1.0 options:(self.displayingPrimary ? UIViewAnimationOptionTransitionFlipFromRight : UIViewAnimationOptionTransitionFlipFromLeft) completion:^(BOOL finished) { if (finished) { self.displayingPrimary = !self.displayingPrimary; } }]; }
上述代码中我们事先了两个view以从左从右过度的笑话效果,将一个view移除后将另外一个view显示出来。
结果:
上述例子中档点击屏幕替换view后发现最后为空白屏幕,这是应为此方法将会移除fromView并使用toView来代替他,如果你想保持对fromView的引用,你需要自己去维护,因为默认情况下框架会直接将此view进行删除(或者引用计数减一,不维护则会被回收)。
如果你仅仅想要隐藏fromView的话你也可以将UIViewAnimationOptionShowHideTransitionViews最为一个选项。
加上此选项后的结果为:
连接多个动画
我们可以使用 animateWithDuration:animations:completion:
和 animateWithDuration:delay:options:animations:completion:的completion handler来将两个动画相连使得他们能够有序而非同时进行。
当让我们也可以使用动画嵌套的方式,将delay控制成有先后顺序去执行也可以达到相同效果,你可以两者选一。
将基于view的动画和layer层的动画嵌套使用
略。
标签:
原文地址:http://www.cnblogs.com/ios123/p/5231996.html