zoukankan      html  css  js  c++  java
  • iOS7 UIKit Dynamics 的初步研究

    这回开始学习iOS7新的UIKit Dynamics,我看有人翻译成UIKit 力学,我觉得倒挺贴切的,所以就借来用一用。

    这个UIKit力学系统里要设计到四个东西:
         1、UIDynamicAnimator:这个东西主要用于
    • 提供动力xing为的上下文
    • 根据ref view确定坐标系
    • 控制动力引擎
    • 维护着动力行为的状态
         2、UIDynamicBehavior:主要用来描述动力的行为,iOS7里默认提供了以下几种行为
    • UIAttachmentBehavior
    • UICollisionBehavior
    • UIDynamicItemBehavior
    • UIGravityBehavior
    • UIPushBehavior
    • UISnapBehavior
         3、Reference View:这个是用来初始化Animator的时候用的,作用是给动力行为提供参考坐标系
         4、dynamic item:动力项就是遵循UIDynamicItem协议的任意对象。
     
    说了那么多理论,我自己都搞不清楚了,直接上代码吧。
     
    首先来一个最简单的demo,新建一个项目,选择single VIew Application,然后在ViewController.m里声明几个变量。
     
    1 UIDynamicAnimator *_animator;
    2 UIGravityBehavior *_gravity;
    然后写一个小方法:
     
     1 - (void)startAnimator
     2 {
     3     //新建一个view来做试验的物体。
     4     UIView *testView = [[UIView alloc] initWithFrame:CGRectMake(110, 60, 100, 100)];
     5     [testView setBackgroundColor:[UIColor blueColor]];
     6     [self.view addSubview:testView];
     7     //初始化animator并且给它一个参考坐标。
     8     _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
     9     _gravity = [[UIGravityBehavior alloc] initWithItems:@[testView]];
    10     [_animator addBehavior:_gravity];
    11 }
    再把这个方法在viewDidLoad方法里用一下,就OK了。
     
    再运行程序,就会看见有模拟器上面有个蓝色的小球,然后他往下掉,接着就不见了= =。有点无聊。。。
     
    现在无聊没关系,后面我们再玩点别的,现在先来研究一下这个暂时很无聊的程序代码是怎么写的,其实很简单,首先新建一个UIView实例名字叫testView,弄成一个蓝色小球的样子,然后初始化_animator再给他参考坐标,基本上UIKit力学里的所有动作都要经它手,然后初始化_gravity,给他testView。这个_gravity顾名思义,就是给testView一个类似受到地心引力的效果,会往下掉,而往下掉的加速度默认是跟现实中的重力加速度一样的。最后把_gravity这个行为加入到_animator,就完成了!
     
    好,接下来我们研究点别的,虽然说_gravity名字叫gravity,但是我们能不能改一下加速度?可以的,下面我们来研究一下怎么改。
     
    翻看一下UIGravityBehavior文挡,发现一个名字叫magnitude的属性,很明显就是这个改变加速度了。在_gravity初始化的那行后面加上
     
    1    [_gravity setMagnitude:100];
    再运行程序,就会发现那个蓝色方块一下就飞出去了,没错,就是它了。
     
    另外UIGravityBehavior中还有几个属性
    • angle:控制物体飘向的角度
    • graviteDirection:也是控制角度,只不过是用x,y的增量来表示
    好了,知道这几个属性我们就可以控制物体怎么飘了。
     
    但是方块一下子就飘出去了,该怎么让他留在模拟器视图里面呢?这就要用到UICollisionBehavior了。
    顾名思义就是一个碰撞行为,让他碰到视图边缘也算一个碰撞行为。
     
    再ViewController.m里也声明一个UICollisionBehavior的实例名字叫_collision.
     
    1 UICollisionBehavior * _collision;
    然后在startAnimator方法里初始化一下,就在最后写就可以
    1     _collision = [[UICollisionBehavior alloc] initWithItems:@[testView]];
    2     [_collision setTranslatesReferenceBoundsIntoBoundary:YES];
    3     [_animator addBehavior:_collision];
    然后就可以看到方块掉到视图底部的时候,弹了几下,就停了。实现也很简单,初始化,给它testView,然后改TranslatesReferenceBoundsIntoBoundary
    属性为YES,最后将这个行为加到_animator里面就可以了。TranslatesReferenceBoundsIntoBoundary 这个属性也很直观,就是告诉他把视图当边界就是了。
     
    除了把视图边缘当碰撞的边界,我们也可以自定义一个边界。UICollisionBehavior也提供了这样一个方法来定义边界
     
     
     
    用法如下:
    1     [_collision addBoundaryWithIdentifier:@"barrier" fromPoint:CGPointMake(0, 360) toPoint:CGPointMake(240, 360)];
    也就是给他一个字符串说一下名字,然后从这个点到那个点,两点之间即为自己定义的边界。然而这条线是看不到样子的,不过自己也可以画一个上去。比如说下面那样。
     

     
     
     
     
    UICollisionBehavior还可以设置Delegate,让方块碰撞的时候发送回调一个方法,这时你就可以在碰撞的时候干点别的事情了。
    比如这样:
     
    给ViewController.m里遵守一个协议<UICollisionBehaviorDelegate>
     
    紧跟_collision设置自定义边界的后面写一行
    1     [_collision setCollisionDelegate:self];
    这样就可以把Delegate设置为ViewController了
     
    然后重写写协议里的方法
    1 - (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier atPoint:(CGPoint)p
    2 {
    3     UIView *v = (UIView *)item;
    4     [v setBackgroundColor:[UIColor redColor]];
    5     [UIView animateWithDuration:0.3 animations:^{
    6         [v setBackgroundColor:[UIColor blueColor]];
    7     }];
    8 
    9 }
    上面这个方法里就实现了当方块发生碰撞的时候,就会闪一下红色。
     
    除此之外在UICollisionBehaviorDelegate协议中还有几种方法
    分别可以在开始,结束,按物体来分事件还是按边界来分事件等。
     
     
    UICollisionBehavior里还可以设置碰撞模式,有一个名字叫CollisionMode的属性就可以修改这个属性,CollisionMode有三个枚举可以选择,分别是:
    • UICollisionBehaviorModeItems
    • UICollisionBehaviorModeEverything
    • UICollisionBehaviorModeBoundaries
    其实也就是你可以选择跟什么东西发生碰撞,比如选择UICollisionBehaviorModeItems的时候,就表示你指向跟另外一个物体发生碰撞,而不跟边界碰撞。
     
     
    碰撞说得差不多了,我们来研究点别的。
    比如UIAttachmentBehavior,按字面意思来理解应该是一种吸附行为,那我们再新建另一个方块来试试这个Behavior。
    1     UIView *testView2 = [[UIView alloc] initWithFrame:CGRectMake(110, 170, 100, 100)];
    2     [testView2 setBackgroundColor:[UIColor greenColor]];
    3     [self.view addSubview:testView2];
     
    把它放到第一个方块的下面,颜色为绿色。
     
    然后在_gravity初始化的时候也把第二块方块加进里面,不然第二块方块就不会往下掉了。
     
    1     _gravity = [[UIGravityBehavior alloc] initWithItems:@[testView,testView2]];
    这个时候运行程序,发现第一块方块还留在我们之前定义的边界上,而第二块方块就掉出边界消失了,这是因为我们没有把第二块方块加进_collision里面,不过这我们不管,这正好用来研究UIAttachmentBehavior。
     
    在startAnimator方法最后加上这两行代码,初始化一下_attachment,并加入两个方块,这个初始化表示两个方块吸附在一起。
    1     _attachment = [[UIAttachmentBehavior alloc] initWithItem:testView attachedToItem:testView2];
    2 
    3     [_animator addBehavior:_attachment];
    然后运行程序,发现第一个方块还是像以前那样留在边界上,但第二块方块就在边界下面,两个方块好像中间有跟绳子连在一起那样,这就是UIAttachmentBehavior的作用了。
     
    同样的,UIAttachmentBehavior也提供了好几种属性来做出各种效果,分别是:
     
     
    UIDynamicItemBehavior
     
    这个行为提供了自转和直线的运动行为。实现一个实例来说明一下,首先把之前那些奇奇怪怪的Behavior都清除掉,只留下_collision来实现一个边界就好。
    声明一个UIDynamicItemBehavior实例:
    1     UIDynamicItemBehavior *_dynamicItem;
    然后添加下面的代码:
    1     _dynamicItem = [[UIDynamicItemBehavior alloc] initWithItems:@[testView]];
    2     [_dynamicItem addAngularVelocity:5 forItem:testView];
    3     [_animator addBehavior:_dynamicItem];
    这个时候,方块会自己按顺时针方向自转,然后慢慢停下来,也就是给他一个初速度自转,接着就在摩擦之类的作用下停下来了。
     
    把上面第二行代码去掉,换成如下代码,就能实现另一个行为,直线运动,而LinearVelocity就是同样要给他一个x,y的初速度,然后它就会根据向量的叠加方向直线运动。
    1     [_dynamicItem addLinearVelocity:CGPointMake(500, 100) forItem:testView];
    在这两个行为的基础下,还有几个属性来配合这两个行为:
     
    UIPushBehavior
    还有一个PushBehavior,这个推也很好理解,我们直接来看代码,把代码中除了关于方块,_animator,_collision的东西都删掉,在最后添加如下代码:
    1     _push = [[UIPushBehavior alloc] initWithItems:@[testView] mode:UIPushBehaviorModeInstantaneous];
    2     [_push setAngle:1];
    3     [_push setMagnitude:0.2];
    4     [_animator addBehavior:_push];
    再运行程序,就可以看见方块仿佛被推了一下,然后就动了起来,代码实现也很简单,初始化_push,然后给他方块,还有设置一个模式,这里模式分别有UIPushBehaviorModeInstantaneous以及mode:UIPushBehaviorModeContinuous,两个的区别就是一个是推一下,一个是连续推。
    初始化完之后,就给他设置角度和初速度就好了,简单粗暴。
     
     
    UISnapBehavior
    最后还有一个UISnapBehavior,其实这个更简单,按照惯例直接上代码
     
    1    _snap = [[UISnapBehavior alloc] initWithItem:testView snapToPoint:CGPointMake(400, 400)];
    2     [_animator addBehavior:_snap];
    运行程序,就会发现方块突然好像被钉在某处那样,没错,这就是UISnapBehavior的效果。无需多解释。
     
    它也只有一个属性damping,直接加上这一行:
    1     [_snap setDamping:10];
    就会发现方块移动变慢了,这就是一个阻尼属性。
     
    研究下来,其实实现也很简单的,这系列API真的帮助我们简单地实现这些挺好玩的效果,材料就在这里,炒成什么菜就看大家了!
  • 相关阅读:
    HTML---网页编程(2)
    HTML---网页编程(1)
    HDOJ/HDU 1297 Children’s Queue(推导~大数)
    HDOJ/HDU 1250 Hat's Fibonacci(大数~斐波拉契)
    HDOJ/HDU 1133 Buy the Ticket(数论~卡特兰数~大数~)
    洛谷P1314 [NOIP2011提高组Day2T2] 聪明的质监员
    洛谷P1313 [NOIP2011提高组Day2T1]计算系数
    POJ3696 The Luckiest number
    洛谷P1312 [NOIP2011提高组Day1T3]Mayan游戏
    洛谷P1311 [NOIP2011提高组Day1T2]选择客栈
  • 原文地址:https://www.cnblogs.com/adamleung/p/3497709.html
Copyright © 2011-2022 走看看