Getting Started with UIKit Dynamics--WWDC 2013 session 206
核心概念(Core concepts)
在iOS上面常见的动画以及交互包括以下几种:
• Core Animation
• UIView animations
• Motion effects
• Gesture driven interactions
• CADisplayLink
那么UIKit Dynamics是什么呢?Apple自己的表述就是:一个可组合,可重用的,声明性的,真实世界的启发性的动画和交互系统。
基本架构如下图所示:
我们来看一下这个UIDynamicAnimator ,它的职责在于以下4点:
• Provide the overall context
• Define the coordinate system
• Control the engine
• Keep track of behaviors
使用方法如下:
animator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView];
[animator addBehavior:...];
[animator addBehavior:...];
这与上图所描述的框架也相符。
然后看下必不可少的UIDynamicBehavior,它的主要职责与特点如下:
• Declarative 声明化的
• Describe “influences” on views 描述对目标views的影响
• Added and removed at any time 随时添加与删除
• Composable 可组合的
• Subclassable 可继承的
当然看上面的代码,behavior是添加到animator里面的。
预定义行为(Predefined behaviors)
• Gravity
• Collision
• Attachments
• Snap
• Forces
• Item properties
上面几个是系统直接提供的“动画行为”。
首先第一个UIGravityBehavior,这是重力行为
一般提供一个重力向量就可以,默认是(0,1)。向量方向是遵照UIKit的坐标系统的。
g = [[UIGravityBehavior alloc] initWithItems:@[v]];
[animator addBehavior:g];
注:initWithItems中的item,是可以随时添加与删除的,跟上面一样。behavior可以随时添加删除,behavior中的item也是可以随时添加删除。另外删除的瞬间,所有的相关动画影响都会马上停止。
第二个UICollisionBehavior,碰撞!两种碰撞行为可以被检测到:
1.关联了collisionbehavior的view与所设定的边界
2.关联了相同的collisionbehavior的多个view之间
3.默认是上述两个同时可以检测到的,如图:
根据这个特点,我们有时可以设置不同种类的view之间产生碰撞,但又不会影响其他view。例如红色view只与红色view碰撞:
那么边界是如何界定呢?有两种:
1.根据最上面提到的the reference view的bounds ,只需设置@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;这个属性即可。
2.同样根据the reference view的bounds,不过可以设置insets:
-(void)setTranslatesReferenceBoundsIntoBoundaryWithInsets: (UIEdgeInsets)insets;
如下图所示:
最后,最重要的是要使用UICollisionBehaviorDelegate,这样才能检测到碰撞!
第三个,UIAttachmentBehavior,怎么解释呢?应该是“吸附”,类似磁铁或弹簧吧。
看下这个最简单的初始化:
//Between a view and an anchor point a1 = [[UIAttachmentBehavior alloc] initWithItem:v1 attachedToAnchor:ap]; //Between two views a2 = [[UIAttachmentBehavior alloc] initWithItem:v1 attachedToItem:v2];
v1,v2,ap如下图所示
默认吸附点是view的center,但是可以用另一个初始化方法,使得吸附点在别的地方,但是注意是相对于center的偏移
//The view attachment point can be an offset from the center a1 = [[UIAttachmentBehavior alloc] initWithItem:v1 point:p1 attachedToAnchor:ap]; a2 = [[UIAttachmentBehavior alloc] initWithItem:v1 point:p2 attachedToItem:v2];
其实还有很多属性可以设置,例如“弹簧属性”:
[a setFrequency:4.0];频率
[a setDamping:0.5];阻尼
这些物理学不懂就回去恶补下吧~哈哈
下一个就是UISnapBehavior,这个嘛,怎么说呢,看图吧~
初始化好之后,
s = [[UISnapBehavior alloc] initWithItem:v snapToPoint:p];
[animator addBehavior:s];
v就会像下面的第一个图运动到第二个图的位置
第五个了吧~UIPushBehavior,这个嘛,简单地说就是物理模型中的外力F作用到物体上面,这个物体就是我们的每一个view了。同理外力F有有大小有方向,也就是一个向量,如果接触过spritekit应该明白里面有个apply force,这是同样的效果。
//Apply a force to a view (or views) p = [[UIPushBehavior alloc] initWithItems:@[view] mode:UIPushBehaviorModeContinuous]; //A simple force vector @property (readwrite,nonatomic) CGFloat xComponent; @property (readwrite,nonatomic) CGFloat yComponent; @property (readwrite,nonatomic) CGFloat angle; @property (readwrite,nonatomic) CGFloat magnitude; //The target point can be customized [p setTargetPoint:x forItem:view];
暂不细究还可以如何去设置。第一句是初始化,这个推力可以是对一个或多个view产生作用,最后一句是设置作用点。实在不明白,就回去看下牛顿一二三定律吧~
最后补充的是,现实世界的牛顿单位加速度(不知道翻译对不对,哈哈)是1kg的物体,其加速度为1m/s^2。
而UIKit的单位加速度是对于一个100*100大小的view,其加速度是100p/s^2,p是像素。
所以在处理动画快慢或者真的做关于牛顿定律的应用时候,就要注意了。
最佳实践(Best practices)
最佳实践竟然是UIDynamic与CollectionView的结合,无奈暂时没有深入研究CollectionView,所以我也暂时不去细究这个了。