本文转载自:点击打开链接
本文译自:UIKit Dynamics Tutorial: Tossing Views
本文中,我们将学习如何用手势很自然的将 view 抛掷出屏幕。
可能你已经看到该技术在 Tweetbot 中的流行了。
本文非常适合中级开发者,因为对 view 抛掷操作中,使用的技术嵌套了多个效果,例如使用内置的 UIKit 框架对 view 进行旋转 (rotation)、飞离 (fly-away) 动画。
如果你之前还不了解 UIKit dynamics,也不用担心 - 本文会一步一步的引导你进行学习。
事不宜迟,我们开始抛掷 view 吧!
目录:
开始
提醒:学习中,本节是可选的,主要是针对想要从零开始的读者。有经验的 iOS 开发者可以忽略本节,直接到下一节 (已经为你准备好一个工程了)。
打开 Xcode,选择 File\New\Project…
,选择 iOS\Application\Single View Application
模板,然后点击 Next
。将工程命名为 DynamicToss
,并将 device family 设置为 iPhone。
现在选中左边的工程名称,并确保选中 Xcode 窗口顶部的 General。在 Deployment Info/Device Orientation
中,不要勾选 ‘Landscape Left’ and ‘Landscape Right’,因为这个程序只以 portrait 模式运行。
接着下载一个图片,这个图片来自gameartguppy.com:
将工程解压出来,然后将图片文件添加到工程中。
接着,打开 Main.storyboard
,并添加一个 image view 控件,相关值设置为:(X=33, Y=137, Width=254, Height=172, Image=goldfish_feature.jpg)。现在屏幕上的看起来应该是这样的:
接着,拖两个 UIView 到 view controller 中,这两个 UIView 用来对手势进行跟踪。按照下面的值进行设置:
- View 1: (X=156, Y=219, Width=8, Height=8, Background=red)
- View 2: (X=80, Y=420, Width=8, Height=8. Background=blue)
至此,view 看起来应该是这样的:
将下面的私有属性添加到 RWTViewController.m
中:
|
|
选中 Main.storyboard
文件,并右键单击 View Controller
。拖拽住出现的 blueSquare
outlet,将其与蓝色正方形 view 连接上:这个动作会将属性连接至 view 对象。
同样也把红色正方形连接好,最后是名字位 image
的属性。现在 3 个 view 属性应该已经连接好了,看起来如下图所示:
红色和蓝色的正方形代表 UIDynamics 物理引擎对图像进行动画效果的点。
蓝色正方形简单的代表触摸的开始,例如,你的手指与屏幕第一次交互时的位置。红色的正方形用来跟踪手指的移动。
你需要对 UIDynamics 框架进行配置,以使得当移动点时,图片也跟着串联的方式做物理动画。
现在还有一件事件需要做 - 为 view 配置一个手势识别。打开 RWTViewController.m
,将下面的方法添加到文件中:
|
|
我们将要添加一个手势识别,来检测拖拽,也称为平移 (panning),当事件发生时,会调用上面这个方法。目前,这个方法简单的显示出手指在两个不同坐标系空间 (view 和 image view) 的位置。
为了添加手势识别,打开 Main.storyboard
,并拖一个 Pan Gesture Recognizer
到 view 中。然后从 Pan Gesture Recognizer
control-drag 到我们的 View Controller
,并将其连接到 handleAttachmentGesture:
方法上。
现在编译并运行程序。在屏幕上轻扫或者拖动,可以在控制台看到类似如下信息:
|
|
非常棒!现在已经完成了基本的 UI 配置 - 接下来是时候开始 dynamic了!
UIDynamicAnimator 和 UIAttachmentBehavior
提醒:如果你忽略了上一章节的内容,请先从这里下载为你准备好的工程。
首先我们要做的事情就是让 image view 跟随我们的拖拽一起移动。这将通过 UIKit Dynamics中的 UIAttachmentBehavior
来实现。
打开 RWTViewController.m
,并将下面的代码添加到 viewDidLoad
中,位于 [super viewDidLoad]
下方:
|
|
上面的代码将配置一个 UIDynamicAnimator
,这是 UIKit 中的一个引擎,用于支持最基本的物理动画效果。参照 self.view
定义了 animator 的坐标系。
通过给 animator 添加行为 (behaviors),可以让你做一些事情,例如具有重力效果的进行 attaching view、pushing view等。
下面我们开始给 animator 添加第一个行为:UIAttachmentBehavior
- 使得 image view 跟着手指的手势进行移动。
为了完成这样的效果,将下面的代码添加到 handleAttachmentGesture:
中,位于 case UIGestureRecognizerStateBegan
的两个 NSLog 语句下方:
|
|
我们来细看一下上述代码的作用:
- 首先移除 animator 中所有已有的行为。
- 创建一个
UIAttachmentBehavior
,将用户 tap image view 上的点连接到一个锚点 (anchor point) 上 (实际上这恰好是完全相同的点)。随后,对锚点的改变,会引发 image view 的移动。
将锚点连接到一个 view 上,就像安装了一个无形的拉杆:将锚点连接到 view 中固定的位置上。
- 更新红色正方形,表示出锚点,而蓝色正方形则表示连接到 image view 内部的点 (现在他们都是一样的)。
- 将这个行为添加到 animator 中,使其具有效果。
接下来需要告诉锚点跟住你的手指。为此,将下面的代码添加到 handleAttachmentGesture:
,位于 fefault
(与手势变化一起改变):
|
|
上面的代码将锚点和红色正方形设置位手指当前的位置。当手指移动时,手势识别会调用这个方法,以更新相应的锚点信息。另外,animator 也会自动的按照这个锚点对 view 进行更新。
编译并运行程序,现在可以拖拽 view 了:
当完成拖拽,要是能降 view 还原到之前的位置就更好了。为此,将下面的方法添加到文件中:
|
|
然后在方法 handleAttachmentGesture:
中调用这个方法,具体位于 UIGestureRecognizerStateEnded
:
|
|
编译并运行程序,现在完成对图片的拖拽之后,该图片应该能够回到最开始的位置。
UIPushBehavior
接下来,我们要完成这样的效果:当停止拖拽时,将 view 从屏幕中移除。那么当手势释放时,需要给这个 view 赋予动量,让它能继续沿着轨迹前行。为此,需要使用 UIPushBehavior
。
首先,定义两个常量,将其添加到文件头部:
|
|
为了让 view 持续移动,其中 ThrowingThreshold
表示 view 必须移动 (相对于立即返回到原点) 多快才行。ThrowingVelocityPadding
是一个神奇的常量,它将对抛掷 view 的快慢产生影响 (这需要反复试验得出结果)。
最后,在 handleAttachmentGesture:
中,用下面的代码替换 UIGestureRecognizerStateEnded
case:
|
|
我们来看看代码都做了些什么:
- 获得手势的拖拽速度。
利用速度和勾股定理 (Pythagorean theorem),计算出速度的幅度 - 也就是由 x 方向上的速度和 y 方向上的速度构成的三角形斜边。
要想理解背后的理论,请看 Trigonometry for Game Programming tutorial。
- 假设手势的幅度超过了最低阀值,那么就配置一个 push behavior。
push behavior 可以是持续性的,或者瞬间的应用到某个对象中。这里,我们需要给 image 一个瞬间的 push 行为。
我们希望 image 的移动方向是由 x 和 y 轴上的速度转换为一个矢量决定的。最后,将 push 行为添加到 animator 上。
- 在这里给 image 添加一些旋转效果,让图片飞离屏幕。这里有复杂的数学知识介绍。
其中的一些效果取决于发起手势操作的手指与边缘的距离。
在此处,设置不同的值,观察它们移动的效果,然后使用最好的那个值即可。
- 指定时间间隔之后,以动画的形式将 imamge 还原到最初状态。
编译并运行程序,现在你应该可以用令人愉快的方式将 view 抛出屏幕!
何去何从?
这里可以下载到本文的最终示例工程。
恭喜你,你现在已经学会如何做一些有趣的 UIKit dynamic 动画了 - 让程序的界面效果非常甜蜜。
如果你想要学习更多关于 UIKit Dynamics 的知识,可以阅读 iOS 7 for Tutorials 中两章 UIKit Dynamics 内容。