重力学这个名词不论在哪个行业领域听起来似乎都很高大上。那么在Swift中的重力学是什么呢?那就是将我们移动端屏幕上毫无生命力的东西也置于万有引力中,使它们能够展现出好像真的由于引力而向下坠落以及碰到物体后自然的弹开的效果。

要想做到这一点,我们得需要两个利器:UIKit DynamicsMotion Effects

  • UIKit DynamicsUIKit中一套完整的物理引擎。它可以让我们在程序中对界面元素添加一些行为从而达到诸如重力、弹簧等现实中的动作行为。你只需在引擎中注册界面元素,并指定好物理行为,其他的事就交给物理引擎去完成了。
  • Motion Effects可以创建很酷的视差效果,就像你iPhone上横竖屏切换时那样。它基于Apple提供的重力加速器提供的数据计算分析,使我们的界面元素根据移动设备的倾斜方向做出相应的反应。

当这两者一起使用的时候,我们就可以让程序活起来,富有生命力。

让我们开始屌丝的逆袭

我们挑一些小例子来学习UIKit Dynamics

注:由于个人编码习惯,在Swift代码中我还是加了;,其实可加可不加,根据大家喜好。

打开Xcode6新建项目,选择iOS Application/Single View Application,名称随便取,我这里命名为UIKitDynamicsDemo,我们可以看到Single View Application的目录结构:

打开ViewController.swift文件,在viewDidLoad方法中添加如下代码:

// 创建一个正方形View,颜色设置为蓝绿色,加入当前的View中
let square = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100));
square.backgroundColor = UIColor.cyanColor();
self.view.addSubview(square);

上面的代码在我们的屏幕上添加了一个蓝绿色的正方形UIView。运行一下,我们能看到一个木讷的蓝绿色正方形静静的待在屏幕中:

如果你用真机运行,你可以摇晃一下手机、倾斜手机、拿着手机手舞足蹈一下,看看那个木讷的方块有什么反应和变化么?答案是要有反应你就见鬼了。因为我们写的这几行代码只能让它杵在那一动不动,那怎么能让它动起来呢?接下来让我们见证奇迹的时刻!

添加重力行为

ViewController.swift文件中添加两个属性:

// UIKit物理引擎
var animator: UIDynamicAnimator!;// 重力行为
var gravity: UIGravityBehavior!;

注:代码中感叹号的作用这里不做过多介绍,请自行查阅官方文档。

然后在viewDidLoad方法中再加入以下代码:

// 实例化UIKit物理引擎类,作用于ViewController的View
animator = UIDynamicAnimator(referenceView: self.view);// 实例化重力行为类,目前只作用于刚才创建的正方形View
gravity = UIGravityBehavior(items: [square]);// 将重力行为添加到UIKit物理引擎类中
animator.addBehavior(gravity);

现在再编译运行一下,这时我们可以看到这个蓝绿色正方形开始做自由落体运动了,一直跌落出屏幕下边缘然后消失。

我们来看看刚才我们添加的两个属性的类型:

  • UIDynamicAnimator属于UIKit物理引擎中的类。它的作用是跟踪你添加到物理引擎中的各种行为动作,比如这里的重力行为,并且提供整个上下文。实例化UIDynamicAnimator时,它的构造函数需要传入一个referenceView参数,用于告知它要跟踪并制定坐标的View
  • UIGravityBehavior是一个模拟重力的模型,可作用于一个或多个元素。它的构造函数需要传入一个数组,该数组的内容就是我们希望有重力表现的一个元素或多个元素。

大多数的行为都有一些配置属性,比如重力行为就有可以改变角度和速率的属性:

// 实例化UIKit物理引擎类,目前只作用于刚才创建的正方形View
animator = UIDynamicAnimator(referenceView: self.view);    // 实例化重力行为类,目前只作用于刚才创建的正方形View
gravity = UIGravityBehavior(items: [square]);// 角度
gravigy.angle = 1.6;// 速率
gravigy.magnitude = 0.1;// 将重力行为添加到UIKit物理引擎类中
animator.addBehavior(gravity);

上述代码中的angle是重力行为的角度属性,angle的值为0时,方块会水平向右移动,随着值的增大,方块会顺时针改变角度。不过我们要模拟现实中的重力,所以该属性一般不设置,不设置时默认是垂直向下移动。magnitude是重力行为的速率属性,值越大下降的速度越快,当magnitude属性的值为0时,方块就不会下降了,所以最小的速率是0.1。

