首页 > 代码库 > Getting Started with UIKit Dynamics--WWDC 2013 session 206

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,所以我也暂时不去细究这个了。