Animation 动画
A.属性动画;
B.一次进行多个动画;
C.基于物理的动画。
Core Animation
是现有、强大的动画框架。
A.UIView的属性动画
属性变化是立即完成的,但是在屏幕上的显示会经过一段时间的动画变化,
等动画结束后才显示正确的属性,可以参考UIView的方法animationWithDuration:...
B.UIView的任意显示变化动画
如跳转flipping、溶解dissolving、弯曲curling整个视图等。
使用UIView的类方法:transitionWithView:...
C.动态动画
给可以做动画的物体(通常是UIView)指定物理特性,
如重力、推力、物体间的联系、碰撞边界等,让物理效果发生。
1UIView Animation
A. 一系列UIView的属性的变化可以实现一段动画:
帧(frame)动画;
变换(transform)动画,如translation位置移动、ratation旋转和scale缩放;
alpha动画,改变的是透明度。
B.使用UIView的方法和block来实现动画
类方法需要动画参数和一个动画block参数,动画block包含改变UIView的代码,
大部分时候还有一个"completion block",当动画完成后执行这个block;
block中改变UIView的变化是马上完成的(虽然它们看起来是经过了一段时间)。
C.UIView中关于动画的类方法
+(void)animateWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion;
例:
[UIView animateWithDuration:3.0
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{myView.alpha = 0.0;}
completion:^(BOOL fin) {if (fin) [myView removeFromSuperView]; }];
以上代码将使myView在3秒内逐渐淡出(代码执行后马上开始,没有延迟)。
然后在动画结束后会将myView从类层次结构中删除。
如果在3秒内其它人把alpha修改成非0,那么删除动作将不会执行。
另一个例子:
if (myView.alpha == 1.0) {
[UIView animateWithDuration:3.0
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{myView.alpha = 0.0;}
completion:^nil];
NSLog(@"alpha is %f. ", myView.alpha);
}
以上代码也将使myView在3秒内逐渐淡出,但是要经过2秒的延迟后再开始。
NSLog将会麻烦执行,不会等3秒或5秒的延迟,而且它会打印:"alpha is 0."
换句话说,动画block改变属性的操作是马上执行的,但是动画本身是在2秒后
才开始,并且经历了3秒钟。
D.UIViewAnimationOptions
BeginFromCurrentState // 打断其它正在进行的相关的属性动画
AllowUserInteraction // 动画进行是允许处理手势
LayoutSubviews //
Repeat // 一直重复动画
AutoReverse // 动画运行完后以相反的方式再执行一遍
OverrideInheritedDuration //
OverrideInheritedCurve //
AllowAnimatedContent //
CurveEaseInEaseOut //
CurveEaseIn //
CurveLinear //
E.有时你想一次进行多个动画,如:
By flipping view over UIViewAnimationOptionsTransitionFlipFrom{left,Right,Top,Bottom}
Dissolving from old to new state UIViewAnimationOptionsTransitionCrossDissolve
Curling up or down UIViewAnimationOptionsTransitionCurling{Up,Down}
只需要把以上变化代码放到以下UIview类的类方法的动画block参数中:
+(void)transitionWithView:(UIView *)view
duration:(NSTimeInterval)duration
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^) (BOOL finished))completion;
F.改变视图层次结构的动画有点不一样
以动画方式用一个view替换另一个view:
+(void)transitionFromView:(UIView *)fromView
toView:(UIView *)toView
duration:(NSTimeInterval)duration
options:(UIViewAnimationOptions)options
completion:(void (^)(BOOL finished))completion;
如果你想使用hidden属性,请包括UIViewAnimationOptionShowHideTransitionViews;
否则以上调用将在视图层次结构中删除fromView、增加toView;
2.Dynamic 动画
跟上述的动画实现方式有些不一样,
设置一些物理关联的动画对象,让它们运行,直到它们的速度最终变成0.
也可以比较容易的通过设置,让它们的速度永远不会变成0,但是这可能引发性能问题。
步骤:
创建一个UIDynamicAnimator对象
给这个对象添加UIDynamicBehaviors(gravity,collisions,etc).
向UIDynamicBehaviors中添加UIDynamicItems.
就这么简单! 然后相关的动作将会开始运行。
创建一个UIDynamicAnimator对象
UIDynamicAnimator * animator = [[UIDynamicAnimator allco] init];
如果动画是针对view的,那么view一定要在视图层次结构中。
创建并添加UIDynamicBehaviors
e.g.,UIGravityBehavior * gravity = [[UIGravityBehavior alloc] init];
[animator addBehavior:gravity];
e.g.,UICollisionBehavior * collider = [[UICollisionBehavier alloc] init];
[animator addBehavior:collider];
向UIDynamicBehavior中添加UIDynamicItems:
id <UIDynamicItem> item1 = ...;
id <UIDynamicItem> item2 = ...;
[gravity addItem:item1];
[collider addItem:item1];
[gravity addItem:item2];
以上Items必须实现了UIDynamicItem协议:
@protocol UIDynamicItem
@property (readonly) CGRect bounds;
@property (readwrite) CGPoint center;
@property (readwrite) CGAffineTransfrom transform;
@end
UIView 实现了这个协议。
如果你在动画运行时修改了center或者transform,你必须调用UIDynamicAnimator的
-(void)updateItemUsingCurrentState:(id <UIDynamicItem>)item;
Behaviors
UIGravityBehavior
@property CGFloat angle;
@property CGFloat magnitude; // 1.0 is 1000 point/s/s
UICollisionBehavior
@property UiCollisionBehaviorMode collisionMode; // Items,Boundaries,Everything(default).
-(void)addBoundaryWithIdentifier:(NSString *)identifier forPath:(UIBezierPath *)path;
@property BOOL translatesReferenceBoundsIntoBoundary;
UIAttachmentBehavior
-(instancetype)initWithItem:(id <UIDynamicItem>item attachedToAnchor:(CGPoint)anchor;
-(instancetype)initwithItem:(id <UIDynamicItem>i1 attachedToItem:(id <UIDynamicItem>)i2;
-(instancetype)initWithItem:(id <UIDynamicItem>item offsetFromCenter:(CGPoint)offset...
@property (readwrite) CGFloat lenght; // distance between attached things(settable!)
也可以设置震动的阻尼和频率
@property (readwrite)CGPoint anchorPoint; //可以在任何时候重置
UISnapBehavior
-(instancetype)initWithItem:(id <UIDynamicItem>item snapToPoint:(CGPoint)point;
想象一下一个item移动到一个新位置时四周绑上了四根弹簧,
你可以使用 @property CGFloat damping; 属性来控制这“四根弹簧”的阻尼系数。
UIPushBehavior
@property UIPushBehaviorMode mode; //连续的或者瞬间的
@property CGVector pushDirection;
@property CGFloat magnitude/angle; //magnitude 1.0 moves a 100*100 view at 100 pts/s/s
UIDynamicItemBehavior
控制物体再被其他行为影响下的表现(行为)。
任何添加到这个行为的item都会被影响到。
@property BOOL allowsRotation;
@property BOOL friction;
@property BOOL elasticity;
@property CGFloat density;
也可以获取item的信息:
-(CGPoint)linearVelocityForItem:(id <UIDynamicItem>item;
-(CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;
UIDynamicItemBehavior的行为表现比较复杂,如果你要使用多个UIDynamicItemBehavior行为,
你最好要知道自己在干什么。
UIDynamicBehavoir
是behavior的父类,你可以通过混合其他behavior来创建自己的子类。
通常你需要重写 init/addItems/removeItem方法。
-(void)addChildBehavior:(UIDynamicBehavior *)behavior;
这个是封装其他物理行为组合的好方法,
你也可能需要增加一些api来帮助你的子类来配置它的孩子(behavior)。
所有的behavior都知道自己属于哪个UIDynamicAnimator,
同一时间它们只能属于一个UIDynamicAnimator:
@property UIDynamicAnimator * dynamicAnimator;
如果它的animator发生了变化,behavior将会受到以下消息:
-(void)willMoveToAnimator:(UIdynamicAnimator *)animator;
UIDynamicBehavior的action属性
这个属性是一个block,如果设置了这个属性,这个block会在每次behavior被应用时调用
@property (copy) void (^action)(void);
你可以设置这个block来做任何事情,但是它会被调用很多次,所以尽量让他有效率的运行。
如果这个action引用了behavior内部的属性,请注意内存循环引用问题!