注意:在现实世界中,重力加速度大约是g = 9.80665m/s^2,就是9.8米每平方秒。根据牛顿第二定律,我们可以使用0.5 * g * Time^2公式来计算下坠距离。
在UIKit的重力世界中,计算重力加速度的公式是一样的,但是单位有所不同。不是米而是像素,即g = 1000pixels/s^2,我们同样可以使用牛顿第二定律来计算我们的方块在单位时间内下降的距离。我们只需要知道重力加速度g越大,坠落速度越快,所以上述代码中的magnitude属性就差不多是这意思。

不能让我们的方块一坠千里

从目前代码的运行状况知道,我们的方块下降到屏幕底部时丝毫没有停止的意思,直接坠崖而下,看都看不见。我们希望我们的屏幕类似一个盒子一样,方块在盒子中,当下降到底部时就停止,那么我们就需要设置一个边界。

ViewController.swift文件中再添加一个属性:

// 碰撞行为
var collision: UICollisionBehavior!;

然后在viewDidLoad方法中加入以下几行代码:

// 实例化碰撞行为类,目前只作用于刚才创建的正方形View
collision = UICollisionBehavior(items: [square]);// 将参考视图的边界作为碰撞边界
collision.translatesReferenceBoundsIntoBoundary = true;// 将碰撞行为添加到UIKit物理引擎类中
animator.addBehavior(collision);

上面的代码创建了边界行为,它会将一个或多个边界与指定的View联系起来,并使两者有具有交互行为。

从上面代码我可以注意到collision.translatesReferenceBoundsIntoBoundary = true;这行代码,它的意思是将UIDynamicAnimator引用的View的边界作为碰撞行为的触发边界,这样就不用我们再去设置边界的坐标了,非常好用。

接着我们编译运行看看,此时小方块坠落到屏幕底部时会产生碰撞效果,并且还会反弹几下,是不是很逼真呢。

碰撞行为进阶应用

接下来我们在屏幕中再添加一个View,长方形并横在屏幕中间,在viewDidLoad方法中添加如下代码:

// 创建一个长方形View,颜色设置为红色,加入当前的View中
let barrier = UIView(frame:CGRect(x: 0, y: 300, width: 140, height: 20));
barrier.backgroundColor = UIColor.redColor();
self.view.addSubview(barrier);

但是我们发现这个红色的障碍物和方块并没有任何交互行为,这里有一点很重要:只有被行为关联起来的Views才会具有交互行为。我们来看看下面这张关系图:

UIDynamicAnimator引擎引用了当前屏幕的view,该view给引擎提供了整个坐标系统。每个行为可以关联多个元素,每个元素都可以被多个行为关联,上面的关系图可以很清晰的表现出当前app中各个行为与元素的关联关系。由于所有行为都没有与长方形view关联,所以barrier基本可以被忽略。

唤醒Barrier

如果我们想让barrier活起来,我们得让碰撞行为将它关联起来:

// 实例化碰撞行为类,目前作用于刚才创建的正方形View和长方形View
collision = UICollisionBehavior(items: [square,barrier]);

barrier添加到碰撞行为关联元素的数组中。这样的话,squarebarrier这两个view都会有碰撞行为,所以当他们相撞时就会产生碰撞效果。

编译并运行,让我们来看看睡醒的barrier会产生什么效果:

我们再来看看现在app中行为与元素的关系图:

来看看我给这个红色长方形view起的名字:barrier,没错,障碍物。但是它现在是一个称职的障碍物吗?显然不是,当它与蓝绿色正方形碰撞时,它会于正方形一起旋转坠落。

等等,为什么barrier坠落到屏幕底部后不像square会有蹦跶一下然后停止,反而在缓慢旋转,感觉向失重一样。嗯哼,这是因为我们并没有将重力行为与barrier关联起来,所以它会向失重一样开始旋转。

这显然不是我想要的结果,我希望square坠落碰到barrier后,barrier纹丝不动,然后square被撞的七荤八素。我们要拦住那个square

隐形的边界与碰撞效果

我们先去掉barrier的碰撞效果,将:

collision = UICollisionBehavior(items: [square,barrier]);

改为:

collision = UICollisionBehavior(items: [square]);

然后在这行下面添加另外一行代码:

collision = UICollisionBehavior(items: [square]);
collision.addBoundaryWithIdentifier("barrier", forPath: UIBezierPath(rect: barrier.frame));

这行代码的意思是在碰撞效果中添加一个隐形的边界,它的位置和形状和barrier的一样。这样就会让人产生一种错觉,认为红色的barrier成为了边界,其实真正的边界隐藏在它之后。编译运行一下,我们来看看会发生什么:

我们看到了当蓝绿色方块下降碰到红色障碍物时产生了碰撞行为,蓝绿色方块弹开并翻转落下。

从上面内容我们了解到,Swift的UIKit动力引擎非常强大,通过简短的几行代码就可以帮助我们实现惊艳的实现行为。下篇文章会向大家详细的介绍碰撞行为背后的故事。

