发布于 2014-11-01 03:54:45 | 437 次阅读 | 评论: 0 | 来源: 网友投递
Swift编程语言
SWIFT,苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C*共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序。
本文为大家讲解的是Swift实现表格视图动画教程,在这个表格视图动画的教程中,你将使用Swift增强一个已有应用程序,来旋转你滚动表格的卡片。在这个过程中,你将学到如何在UIKit中使用变换,和如何以微秒的方式使用它们,来防止你的用户在屏幕中同时出现的大量事件中无所是从。你也会得到一些建议,它们是关于如何组织你的代码使他们分工明确以及如何是你的视图控制器变得简洁。
下载开始项目然后在Xcode 6中打开它。你将找到一个简单的storyboard项目,包含UITableViewController的子类(MainViewController)和一个显示团队成员的自定义UITableViewCell (CardTableViewCell)。你也将看到一个叫做Member的model类,包含了团队成员的所有信息,并且它知道如何从存储在本地的JSON文件中获取信息。
生成并在模拟器中运行项目;你将看到如下所示:
完美的设计
该应用程序是一个好的开始,但它还可以做得更好。那将是你需要做的;你将使用一些Core Animation技巧来给你的卡片加动画。
你将由创建一个超级简单的淡入动画辅助类来开始接触基本的应用程序结构。转到FileNewFile…选择类型iOSSourceSwift File来创建一个空的Swift文件。点击Next,把文件命名为TipInCellAnimator.swift,然后点击Create。
把文件内容替换如下:
这个简单的类提供了一个方法,接收一个卡片参数,获取它的contentView然后设置图层的不透明度初始值为0.1。然后在1.4秒内,闭包(closure)表达式中的代码慢慢将图层的不透明度设回1.0。
注:Swift中的闭包(closure)是可以获取外部的变量一个代码块。例如,{ }是一个简单的闭包。使用func关键字声明的函数是named closures的例子。Swift里在其他函数中定义函数甚至是完全合法的。
如果你给函数传参时闭包是最后一个参数,则你可以使用特殊的trailing closure语法,把闭包移动到函数调用之外。你可以在UIView.animateWithDuration()的调用中看到这种情况。
现在你已经有了动画的代码,你需要表格视图控制器在卡片出现时触发这个新的动画。
要触发你的动画,打开MainViewController.swift然后添加如下方法到类中:
本方法在UITableViewDelegate协议中声明,它会在卡片被显示在屏幕前调用。它在每个卡片出现时调用了TipInCellAnimator的类方法animate()来触发这个动画。
生成并运行你的应用程序。滚动卡片来看卡片慢慢的淡入:
现在是时候让应用程序加入一些旋转动画来显得更酷炫了。这部分和淡入动画使用的是同种方式,除非你指定了开始和结束的变换。
打开TipInCellAnimator.swift,替换它的内容如下:
这次的动画很快(0.4秒),淡入得更微秒一些,现在你得到了一个很好的旋转效果。上述动画的关键在于定义了startTransform的矩阵,然后让卡片变换回它原来的身份。让我们深入看一下它是怎么做到的:
注意你是如何像下图所示一步一个脚印的建立最终的变换的:
建立变换产生预期的效果
注:任意连续的变换最终可以用一个矩阵)表示。如果你在学校里学过矩阵数学,你可以认出来这是矩阵乘法。每一步相乘一个新的变换,直到结束得到你最终的矩阵。
你也将注意到你是在变换卡片的子视图,而不是卡片本身。旋转实际的卡片会导致它的一部分覆盖到它上方和下方,这将导致一些奇怪的视觉效果,例如闪烁和被裁剪。卡片的contentView包含所有它的组成部分。
不是所有的属性支持动画;Core Animation Programming Guide 提供了支持动画的属性列表供你参考。
生成并运行你的应用程序。查看卡片出现时是如何倾斜的进入视图的!
本教程的Objective-C原版中只在开始处计算了变换一次。在上述的代码版本中,它每次调用animate()计算一次。如何在Swift中像原版那样做?
一种方法是通过调用闭包计算一个不变的存储属性。替换TipInCellAnimator.swift的内容如下:
注意生成startTransform的代码现在在它自己的存储属性TipInCellAnimatorStartTransform中。与其定义这个属性和调用getter来每一次创建变换,不如把它的默认属性分配给一个闭包函数,然后在闭包函数后面添加一对括号。括号强制立即调用闭包函数赋值返回值给属性。这个初始化风格在Apple的Swift书中initialization章节中讨论过。更多内容请查看“Setting a Default Property Value with a Closure or Function”。
注:如果把TipInCellAnimatorStartTransform设为一个TipInCellAnimator的类属性就更好了。但在撰写本文时,Swift的类属性尚未实现。
虽然动画效果是整洁的,但你也要有节制地使用它。如果你曾经经历了有过度的声音效果和动画效果的演示文稿,那么你就应该知道效果过度的感觉!
在你的项目中,你只想要动画在卡片出现时运行一次 — 当它从底部滚动进入屏幕时。当你向顶部滚动时,卡片应该滚动而没有动画。
你需要一种方法来追踪哪些卡片已经被显示了,他们不需要再一次的展示动画。完成它,你将需要使用Swift的Dictionary集合,它提供了快速的查找函数。
注:Set是无序的集合,唯一的key对应的值不存在重复,Array是有序的集合,它允许重复。Swift标准库当前并不包含Set类型,但它可以由Bool的(字典)Dictionary简单模拟而成。这样使用Dictionary的抽象害处是很小的,这也许也是Swift组没有在它的初始版本中加入它的原因。
Set和Dictionary的key的主要缺点在于他们不是有序的,但是你卡片的排序已经由数据源持有了,所以在这种情况下它不是一个问题。
打开MainViewController.swift,添加如下属性到类中:
这声明了一个空的字典,NSIndexPath为key,Bool为value。下一步,替换tableView(tableView:, willDisplayCell:, forRowAtIndexPath:)的实现如下:
把每次向上和向下滚动表格时每个卡片展示动画,替换为检查卡片的索引是否在字典中。如果不在,则卡片是第一次被显示;因此你运行动画并添加indexPath到你的Set中。如果它已经在Set中,你则不需要展示任何动画。
生成并运行你的项目;向上和向下滚动表格视图,你将只会看到卡片在第一次进入屏幕时有动画。
在本文中,你给标准的视图控制器添加了动画。实现细节远离了MainViewController类,放进了一个小的,集中的,动画辅助类中。保持类的职责集中,特别是视图控制器,是iOS开发中一个主要的挑战。
你可以从这里下载本教程的最终项目。
现在你已经学会了添加动画到卡片的基础内容,请尝试修改你的变换值来看看你可以达到一些什么其他效果。建议:
你可以(但可能不应该)应用到你的卡片上的疯狂旋转。看你能不能与这些相同!
在你最喜欢的应用程序中尝试和识别动画是一个很好的锻炼。甚至在本教程中的简单动画中,你也可以在这个基础的主题中创造出无数的变化。动画对用户的操作来说是一个很好的补充,例如选中卡片时翻转它,或者在展现或删除卡片时淡入或淡出它。