英文原文http://www.raywenderlich.com/76147/uikit-dynamics-tutorial-swift

中文原文引自http://www.devtalking.com/articles/swift-uikit-dynamics-1/

Swift中的UIKit重力学(一)相关推荐

  1. Swift 中的关键字详解

    转载自:https://www.cnblogs.com/liYongJun0526/p/7522130.html 要学习Swift这门语言,就必须先了解Swift的关键字及对应的解释.这里就列一下在S ...

  2. 怎样在swift中创建CocoaPods

    本文由yake_099(博客)翻译自raywenderlich,作者:Joshua Greene 原文:How to Create CocoaPods with Swift 你可能对一些比较著名的开源 ...

  3. swift设置启动图不现实_如何通过装饰房屋来开始在Swift中使用增强现实

    swift设置启动图不现实 by Ranadhir Dey 由Ranadhir Dey 如何通过装饰房屋来开始在Swift中使用增强现实 (How to get started with augmen ...

  4. Swift中@IBDesignable/@IBInspectable的使用

    IB可视化属性调节视图-@IBDesignable/@IBInspectable的使用 在工程中新建一个swift类(继承UIView),将它与某个view关联起来. 在文件中添加下面的代码 //可以 ...

  5. swift_039(Swift中的KVC的使用方法)

    KVC简单介绍 KVC是OC特有的,KVC本质上是在运行时,动态向对象发送setValue:ForKey:方法,为对象的属性设置数值 因此,在使用KVC的方法之前,需要确保对象已经被正确实例化 在Sw ...

  6. [译] 探究 Swift 中的 Futures Promises

    本文讲的是[译] 探究 Swift 中的 Futures & Promises, 原文地址:Under the hood of Futures & Promises in Swift ...

  7. 27.怎样在Swift中声明typedef?

    在OC中,我们经常会用typedef关键字来声明Block,例如: /*** 通用的空闭包类型,无参数,无返回值*/ typedef void (^GofVoidBlock)(void); 在Swif ...

  8. storyboard搭建项目_swift项目第五天:swift中storyBoard Reference搭建主界面

    import UIKit/*总结:1:lazy用于懒加载,只能用var来对变量进行懒加载,有两种方式:1:lazy var first = NSArray(objects: "1" ...

  9. swift 引用其他类_浅谈swift中闭包修饰符 weak?unowned? 或什么都不用

    浅谈swift中闭包修饰符 weak?unowned? 或什么都不用 平常的开发中,clourse是我们iOSr绕不过去的坎儿. 苹果本身也很重视闭包,像之前的一些老的target-action类型的 ...

最新文章

  1. Markdown here 离线下载安装
  2. python之⾯向对象基础
  3. 贾扬清出任阿里巴巴开源技术委员会负责人
  4. Python安装第三方库太慢?配置好这个速度飞起
  5. DeepLink用法及源码解析
  6. 方法的重载与重写_我们不一样,不一样,重写与重载
  7. python为什么没有数据类型_python3 数据类型
  8. python中类的构成_Python中类型关系和继承关系实例详解
  9. JinlinOJ 通化邀请赛 E.GCD and LCM 最大公约数最小公倍数 关系
  10. NLP论文中出现的名词解释(不断更新)
  11. 运筹学考题汇总(填空题+计算题)带答案
  12. android ios9 rom,安卓党也能用上IOS9了 奇兔刷机首发24款机型仿IOS9 ROM
  13. 带农历万年历C语言程序,c语言万年历程序代码
  14. 91.(leaflet篇)leaflet态势标绘-进攻方向绘制
  15. SpringBoot实现Excel、Word转换为PDF
  16. 2013计算机学科排名,2013年世界大学学科排名 计算机科学.pdf
  17. 微信小程序搜索关键词高亮效果(转)
  18. 使用单片机的串口蓝牙通信写的接收SBUF里的数据,并进行发送执行命令,显示在数码管上,波特率9600
  19. 单片机软件延时的时间计算
  20. 你的用户珍贵么?杀鸡吃肉和养鸡吃蛋的选择……

热门文章

  1. golang字符串拼接方式
  2. 【浏览器】1022- 47 张图带你走进浏览器的世界!
  3. DNS解析出现错误故障解决
  4. ios开发 c语言打包.a文件,【转】IOS静态库a文件制作流程
  5. 大通流TVS管和ESD静电二极管的区别
  6. 计算机之父 匈牙利“唯一的天才” 冯·诺依曼
  7. Redis 使用场景
  8. 鸿图霸业nbsp;谁与争锋
  9. Android小代码
  10. 我司何晓磊续签立命馆大学的客座研究员