Flash-IOS-应用秘籍-全-

Flash IOS 应用秘籍(全)

原文:zh.annas-archive.org/md5/9b329a16897637011cf7e4717543e930

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

iPhone 是一场革命。几乎每天,都有人发现它的创新用途,并在 App Store 中找到展示其作品的完美平台。它的成功使应用程序变得酷炫,并帮助将内容交付从浏览器中转移出来。Adobe 对此变化做出了反应,重新定位了 Flash 平台,并提供了从 Flash Professional 直接创建和发布原生 iOS 应用程序的所需工具。

《Flash iOS 应用程序食谱》是我自 AIR for iOS 诞生以来工作经验的结晶。我特别关注了基础知识,专注于许多新手觉得令人畏惧的底层工作。对于那些已经牢固掌握基础的人,还有很多东西可以学习,从与设备众多传感器的协作,到利用硬件加速最大化图形性能。

到这本书的结尾,你将掌握使用 Flash 编写和分发你自己的原生 iOS 应用程序所需的技能。我希望你能利用在这里学到的知识,创建出适合你即将成为其中一员的才华横溢且鼓舞人心的社区的美观应用。

本书涵盖内容

第一章,iOS 应用程序开发入门,将引导你通过成为注册 iOS 开发者的通常令人畏惧的过程。到本章结束时,你将拥有从 Flash Professional 发布原生 iOS 应用程序所需的必要文件。

第二章,使用 Flash 构建 iOS 应用程序,涵盖了配置 Flash Professional 并从其中发布原生 iOS 应用程序所需的一切。你还将学习如何安装应用程序在 iPhone 上进行测试。

第三章,编写你的第一个应用程序,将带你通过使用 Flash Professional 和适量的 ActionScript 构建和测试你的第一个 iOS 应用程序的步骤。还将探讨一些开发最佳实践。

第四章,将 Flash 项目移植到 iOS,将帮助你正确开始将桌面 Flash 项目转换为 iOS 的过程。你将学习如何在移动限制内工作,以及如何避免常常会削弱应用程序性能的常见陷阱。

第五章,多点触控和手势支持,将向你展示如何充分利用触摸屏。你将学习如何检测多个触摸点,并使用 ActionScript 对滑动、平移和捏合手势做出响应。

第六章,图形和硬件加速,为经常引起挫折的一个领域提供了宝贵的食谱。我们将介绍大幅提升应用程序帧率的强大技术,并学习 Flash 渲染管道的复杂性。有了这些知识,你将能够将你自己的作品中的图形性能推向极限!

第七章,处理文本和虚拟键盘,将帮助你通过探索 iOS 的虚拟键盘和原生文本输入控件的支持来适应没有物理键的生活。还将花费时间介绍 Flash 自己的文本引擎的相关功能。

第八章,屏幕分辨率和方向变化,详细介绍了如何在任何 iOS 设备上渲染内容,无论其屏幕分辨率或物理方向如何。还可以找到对高分辨率 Retina 显示器的支持,以及如何设置一个可以针对 iPhone、iPad 和 iPod touch 的通用应用程序的说明。

第九章,地理位置和加速度计 API,涵盖了利用设备 GPS 传感器和加速度计的食谱。学习如何制作位置感知的应用程序,响应物理方向的变化,以及检测震动。

第十章,相机和麦克风支持,将帮助你掌握 iOS 设备中内置的两种最受欢迎的传感器。通过相机,你将学习如何拍摄视频、捕捉照片以及访问图像库。本章将以介绍如何使用麦克风录制和播放音频结束。

第十一章,渲染网页,专注于网页内容的展示——无论是在你的应用程序内部直接展示,还是通过启动 Safari。它还涵盖了如何动态生成 HTML,浏览历史记录,以及捕获当前页面的快照。

第十二章,处理视频和音频,探讨了针对 iOS 时可用的大量 A/V 选项。除了利用 Flash 流行的 FLV 视频格式外,本章还将详细介绍如何利用硬件加速的 H.264 视频以实现最佳质量的高清播放。

第十三章,连接性、持久性和 URI 方案,解决了一些悬而未决的问题,从互联网连接开始。接下来,讨论了文件系统访问——这是本书中许多食谱所涉及的话题。本章的最后部分将介绍使用 URI 方案启动各种系统应用程序,包括邮件、YouTube、App Store 和地图。

第十四章,使用本地扩展和 ADT,详细介绍了如何使用命令行来利用 Flash Professional 直接未提供的 AIR for iOS 功能。具体来说,你将学习如何使用本地扩展来访问从 AIR SDK 中缺失的 iOS 特定 API。这一章节在书中没有出现,但可以通过以下链接免费下载:www.packtpub.com/sites/default/files/downloads/1383_Chapter14.pdf

第十五章,ActionScript 优化,涵盖了可以应用于你项目 ActionScript 的各种宝贵的优化方法。你将看到即使是微小的改变也能提高应用程序的执行速度或改善其内存使用。这一章节在书中没有出现,但可以通过以下链接免费下载:www.packtpub.com/sites/default/files/downloads/1383_Chapter15.pdf

附录 A,Flash Professional CS5.5 特定食谱,列出了本书中需要 Flash Professional CS5.5 和 AIR 2.6 或更高版本的食谱。这个附录在书中没有出现,但可以通过以下链接免费下载:www.packtpub.com/sites/default/files/downloads/1383_AppendixA.pdf

附录 B,ActionScript 优化度量,提供了第十五章中详细描述的各种优化的结果。这个附录在书中没有出现,但可以通过以下链接免费下载:www.packtpub.com/sites/default/files/downloads/1383_AppendixB.pdf

你需要为此书准备的内容

本书是为 Adobe Flash Professional CS5 或 CS5.5 的用户编写的。

大多数涵盖的食谱都与 CS5 和 CS5.5 兼容。然而,有些是特定于 CS5.5 的,需要 Adobe AIR SDK 的最新版本。

你还需要一部 iPhone、iPad 或 iPod touch。Flash Professional CS5.5 支持开发 iOS 4 或更高版本的移动应用,而 CS5 则提供了对运行 iOS 3 的旧设备的支持。

你可以使用 Mac OS X 的 Flash Professional 或 Microsoft Windows 来构建本机 iOS 应用。

这本书面向的对象

本书适用于具备 ActionScript 3.0 和 Flash Professional 实际操作知识的初学者和经验丰富的开发者。如果你想要利用现有的 Flash 技能来编写 iOS 应用,那么这本书将向你展示如何从基础知识开始。那些已经熟悉这些知识的用户可以直接跳到提供的更高级主题。

术语约定

在这本书中,您将找到多种文本样式,用于区分不同类型的信息。以下是一些这些样式的示例,以及它们含义的解释。

使用 Flash Professional 开发 iOS 应用通常被称为 AIR for iOS。然而,Flash Professional CS5 使用的是 iPhone OS 这个术语。本书将几乎全程使用 AIR for iOS 这个术语。

文本中的代码词如下所示:“将默认位置设置为C:\OpenSSL-Win32."

代码块如下设置:

public function Main() {
application = NativeApplication.nativeApplication;
application.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
application.addEventListener(Event.ACTIVATE, activate);
application.addEventListener(Event.DEACTIVATE, deactivate);
}

当我们希望您注意代码块中的特定部分时,相关的行或项目将以粗体显示:

public function Main() {
 application = NativeApplication.nativeApplication;
application.systemIdleMode = SystemIdleMode.KEEP_AWAKE; 
application.addEventListener(Event.ACTIVATE, activate);
application.addEventListener(Event.DEACTIVATE, deactivate);
}

任何命令行输入或输出都如下所示:

openssl genrsa -out mykey.key 2048 

新术语重要词汇以粗体显示。您在屏幕上看到的单词,例如在菜单或对话框中,在文本中如下所示:“向下滚动页面,直到您看到如下截图所示的加入 iOS 开发者计划链接”。

注意

警告或重要提示以如下框的形式出现。

小贴士

小技巧和窍门如下所示。

读者反馈

我们欢迎读者的反馈。请告诉我们您对这本书的看法——您喜欢什么或可能不喜欢什么。读者反馈对我们开发您真正能从中获得最大收益的标题非常重要。

要向我们发送一般反馈,只需发送一封电子邮件到<feedback@packtpub.com>,并在邮件的主题中提及书名。

如果您在某个主题上具有专业知识,并且您对撰写或为书籍做出贡献感兴趣,请参阅我们的作者指南www.packtpub.com/authors

客户支持

既然您已经自豪地拥有了一本 Packt 图书,我们有许多事情可以帮助您从购买中获得最大收益。

下载示例代码

您可以从您在www.PacktPub.com的账户下载您购买的所有 Packt 图书的示例代码文件。如果您在其他地方购买了这本书,您可以访问www.PacktPub.com/support并注册,以便将文件直接通过电子邮件发送给您。

错误清单

尽管我们已经尽最大努力确保内容的准确性,但错误仍然可能发生。如果你在我们的书中发现错误——可能是文本或代码中的错误——如果你能向我们报告这个问题,我们将不胜感激。这样做可以帮助其他读者避免挫败感,并帮助我们改进本书的后续版本。如果你发现任何勘误,请通过访问www.packtpub.com/support,选择你的书籍,点击勘误提交表单链接,并输入你的勘误详情来报告。一旦你的勘误得到验证,你的提交将被接受,勘误将被上传到我们的网站,或添加到该标题的勘误部分下的现有勘误列表中。任何现有的勘误都可以通过从www.packtpub.com/support选择你的标题来查看。

盗版

在互联网上对版权材料的盗版是所有媒体中持续存在的问题。在 Packt,我们非常重视我们版权和许可证的保护。如果你在网上发现我们作品的任何非法副本,无论形式如何,请立即提供位置地址或网站名称,以便我们可以寻求补救措施。

请通过<copyright@packtpub.com>与我们联系,并提供涉嫌盗版材料的链接。

我们感谢你在保护我们的作者和我们提供有价值内容的能力方面提供的帮助。

问题

如果你在本书的任何方面遇到问题,可以通过<questions@packtpub.com>联系我们,我们会尽力解决。

第一章. 开始 iOS 应用程序开发

在本章中,我们将涵盖:

  • 加入 iOS 开发者计划

  • 访问 iOS 配置文件门户

  • 使用 Windows 生成证书签名请求

  • 使用 Mac OS X 生成证书签名请求

  • 获取你的开发证书

  • 使用 Windows 创建 P12 证书

  • 使用 Mac OS X 创建 P12 证书

  • 注册设备

  • 创建 App ID

  • 创建开发配置文件

  • 在你的设备上安装配置文件

简介

在编写 iOS 应用程序时,为了在真实设备上进行测试,创建和管理某些文件是必要的。所需的确切文件取决于你目前是在开发还是准备分发。我们将主要关注开发。

到本章结束时,你将创建一个P12 证书文件和一个开发配置文件,这两个文件都是如果你想要充分利用本书中的菜谱所必需的。在这个过程中,你将了解各种工具的细节,包括 Apple 的iOS 配置文件门户,你将在作为 iOS 开发者的时间里广泛使用它。

如果一开始所有内容都不完全明白,请不要担心。如果你遵循每个菜谱中详细说明的步骤,你最终将获得完成本书剩余部分所需的工作文件。

加入 iOS 开发者计划

注册为 Apple 开发者并加入 iOS 开发者计划是任何希望编写 iOS 应用程序的人的先决条件。

虽然你可以免费报名参加一个项目,但如果你想将你的应用程序安装到设备上并在App Store中分发,你需要支付 99 美元的年度费用以加入标准项目。

使用 iOS SDK 进行开发的开发者可以选择免费项目,并使用 Apple 官方开发工具提供的 iOS 模拟器测试他们的应用程序。不幸的是,使用Flash Professional构建的本地 iOS 应用程序在模拟器上无法运行。因此,如果你想完全测试本书中提供的示例,你需要在 iOS 设备上安装它们。

注意

在 Flash Professional 中,你可以使用AIR 调试启动器(ADL)在桌面上测试你的应用程序;然而,由于不支持 iOS 设备功能,这限制了 ADL 的实用性。

让我们看看注册所需的步骤。

准备工作

注册发生在 Apple 开发者网站上。如果你不使用 Apple 的Safari浏览器,那么建议你下载并安装它,因为有时在其他浏览器上尝试使用网站上的某些区域时会报告问题。

Safari 是预安装在 Mac OS X 中的默认网络浏览器。使用 Windows 且尚未安装 Safari 的用户可以从www.apple.com/safari/download下载它。

如果你已经安装了 Safari,请确保你有最新版本。

小贴士

在注册过程中,您可以采取几种不同的路径,一旦完成注册,可能无法更改您的一些选择。在提交注册详情和购买开发者计划之前,请仔细思考。您可能首先想通读整个配方,以确保您完全了解所有可用的选项。

如何操作...

  1. 访问苹果开发者网站developer.apple.com。滚动页面,直到您看到如下截图所示的加入 iOS 开发者计划链接:如何操作...

    小贴士

    注意,苹果定期对其各种开发者网站进行修改。因此,本章截图中的项目位置可能在您阅读时略有不同。本章中描述的链接也可能会有所变化。

  2. 点击链接。您将被带到iOS 开发者计划页面,在该页面的顶部您将找到一个立即注册按钮。

  3. 点击立即注册按钮,进入注册苹果开发者计划页面。页面列出了注册所需的三个主要步骤。它们是:

    • 注册为苹果开发者

    • 选择您的计划

    • 完成您的购买

  4. 页面底部有一个继续按钮,它将开始引导您完成每个步骤。请点击它。

注意

继续按钮旁边,您将找到概述注册技术要求的文本。这指的是使用苹果 iOS SDK 的开发者,不适用于使用 Flash Professional 的开发者。请忽略它。

注册为苹果开发者

  1. 您是新手还是已注册的苹果开发者?页面,您将能够注册为新的苹果开发者。在新苹果开发者栏中,点击如下截图所示的我需要为苹果开发者计划创建新的账户和 Apple ID单选按钮:注册为苹果开发者

    注意

    如果您目前有一个 Apple ID,则点击栏中的第二个单选按钮。如果您是现有的苹果开发者,则应从现有苹果开发者栏中选择相应的单选按钮。

  2. 点击继续按钮,进入您是作为个人还是公司注册?页面。

    提供了两种选项。您可以个人注册或代表公司注册。

    注意

    要作为公司注册,您需要向苹果提供商业文件,并拥有将您的公司绑定到注册过程中向您展示的法律协议的法律权限。

  3. 根据您的需求,点击页面底部的个人公司按钮。

  4. 现在通过执行以下任务来完成您的个人资料:

    • 指定一个期望的 Apple ID 和密码。

    • 设置一些可以用来验证您身份的安全信息。

    • 提交您的个人信息。

    注意

    在提交您的联系信息时,您指定的名称将作为您在 App Store 上分发的任何应用的“卖家”显示。

    不要在名称字段中尝试添加别名或组织名称。这很可能会导致您的 Apple 开发者注册失败,或者当 Apple 最终注意到错误时,您的账户将被暂停。

    如果您希望公司名称作为“卖家”显示,那么请作为公司注册,并向 Apple 提供相关的法律文件以验证您的身份。

    如果您作为个人进行注册,请在公司/组织字段中输入您的姓名和姓氏。

  5. 仔细阅读显示页面上的信息,并在填写完表格后,点击继续按钮,这将带您到完成您的专业资料页面。

  6. 对于“您使用哪些 Apple 平台进行开发?”字段,请勾选iOS复选框。这将显示必须填写的一些附加字段列表。

  7. 当您到达请选择您的应用程序的主要类别字段时,请确保您点击商业应用程序单选按钮。

    注意

    通过选择开发商业应用程序,您在分发应用程序之前必须提供您的银行详细信息;然而,在注册过程中不会要求您提供此信息。如果您计划仅分发免费应用程序,则可以选中免费应用程序单选按钮,无需提供银行详细信息。此选项适用于本书中的示例;然而,如果您计划在某个时候销售应用程序,则请坚持选择商业应用程序选项。

  8. 一旦您已填写表单中所有字段的答案,请点击页面底部的继续按钮。

  9. 仔细阅读显示的注册 Apple 开发者协议。通过勾选复选框并点击页面底部的我同意按钮来确认您已阅读。

  10. 将验证码发送到您的电子邮件地址。获取该代码并将其输入到输入发送到您的电子邮件的验证码页面上的文本字段中。点击继续

    将发送第二封电子邮件以确认您现在已成为注册的 Apple 开发者。

注意

邮件还将包含您选择的 Apple ID。请妥善保管此邮件,因为您将需要您的 Apple ID(以及您的密码)来访问 Apple 开发者网站上的某些资源。

选择您的计划

在您的网页浏览器中,您将被带到输入您的账单信息以进行身份验证页面。

  1. 请将您的姓名和姓氏输入得与您的信用卡上显示的完全一致。同时提供您的信用卡账单地址。

  2. 点击页面底部的继续按钮。

    注意

    在这一点上,你的信用卡详情将被用于身份验证。你不会被要求提供信用卡号码,也不会被收费。

  3. 选择你的计划页面将出现。如以下截图所示,勾选iOS 开发者计划复选框,然后点击页面底部的继续按钮:选择你的计划

  4. 下一页将允许你查看你的注册信息。请确认你已经选择了iOS 开发者计划,并且你的个人详情和账单信息是正确的。如果任何信息有误,请点击页面底部的返回按钮,并进行任何必要的修改。

  5. 点击继续提交你的注册信息到苹果。

  6. 程序许可协议页面将出现。通过勾选复选框确认你已经阅读过,然后点击页面底部的我同意按钮。

完成购买

  1. 将出现一个购买页面。点击添加到购物车继续到你所在国家的在线商店购买你的计划。

  2. 将打开一个新的浏览器窗口,并将你带到苹果商店。确认你的 iOS 开发者计划已放入购物车,然后点击页面右侧的现在结账按钮购买该项目。

  3. 一封激活邮件将在 24 小时内发送给你。当你收到时,请按照指示激活你的 iOS 开发者计划。

它是如何工作的...

注册为苹果开发者并激活你的开发者计划使你能够通过苹果的iOS 开发者中心网站访问 iOS 配置文件门户。iOS 配置文件门户将引导你完成测试和分发应用到 iOS 设备的必要步骤,并将在本章中用到。

你将使用你设置的 Apple ID 和密码登录到iOS 开发者中心

更多内容...

以下是一些额外的信息值得考虑。

与多个团队成员协作

如果你选择以公司名义注册,那么你可以添加额外的团队成员到你的账户中,他们可以访问 iOS 开发者计划资源。这将允许,例如,其他团队成员生成和下载构建和部署应用到 iOS 设备所需的开发者文件。

如果你以个人名义注册,那么你将是唯一有权访问计划资源的开发者。生成所有必需的开发者文件和管理测试设备列表将是你的责任。

iOS SDK、工具和文档

iOS 开发者中心包含丰富的资源。虽然可用的文档和工具旨在针对使用 iOS SDK 的开发者,但你也会发现一些在用 Flash Professional 构建自己的应用时会有帮助的工具。

一个重要的起始文档是iOS 用户界面指南。它描述了帮助您创建感觉像是专门为 iOS 设计的应用的指南和原则。

此外,如果您计划在 App Store 上发布您的应用,请阅读developer.apple.com/appstore/guidelines.html上的App Store 审查指南

如果您在 Mac OS X 上开发,您可能还想下载开发者工具集。虽然本书不会涵盖 Apple 的开发者工具,但请花些时间探索包含在捆绑包中的Instruments应用程序,它提供了强大的分析和调试功能,可以帮助您微调您的应用。

一个好的开始是从iOS 开发者指南的“仪器用户指南”介绍开始。

访问 iOS 配置文件门户

iOS 配置文件门户是一个在线工具,旨在指导您完成在 iOS 设备上测试您的应用并为其在 App Store 上分发做准备所需的步骤。

这就是您将创建和下载用于使用 Flash Professional 构建应用的开发者文件的地方。

让我们一步步了解访问它的步骤。

准备工作

您需要一个 Apple ID 来注册 iOS 开发者计划。

如果您还没有这样做,请按照加入 iOS 开发者计划食谱中详细说明的步骤进行操作。

如何操作...

  1. 访问iOS Dev Center网站。在页面顶部点击登录按钮。

  2. 使用您的 Apple ID 登录页面,将您的 Apple ID 和密码输入到文本框中。点击登录按钮。

  3. 如果操作成功,您将被带回到 iOS Dev Center 的主页,在那里您现在可以访问包括 iOS 配置文件门户在内的您的开发者计划的主要区域。这些链接可以在主页右上角的iOS 开发者计划标题下方找到。

  4. 点击iOS 配置文件门户链接以访问门户的主页,如下面的截图所示:

如何操作...

它是如何工作的...

配置文件门户为您提供了开发和分发您的 iOS 应用所需的资源。

对于本书中的示例,您只需关注开发即可。以下是要完成此操作所需的四个主要步骤:

  • 获取开发证书

  • 注册 iOS 设备进行测试

  • 为您的应用创建唯一的 ID

  • 创建和下载开发配置文件

这些步骤可以从配置门户页面左侧的链接执行,并在本章的剩余部分进行分解和介绍。

或者,苹果提供了开发配置助手,可以用来引导您完成这个过程。然而,配置助手在本书中没有涵盖。

更多...

鼓励您花时间探索配置门户,因为它对于 iOS 开发过程至关重要。

以下信息也可能有所帮助。

资源

在门户首页的右侧是资源部分,您可以在此找到指南、"如何做"视频、文档和用户论坛的链接。

如果您需要进一步了解配置步骤,"如何做"视频是理想的。在资源部分的顶部,您还可以找到程序用户指南的链接,该指南详细介绍了配置过程。

记住,网站上所有内容都将针对 Mac OS X 用户。如果您使用的是 Windows,那么部分内容可能不适用。

添加团队成员

如果您代表公司注册,那么您还可以将其他团队成员添加到您的账户中。

作为原始注册者,您有权访问所有 iOS 配置门户功能,并且可以为邀请的任何成员分配角色。您分配给个人的角色将决定他们获得的权限并规定他们可以执行的任务。

团队管理成员中心内处理,您可以从配置门户的首页访问它。只需在门户首页的中心点击立即访问成员中心链接即可。

作为个人注册的用户将无法添加团队成员,但将有权访问所有配置门户功能。

要获取团队管理的全面指南,请查看资源部分中的程序用户指南

分发

准备应用程序提交到 App Store 和分发所需的步骤在本书中没有涵盖。然而,一旦您熟悉了应用程序开发的配置过程,您会发现分发并不太不同。

在配置门户的资源部分的程序用户指南中提供了有关分发的全面文档。

技术支持

作为 iOS 开发者计划的成员,您有权获得苹果开发者技术支持团队的支持,在那里您可以从合格的苹果工程师那里获得直接的一对一帮助。

作为您的开发者计划会员,您的会员期间可免费获得两次技术支持。

然而,您应该知道,这种支持主要是针对使用 iOS SDK 的开发者。苹果工程师无法帮助有关 Flash Professional 的问题。

使用 Windows 生成证书签名请求

开发证书用于识别开发者,以便在 iOS 设备上安装和测试应用程序。没有它,您无法从 Flash Professional 发布原生 iOS 应用程序。您可以从 Apple 的 iOS 配置文件门户获取开发证书,但为此您必须首先生成证书签名请求(CSR)文件。

生成 CSR(证书签名请求)的过程取决于您选择的操作系统。

这里涵盖了 Microsoft Windows 的步骤。如果您使用的是 Mac OS X,请参阅使用 Mac OS X 生成证书签名请求配方。

准备工作

  1. CSR 文件使用OpenSSL生成,可以从www.slproweb.com/products/Win32OpenSSL.html下载和安装。您实际上需要从该网站安装两个文件。

  2. 首先,滚动到下载 Win32 OpenSSL部分,并下载Visual C++ 2008 Redistributables安装程序。简单地运行可执行文件,并按照向导完成安装过程。

  3. 接下来,下载并运行Win32 OpenSSL v1.0.0e Light安装程序。向导将询问您选择 OpenSSL 应安装的位置。请保持默认位置设置为C:\OpenSSL-Win32。另外,当提示时,指示安装程序将 OpenSSL 的 DLLs 复制到Windows 系统目录

如何操作...

  1. 使用管理员权限打开命令提示符窗口。

    注意

    如何以管理员权限运行命令会话取决于您的操作系统选择。

    如果您是 Windows 7 或 Vista 用户,请点击开始按钮,在搜索框中键入cmd。但是,而不仅仅是按Enter,您应该按Ctrl + Shift + Enter。将出现一个对话框询问您是否希望程序对您的计算机进行更改。点击按钮。

    如果您使用的是 Windows XP,请确保您已使用管理员账户登录。点击 Windows 开始按钮,然后选择运行。在运行对话框中,键入cmd并按Enter

  2. 从命令提示符移动到 OpenSSL 的bin文件夹,输入以下命令:

    cd C:\OpenSSL-Win32\bin 
    
    
  3. 现在通过输入以下内容创建私钥:

    set RANDFILE=.rnd 
    
    
    • 紧接着:
    openssl genrsa -out mykey.key 2048 
    
    
  4. 文件mykey.key将被输出到 OpenSSL 的bin文件夹。

    注意

    即使在命令行上报告错误后,OpenSSL 可能仍然会输出一个文件。如果您发现错误,请检查您的语法,并再次运行命令,因为您的文件可能不可用。

  5. 使用您的私钥,您现在可以创建 CSR 文件。为此,需要以下格式的命令:

openssl req -new -key mykey.key -out CertificateSigningRequest.certSigningRequest -subj "/emailAddress=yourAddress@example.com, CN=John Doe, C=US" 

  • 在将前面的命令输入到命令行时,您需要做一些更改。将电子邮件地址和证书名称替换为您在 iOS 开发者计划中注册的相同电子邮件地址和名称。另外,如果您居住在美国以外,您需要编辑国家代码。

注意

在创建 CSR 时可以使用的国家代码列表可以在 DigiCert 网站上找到,网址为www.digicert.com/ssl-certificate-country-codes.htm

  • 将创建一个名为CertificateSigningRequest.certSigningRequest的 CSR 文件,并将其输出到bin文件夹。

它是如何工作的...

您现在有一个包含您的个人信息(您的姓名、电子邮件地址和所在国家)的 CSR 文件,它将被用来从 Apple 请求开发证书。

当 CSR 文件创建时,OpenSSL 也创建了一个公钥和私钥。公钥包含在 CSR 文件中,而私钥用于签名请求。

不要删除您的 CSR 文件或私钥,因为它们在本章的后续部分都将被需要。

参见

  • 获取您的开发证书

使用 Mac OS X 生成证书签名请求

开发证书用于识别开发者,以便在 iOS 设备上安装和测试应用程序。没有它,您无法从 Flash Professional 发布原生 iOS 应用程序。您可以从 Apple 的 iOS 配置文件门户获取开发证书,但为此您必须首先生成一个证书签名请求(CSR)文件。

生成 CSR 的过程取决于您选择的操作系统。

这里介绍了 Mac OS X 的步骤。如果您使用的是 Microsoft Windows,请参阅使用 Windows 生成证书签名请求配方。

如何操作...

按照以下步骤生成 CSR:

  1. Applications/Utilities文件夹中启动钥匙串访问应用程序。

  2. 打开之后,从钥匙串访问(Cmd *+ ,)菜单中选择偏好设置

  3. 偏好设置对话框中,点击证书选项卡,并确保在线证书状态协议(OCSP)证书吊销列表(CRL)都设置为关闭。关闭对话框。

  4. 钥匙串访问菜单中选择证书助手 | 从证书颁发机构请求证书

  5. 证书助手对话框中,您可以输入您的个人信息。在提供的文本字段中,输入您在 iOS 开发者计划中注册的电子邮件地址和姓名。将CA 电子邮件地址字段留空,并点击保存到磁盘单选按钮。现在点击继续

  6. 当被要求时,选择将证书保存到您的桌面。

将创建一个名为CertificateSigningRequest.certSigningRequest的 CSR 文件,并将其保存在磁盘上。

如何操作...

您现在有一个包含您的个人信息(您的姓名和电子邮件地址)的 CSR 文件,它将被用来从 Apple 请求开发证书。

当 CSR 文件创建时,钥匙串访问应用程序也创建了一个公钥和私钥。公钥包含在 CSR 文件中,而私钥用于签名请求。使用钥匙串访问,您可以在密钥类别中看到这两个密钥的列表。

不要删除您的 CSR 文件或私钥,因为它们在本章的后续部分都将需要。

相关链接

  • 获取您的开发证书

获取您的开发证书

现在您有了证书签名请求(CSR),可以使用它从苹果公司获取开发证书。这需要将您的 CSR 文件上传到 iOS 配置门户并等待批准。

准备工作

如果您还没有生成 CSR 文件,请生成一个。根据您选择的操作系统,请参阅使用 Windows 生成证书签名请求使用 Mac OS X 生成证书签名请求以获取更多详细信息。

如何操作...

  1. 登录到iOS Dev Center,然后进入配置门户。

  2. 点击门户主页左侧的证书链接,进入证书部分。如图所示,确保已选择开发选项卡:如何操作...

  3. 现在,点击屏幕最右侧的请求证书按钮,这将带您进入创建 iOS 开发证书页面。

  4. 在页面底部是浏览按钮。向下滚动一点,您也会在右侧看到提交按钮。

  5. 首先,点击浏览并导航到您硬盘上的 CSR 文件。

    注意

    如果您在 Windows 上使用 OpenSSL 创建了 CSR 文件,那么您可以在C:\OpenSSL-Win32\bin\CertificateSigningRequest.certSigningRequest中找到它。

    如果您是 Mac OS X 用户,那么您应该已经将CertificateSigningRequest.certSigningRequest保存在您的桌面上。

  6. 选择您的 CSR 文件后,点击提交

  7. 您将被带回到证书部分,现在将列出证书。其状态最初将被设置为待发行,苹果公司将发送一封主题为证书请求需要您的批准的电子邮件给您。

    这封电子邮件是为团队环境中的工作人员准备的。如果您已注册为个人,则无需采取任何进一步行动。只需在浏览器中刷新页面,证书的状态将自动更改为已发行

    小贴士

    在证书状态最终更新之前,您可能需要刷新网页几次。

  8. 点击操作列下的下载按钮,并将开发证书保存到您的硬盘上。

  9. 您保存证书的位置取决于您选择的操作系统。如果您使用的是 Windows,则将其保存到 OpenSSL 的bin文件夹中的C:\OpenSSL-Win32\bin\developer_identity.cer。如果您使用的是 Mac OS X,则暂时将developer_identity.cer文件保存到您的桌面上。

工作原理...

开发证书仅限于应用开发,并且有效期为有限时间。查看配置文件门户的证书部分中的过期日期列,以了解你的数字证书何时到期。通常证书有效期为一年。

证书过期后,您需要将其撤销,并从配置文件门户请求新的证书。

你现在离能够直接从 Flash Professional 编译 iOS 应用又近了一步。然而,在 Flash 可以为创建的任何 iOS 应用进行数字签名之前,你的开发证书必须转换为 P12 证书文件,我们将在下一道菜谱中介绍。

更多内容...

让我们详细说明一些额外的信息,其中一些对于代表公司报名并作为团队成员工作的人来说尤为重要。

批准证书签名请求

所有团队成员都可以提出 iOS 开发证书请求。作为原始报名者,你有责任批准或拒绝这些请求。

当团队成员请求开发证书时,您将收到一封主题为证书请求需要批准的电子邮件。这与注册为个人时收到的电子邮件相同;然而,在团队环境中工作,您需要通过点击电子邮件中提供的链接采取行动。

链接将在您的默认网络浏览器中打开,带您进入配置文件门户,您可以登录并查看任何等待批准的证书请求。在证书页面上,只需找到等待批准的证书请求,然后从操作列中选择接受拒绝

对于更多详细信息,请参阅程序用户指南,它可以在配置文件门户的资源部分找到。

团队角色

正如所述,原始报名者有权和责任批准或拒绝开发证书请求。原始报名者可以访问所有配置文件门户功能,并被指定为团队代理。

团队代理可以邀请其他人,并分配他们为团队管理员或团队成员的角色。

团队管理员可以邀请新的团队管理员和团队成员。此外,他们可以批准或拒绝证书签名请求。

团队成员拥有最低权限,必须由团队代理或团队管理员批准任何证书签名请求。

重要的是,所有三种类型的成员都可以在 iOS 设备上测试应用。

从现在起,在团队环境中原始报名者将在此书中被称为团队代理。

对于在团队环境中工作的详细解释,包括成员责任的完整列表,请参阅配置文件门户的资源部分中的程序用户指南

分发证书

为了在 App Store 上分发您的应用,您需要申请一个分发证书。尽管这些步骤在本书中没有涉及,但它们与获取和使用开发证书的步骤类似。

如需获取更多信息,请参阅程序用户指南中的分发部分,该部分可在配置门户的资源部分找到。

使用 Windows 创建 P12 证书

现在您已经从配置门户下载了您的开发证书,最后一步是将它转换为 P12 证书文件。

Flash Professional 将使用此 P12 文件对您创建的任何 iOS 应用进行数字签名。

生成 P12 证书文件的过程取决于您选择的操作系统。

本配方涵盖了 Microsoft Windows 的步骤。如果您使用的是 Mac OS X,请参阅使用 Mac OS X 创建 P12 证书配方。

准备工作

您需要从 iOS 配置门户创建并下载的开发证书。如果您还没有这样做,请按照获取您的开发证书配方中的步骤进行操作。

如何操作...

与创建 CSR 时的情况一样,您需要使用 OpenSSL 通过执行以下步骤将您的开发证书转换为 P12 文件:

  1. 以管理员身份在 Windows 中打开一个命令会话。

  2. 通过在命令提示符中输入以下命令进入 OpenSSL 的bin文件夹:

    cd C:\OpenSSL-Win32\bin 
    
    
  3. 第一步是将您的开发证书文件转换为 PEM 证书文件,通过输入以下命令行语句:

    openssl x509 -in developer_identity.cer -inform DER -out developer_identity.pem -outform PEM 
    
    
    • 为了使此操作生效,您需要将从配置门户下载的developer_identity.cer文件保存到 OpenSSL 的bin文件夹中。
  4. 现在请使用 PEM 文件和您的私钥,通过输入以下命令生成有效的 P12 文件:

    set RANDFILE=.rnd 
    
    
    • 接着是:
    openssl pkcs12 -export -inkey mykey.key -in developer_identity.pem -out ios_dev.p12 
    
    
  5. 在此过程中,OpenSSL 将要求您指定一个导出密码。Flash Professional 在将您的.swf文件编译成原生 iOS 应用时会提示您输入此密码,因此请选择一个您不太可能忘记的密码。输入您的密码,并在 OpenSSL 要求您验证时确认它。

    注意

    在输入密码时,可能会看起来命令行没有响应您的按键。请不要担心,您的按键已被记录,但由于安全原因,它们不会被显示在屏幕上。

  6. 如果操作成功,将在bin文件夹中创建一个ios_dev.p12文件。重要的是您要保管好此文件,因为您将需要它来发布本书中的任何示例。

  7. 使用 Windows 资源管理器,导航到您的Documents文件夹,并在其中创建以下文件夹结构:packt\flash-ios-cookbook\developer-files\。从现在起,我们将在此处保存我们的 P12 证书文件。

    注意

    您的Documents文件夹的位置取决于您正在运行的 Windows 版本。对于 Windows Vista 和 Windows 7,它可以在以下位置找到:C:\Users\<username>\Documents\。如果您使用的是 Windows XP,那么它位于:C:\Documents and Settings\<username>\My Documents\

  8. ios_dev.p12C:\OpenSSL-Win32\bin\复制到您刚刚创建的developer-files文件夹中。

它是如何工作的...

当您从 Flash Professional 发布 iOS 应用时,您将需要输入您的 P12 证书文件和密码。这两个都用于对您的应用进行数字签名,以便在 iOS 设备上部署和测试。

P12 证书是每次您使用 Flash Professional 进行 iOS 构建时将使用的两个文件中的第一个。

小贴士

无设备测试

如果您决定使用 AIR Debug Launcher (ADL)进行测试而不是部署到 iOS 设备,则不需要 P12 证书文件。

还有更多...

最后,关于证书的一些额外说明。

证书过期

当您的开发者证书最终过期时,您需要在将其转换为 P12 文件之前,从 Provisioning Portal 请求一个新的。使用旧证书发布的任何应用将无法在您的 iOS 设备上运行,并且需要使用新的有效 P12 文件重新发布。

如果您不小心删除了现有的 P12 文件,您可以从本食谱中概述的步骤简单地重新创建它。您不需要从 Provisioning Portal 请求新的开发者证书。

使用 Mac OS X 创建 P12 证书

现在您已经从 Provisioning Portal 下载了您的开发者证书,最后一步是将它转换为 P12 证书文件。

Flash Professional 将使用此 P12 文件对您创建的任何 iOS 应用进行数字签名。

生成 P12 证书文件的过程取决于您选择的操作系统。

这里涵盖了 Mac OS X 的步骤。如果您使用的是 Microsoft Windows,请参阅使用 Windows 创建 P12 证书食谱。

准备工作

您需要从 iOS Provisioning Portal 创建并下载的开发者证书。如果您还没有这样做,请按照获取您的开发者证书步骤进行操作。

如何操作...

执行以下步骤:

  1. 应用程序/实用工具文件夹启动Keychain Access应用程序。

  2. 从下拉菜单中选择文件 | 导入项目 (Shift + Cmd + I)。从文件浏览器中,选择您的证书,位于桌面/developer_identity.cer

  3. 您的证书将安装在 Keychain Access 应用程序中。您可以通过点击证书类别来确认这一点,您将看到您的iPhone Developer证书列出来。

  4. 现在,选择 密钥 类别,找到与您的证书关联的私钥。您的公钥和私钥都将列出,并使用您创建 CSR 时输入的名称命名。这在上面的屏幕截图中显示:如何操作...

  5. 右键单击私钥并选择 导出。当创建 P12 文件时,会出现一个对话框,提示您指定保存文件的路径。选择桌面并点击 保存

    小贴士

    请注意,右键单击私钥而不是公钥。您可以通过查看每个密钥旁边的 类型 字段中列出的 私钥 来进行检查。

  6. Keychain Access 会要求您指定一个导出密码。Flash Professional 在将您的 .swf 文件编译成原生 iOS 应用时,会提示您输入此密码,因此请选择一个您不太可能忘记的密码。输入您的密码,并在 验证 字段中重新输入以确认,然后点击 确定

    注意

    Keychain Access 可能还会提示您输入您的 Mac 登录密码。如果是这样,请这样做,并点击 允许 以授予 Keychain Access 导出密钥的权限。

    • 如果成功,将创建一个 P12 证书文件并将其保存到您的桌面上。

      重要的是您要保管好这个文件,因为您将需要它来发布本书中的任何示例。

  7. 使用 Finder,导航到您的 Documents 文件夹,并在其中创建以下文件夹结构:packt/flash-ios-cookbook/developer-files/

  8. 将您的 P12 文件复制到这个新位置。从现在起,我们将在这里保存它。

它是如何工作的...

当您从 Flash Professional 发布 iOS 应用时,您将需要输入您的 P12 证书文件和密码。这两个都用于对您的应用进行数字签名,允许它在 iOS 设备上部署和测试。

P12 证书是 Flash Professional 每次您制作 iOS 构建时使用的两个文件中的第一个。

小贴士

无设备测试

如果您决定使用 AIR 调试启动器 (ADL) 进行测试而不是部署到 iOS 设备,则不需要 P12 证书文件。

还有更多...

最后,关于证书到期的一些额外说明。

证书到期

当您的开发者证书最终到期时,您需要在将其转换为 P12 文件之前,从配置文件门户请求一个新的。使用旧证书发布的任何应用将无法在您的 iOS 设备上运行,并且需要使用新的有效 P12 文件重新发布。

如果您不小心删除了现有的 P12 文件,则可以简单地根据本食谱中概述的步骤重新创建它。您不需要从配置文件门户请求新的开发证书。

注册设备

您想要用于测试的任何设备都必须注册。每个 iOS 设备都有一个 唯一设备标识符 (UDID),需要在注册过程中作为注册过程的一部分输入到配置文件门户中。

在这个菜谱中,我们将学习如何定位设备的 UDID 并将其添加到配置门户。

准备工作

可以使用 iTunes 获取设备的 UDID。

iTunes 通常预装在 Mac OS X 上。使用 Windows 且尚未安装 iTunes 的用户可以从www.apple.com/itunes/download下载它。

如果您已经安装了 iTunes,请确保您有最新版本。

如何操作...

按照以下步骤注册您的设备:

  1. 启动 iTunes 并通过 USB 连接您的 iOS 设备。片刻之后,设备将出现在 iTunes 的设备部分。

  2. 点击设备的名称以显示摘要。

  3. 在这里,您可以在屏幕顶部附近找到它的 11 位序列号。点击序列号以显示设备的 40 位 UDID,如下面的截图所示。UDID 将替换以下截图中所显示的序列号:如何操作...

  4. 通过从 iTunes 的下拉菜单中选择编辑 | 复制 (Ctrl + C 或 Cmd + C) 来复制 UDID。

  5. 登录到iOS Dev Center并进入配置门户。

  6. 通过点击门户主页左侧的链接进入设备部分。确保已选择管理标签。从该页面,您将能够管理您想要与您的应用程序一起测试的设备。

  7. 点击页面右上角的添加设备按钮。您将看到一个添加设备页面,您可以在此处输入设备的 UDID 并为识别目的分配一个名称。

    小贴士

    使用多台设备进行测试

    如果您计划使用多台设备进行测试,那么尝试为每台设备分配有意义的名称,以帮助区分它们。这对于在大型开发团队工作的组织尤为重要。

  8. 添加您的设备 UDID 并为它输入一个名称。完成后,点击页面右下角的提交按钮。页面将刷新,如下面的截图所示,您将在屏幕上看到您新注册的设备:如何操作...

  9. 如果您有其他 iOS 设备想要用于测试,请现在添加它们。

工作原理...

基本上,配置过程是为了允许您在您拥有的设备上测试您编写的应用程序。

在配置门户上注册设备是朝着实现这一目标迈出的另一步。如果不需要设备注册,那么理论上您可以通过在任意数量的设备上安装应用程序来绕过 App Store 的发行模式。

苹果的限制不仅是为了保护其分发模式,也是为了保护您的开发应用不落入错误的手中,并在未经授权的设备上运行。

更多...

注册设备是一个相当简单的过程。然而,还有一些其他选项和场景您应该了解。

在团队环境中添加设备

在团队环境中工作,只有团队代理或团队管理员可以添加设备。团队成员没有执行此操作的必要权限。

编辑设备名称

如果您对分配给设备的标识符不满意,您可以在稍后更改它。在配置门户中,只需移动到 设备 部分,并在 当前已注册设备 列表中找到该设备。在右侧的 操作 列中,点击该设备的 编辑 链接。

设备限制

您每年只能向您的开发者计划添加最多 100 台设备。您添加并随后删除的任何设备都将计入该总数,因此在管理您的列表时请仔细考虑。

如果您在年底续订 iOS 开发者计划,您将在添加任何额外设备之前重置您的设备列表。然而,一旦您再次开始添加设备,您选择的任何要删除的设备将再次计入您的设备限制。

UDID 发送者

App Store 中有一个名为 UDID 发送者 的应用,您可能会觉得它很有用。UDID 发送者将提取您的设备的 UDID 并自动将其填充到一封电子邮件中,供您发送。

这对于大型组织尤其有用,因为团队代理或团队管理员可能会收到来自团队成员的大量设备注册请求。

为了让团队管理员不必分别检索每个设备并从 iTunes 中发现其 UDID,他们可以简单地依赖团队成员直接将设备的 ID 发送给他们。

UDID 发送者可以从 iTunes 或 App Store 下载,并且是免费的。

创建 App ID

您编写的每个应用都必须分配一个 App ID,这是 iOS 使用的唯一标识符。

有两种类型的 App ID:显式 App ID通配符 App ID。为了简化开发,您可以使用通配符而不是显式 App ID。这消除了为每个应用生成 ID 的需要,并且当您在本书中的示例中进行测试时将特别有用。

让我们创建一个通配符 App ID,它可以在多个应用中使用。

如何操作...

执行以下步骤:

  1. 登录到 developer.apple.com/devcenter/ios 上的 iOS 开发中心,并前往配置门户。

  2. 通过点击门户主页左侧的链接,移动到 App IDs 部分。确保已选择 管理 选项卡。从该页面,您可以添加新的 App IDs 并查看您之前创建的任何 App IDs。

  3. 在页面右侧,与App IDs标题相对的是新建 App ID按钮。点击它,您将被带到创建 App ID页面。

  4. 应为每个新的 App ID 分配一个通用名称。这将在配置文件门户中用于识别该 App ID。在描述标题下方直接输入通用开发

  5. 现在您可以创建 App ID。在包标识符文本框中输入*。您的创建 App ID页面应该类似于以下截图:如何操作...

  6. 点击页面右下角的提交按钮。您将被带回到App IDs页面,在那里您将看到您刚刚创建的新 App ID 列在表中。

它是如何工作的...

App ID 是一个用于识别应用(或多个应用)的开发者或团队的唯一字符串。

它由两部分组成:一个包种子 ID和一个包标识符。包种子 ID 是由苹果生成的全球唯一的 10 位前缀。包标识符是由您自己确定的唯一后缀,可以包括通配符符号"*"。

当从 Flash Professional 编译 iOS 应用时,您需要选择与您的应用关联的 App ID 并将其提供给 Flash。尽管您在发布过程中会被要求提交 App ID,但实际上您只需提供 App ID 的包标识符部分。

如果您的包标识符包含通配符字符,那么您需要用任意字符串替换通配符,以唯一地表示您的应用。如果没有使用通配符,那么您必须将包标识符指定为与在配置文件门户中输入的完全一致。

通配符的好处是它允许您创建一个可以用于您开发的任何应用的单一 App ID。这在您阅读本书时尤其有用,因为它消除了为每个配方在配置文件门户中创建唯一 App ID 的需要。

更多...

您按照本配方步骤创建的 App ID 是完成本书中提供的示例所必需的。然而,您可能会发现以下附加细节对您自己的个人项目有用。

包标识符命名约定

虽然我们使用单个星号来表示包标识符,但苹果推荐的做法是使用反向域名样式。

您应该熟悉这个命名约定,因为它在 ActionScript 中用于命名包,有助于防止命名空间冲突;域名只能由个人或组织拥有。

以域名 yeahbutisitflash.com 为例。与其使用单个星号,不如创建一个 App ID,通过以下包标识符在多个应用中使用:com.yeahbutisitflash.*

要使用这个 App ID 从 Flash Professional 发布多个应用,请向 Flash 提供完整的 Bundle Identifier,但将通配符替换为你为每个应用选择的唯一字符串。

例如,如果你正在开发两个单独的测试应用,那么你可以指定给 Flash,第一个应用的 ID 是 com.yeahbutisitflash.test1,而另一个的 ID 可以设置为 com.yeahbutisitflash.test2

这两个应用仍在使用配置文件门户中注册的 com.yeahbutisitflash.* ID,但每个应用都替换了独特的字符串,以区分彼此。

应用分发

准备分发到 App Store 的应用在其 Bundle Identifier 中不能指定通配符。

当你准备好将你的应用提交到 App Store 时,你需要从配置文件门户创建一个新的 App ID,并使用新的 ID 从 Flash Professional 发布你的应用。

例如,你可能在使用相机应用的开发过程中使用了 Bundle Identifier com.yeahbutisitflash.*,但在分发时,你必须创建一个新的 App ID,移除通配符,并确保它对该应用是唯一的。以下 Bundle Identifier 就足够了:com.yeahbutisitflash.camera

值得注意的是,在开发过程中,你也不必在 Bundle Identifiers 中使用通配符,但它很有用,因为它允许你快速将多个测试应用部署到你的设备上。如果你使用的不包含通配符的 App ID,那么你将无法部署使用该 App ID 的单独应用到你的设备上,迫使你在配置文件门户中为每个应用注册一个新的 App ID。

编辑 App ID

配置文件门户不允许你删除或编辑你创建的任何 App ID。在命名你的 App ID 和分配它们的 Bundle Identifiers 时要小心,因为这些细节以后无法更改。你可以注册的 App ID 数量没有限制,所以如果你犯了错误,你可以在以后创建并添加一个新的。

创建开发配置文件

一旦你有了开发证书、至少一个注册的 iOS 设备和一个 App ID,你就可以创建配置文件了。开发配置文件是一个文件,它将一个应用(或一组应用)与一个或多个授权的开发者和一组设备关联起来。在你可以在一个设备上测试一个应用之前,你必须首先在该设备上安装一个配置文件。一个设备可以安装多个配置文件。

配置文件是从 iOS 配置文件门户创建的。

本指南将指导你完成创建配置文件的步骤,这将允许你在设备上测试本书的示例。

准备工作

为了完成此配方,您需要创建一个开发证书,注册一个 iOS 设备,并拥有一个 App ID。如果您还没有这样做,请先完成以下配方:

  • 获取您的开发证书

  • 注册设备

  • 创建 App ID

如何操作...

按照以下步骤创建开发配置文件:

  1. 登录到iOS Dev Center并转到配置门户。

  2. 点击门户主页左侧的配置链接。您将被带到配置页面,并选择开发选项卡。

  3. 点击开发配置文件标题右侧的新建配置文件按钮。您将被带到创建 iOS 开发配置文件页面。

  4. 从此页面,您可以通过执行以下步骤生成配置文件:

    • 为配置文件分配一个名称。

    • 将其与开发证书关联。

    • 选择 App ID。

    • 选择一个或多个可用于测试的 iOS 设备。

  5. 首先,在配置文件名称文本框中输入Flash iOS Cookbook。从证书字段中,勾选您开发证书旁边的复选框。从App ID下拉菜单中,选择您之前创建的通用开发App ID。最后,勾选您想要测试此书示例的设备的复选框。如果您已注册多个设备,则可以全部选择。

  6. 点击页面右下角的提交按钮。

  7. 您将被带回到开发配置文件页面,您的配置文件将列出,并分配一个待定状态。在浏览器中刷新页面将更改配置文件的状态为活动

    小贴士

    在状态最终更新之前,您可能需要刷新您的网页几次。

  8. 现在点击下载按钮,该按钮位于操作列下方。将Flash_iOS_Cookbook.mobileprovision文件保存到与您的 P12 证书文件相同的目录。具体路径,请参考使用 Windows 创建 P12 证书配方或使用 Mac OS X 创建 P12 证书配方。

工作原理...

您的开发配置文件已与创建 App ID配方中的General Development App ID 关联。作为一个通配符 App ID,此配置文件可用于在授权设备上运行和测试本书的任何示例。

配置文件需要在授权设备上安装,并且 Flash Professional 也需要它。为了编译原生 iOS 应用,您不仅需要提供 Flash 您的 P12 证书文件,还需要提供您尝试编译的应用关联的配置文件。

小贴士

无设备测试

如果您从 ADL 进行测试而不是部署到 iOS 设备,则不需要配置文件。

还有更多...

在我们进入最后的配方之前,您可能会发现以下附加信息很有用。

配置文件过期

开发配置文件仅限于应用开发,并且仅有效期为三个月。如果在开发过程中配置文件过期,那么您需要从配置文件门户创建一个新的配置文件。请记住,在所有授权设备上安装新配置文件,并使用新配置文件从 Flash 重新构建您的应用。

编辑配置文件

与 App ID 不同,配置文件可以从配置文件门户中删除。从配置文件列表中,只需勾选您想要删除的每个配置文件旁边的复选框。然后点击列表底部的删除所选按钮。

您还可以编辑现有的配置文件。在操作列的右侧,点击配置文件的编辑链接。您可以修改与配置文件关联的原始详细信息,甚至可以在对其进行更改之前创建配置文件的副本。

其他配置文件类型

实际上可以创建三种类型的配置文件。本书将重点介绍开发配置文件的使用,但配置过程还涵盖了两种分发方法——Ad Hoc 和 App Store。

Ad Hoc 分发配置文件用于与最多 100 名其他 iOS 用户共享应用进行测试。另一方面,App Store 分发配置文件用于构建和提交应用到 App Store。

在创建 Ad Hoc 或 App Store 分发配置文件时,您需要请求和使用分发证书,而不是开发配置文件所需的发展证书。

更多详细信息,请参阅程序用户指南分发部分,该指南可在配置文件门户的资源部分找到。

与多个团队成员协作

如果您在一个团队环境中工作,您必须是团队代理或团队管理员才能创建配置文件。在创建配置文件时,检查每个应获得构建和测试与配置文件关联的应用程序权限的团队成员的证书旁边的复选框。

在您的设备上安装配置文件

现在您已经拥有配置文件,需要将其安装到设备上。这将允许与配置文件关联的任何应用在该设备上进行测试。

在本配方中,我们将使用 iTunes 将配置文件复制到连接的设备上。

准备工作

如果您尚未创建配置文件,请在继续之前参考创建开发配置文件配方。

如何操作...

执行以下步骤:

  1. 启动 iTunes 并通过 USB 连接您的 iOS 设备。

  2. 短暂片刻后,设备将在 iTunes 的设备部分中显示。

  3. 从 iTunes 的下拉菜单中选择文件 | 添加文件到库 (Ctrl + O | Cmd + O)

    注意

    在 Mac OS X 上,下拉菜单选项列出的为添加到库,这允许您添加文件和文件夹。在 Windows 上,这分为两个单独的选项:将文件添加到库将文件夹添加到库

  4. 导航到您的Documents文件夹,并在以下位置选择您的配置文件:packt\flash-ios-cookbook\developer-files\Flash_iOS_Cookbook.mobileprovision。配置文件将被添加到 iTunes 中。

  5. 在 iTunes 的设备部分中,点击您的设备名称。您将看到设备的摘要信息。

  6. 点击 iTunes 右下角的同步按钮,将配置文件复制到您的设备上。

它是如何工作的...

配置文件只会安装在与该配置文件关联的设备上。

在您的 iOS 设备上,您可以通过选择设置 | 通用 | 配置文件来确认配置文件已被添加。您应该能够看到配置文件及其到期日期的列表。如果您的设备上没有安装配置文件,则不会提供配置文件选项。

当安装用于测试的应用程序时,应用程序将首先与设备的配置文件列表进行核对。如果找到与该应用程序关联的配置文件,它才会被复制到设备上。

更多...

一旦您熟悉了将配置文件添加到设备的过程,您可能还想考虑以下信息。

删除配置文件

您可以通过设置 | 通用 | 配置文件从您的设备中删除配置文件。通常,您会在配置文件过期时执行此操作。然而,删除配置文件后,您可能会发现它下次与您计算机上的 iTunes 同步时再次出现在您的设备上。

每次您安装的配置文件副本都将保存在您的计算机以及您的设备上。如果您从设备中删除了配置文件,请确保您也从计算机中删除了本地副本。

这是配置文件存储的位置:

  • Windows 7 和 Vista: C:\Users\<username>\AppData\Roaming\Apple Computer\MobileDevice\Provisioning Profiles\

  • Windows XP: C:\Documents and Settings\<username>\AppData\Roaming\Apple Computer\MobileDevice\Provisioning Profiles\

  • Mac OS X:<username>/Library/MobileDevice/Provisioning Profiles/

您可以根据操作系统使用 Windows 资源管理器或 Finder 简单地删除配置文件。

iPhone 配置实用工具

作为 iTunes 的替代方案,您可能想从 Apple 下载并安装 iPhone 配置实用工具。

它允许您轻松管理配置文件和从连接的设备捕获控制台日志信息。您可以检查配置文件何时即将到期,还可以发现每个已安装的应用程序关联的 App ID。

iPhone 配置工具适用于 Mac OS X 和 Windows,并可从 www.apple.com/support/iphone/enterprise 下载。

第二章:使用 Flash 构建 iOS 应用

在本章中,我们将涵盖:

  • 安装 AIR SDK

  • 创建一个 AIR for iOS 文档

  • 将内容添加到舞台

  • AIR for iOS 常规设置

  • AIR for iOS 部署设置

  • 从 Flash Professional 编译

  • 使用 iTunes 安装您的应用

简介

现在你已经注册了 iOS 开发者计划,并从 iOS 配置文件门户获取了必要的文件,我们可以将注意力转向从 Flash Professional 构建原生 iOS 应用。

本章将介绍设置和编译 iOS 应用所需的基本任务。虽然我们将主要关注配置,但我们将为基本应用打下基础,这些内容将在下一章完成。

但首先,让我们花些时间介绍工具链。

在 Flash Professional CS5 发布时,Adobe 包括了iPhone 打包器(PFI)——一个命令行工具,它也被集成到 Flash IDE 中,允许 ActionScript 3.0 项目编译成原生 iOS 应用。

初始支持提供了对 Adobe AIR 2.0 和 Flash Player 10.1 API 的大部分访问权限,并针对 ARMv6 和 ARMv7 iOS 设备。

对于那些不熟悉Adobe AIR的人来说,它将 Flash 的功能扩展到浏览器沙盒之外,使开发者能够直接访问 Flash Player 无法访问的桌面计算机和移动设备的特性。

随着Flash Professional CS5.5的发布和 AIR 2.6 的引入,为 iOS 开发提供的 API 得到了扩展。Adobe 还进行了重大的性能改进;特别是渲染引擎。然而,对 iOS 3 及更早的 ARMv6 设备的支持已被取消,这意味着如果你使用 CS5.5,将无法针对原始 iPhone、iPhone 3G 或第一代和第二代 iPod touch 进行开发。

PFI 命令行工具也被移除,并由AIR 开发工具(ADT)取代。这是有道理的,因为 ADT 是 AIR 开发者传统上用来打包桌面和最近 Android 手机上交付的 AIR 应用的工具。

Adobe 迅速推出了 AIR 2.7,尽管它没有为 iOS 开发提供任何新的 API,但渲染性能再次得到提升,并添加了一个新构建选项,这大大提高了编译时间。

AIR SDK的最新主要版本是 3.0,它带来了一系列令人兴奋的新功能、性能增强和错误修复。也许,最显著的新增功能是备受期待的硬件加速 3D API 和能够使用原生代码实现的自定义 ActionScript 库编写功能。

本书涵盖的大多数配方都与 Flash Professional CS5 和 CS5.5 兼容。然而,AIR 2.6 及以上版本提供的新功能是针对 CS5.5 的,并将被明确标注。

使用 Flash 开发 iOS 应用通常被称为 AIR for iOS,这是本书中使用的术语。

安装 AIR SDK

在我们开始之前,重要的是您要花时间确保您的 Flash Professional 安装是最新的,并且已安装最新的 AIR SDK。

准备工作

您需要 Flash Professional CS5 或 CS5.5 才能编译原生 iOS 应用。

您可以从 Adobe 网站下载 Flash Professional CS5.5 的 30 天试用版,网址为 www.adobe.com/downloads

如何操作...

我们将把这个步骤分成两部分。首先,我们将安装 Flash Professional 所需的任何更新。其次,我们将下载并安装最新的 AIR 运行时和 SDK 版本。

更新 Flash Professional

不时地,Adobe 会提供 Flash Professional 的更新。这些更新通常包括错误修复或额外的功能,由于某种原因,这些功能在发布时不可用。

访问 www.adobe.com/support/flash/downloads.html 并检查 Flash 版本的更新。

如果您使用的是 Flash Professional CS5,那么您应该特别下载适用于您所选操作系统的以下两个更新:

  • Flash Professional CS5 更新 11.0.2

  • Flash Professional CS5 iOS 更新

注意

在应用 iOS 更新之前,必须安装 11.0.2 更新。此外,如果您当前已打开 Flash Professional CS5,则在尝试之前请关闭它。

iOS 更新必须通过将各种文件复制到您的 Flash Professional CS5 安装中手动应用。更新附带文档,您在尝试之前应仔细阅读。

一段详细说明 Flash Professional CS5 更新过程的视频也可用,可在 www.gotoandlearn.com/play.php?id=133 找到。

在 AIR SDK 上叠加

建议您在开发计算机上安装 AIR 运行的最新版本。您可以从 get.adobe.com/air 下载并安装。

此外,如果您使用的是 Flash Professional CS5.5,您还需要最新的 AIR SDK。默认情况下,CS5.5 提供对 AIR 2.6 的支持,但它可以被更新以使用最新版本。如果您想完成本书中涵盖的所有食谱,这是一个必要的步骤。

要实现这一点,您必须下载并手动将最新的 AIR SDK 套叠到您的 Flash Professional CS5.5 安装上。SDK 的下载链接和分步说明可在 www.yeahbutisitflash.com/?p=2949 找到。在继续之前,请仔细遵循这些说明。

不幸的是,如果你使用的是 Flash Professional CS5,你将仅限于使用 AIR 2.0 SDK,因为无法在其上叠加更新的 AIR SDK。不过,不用担心;你仍然可以尝试本书的大多数食谱。对于你不能尝试的食谱,考虑升级到 Flash Professional CS5.5 或从 Adobe 网站下载 30 天试用版。

官方 Adobe AIR 网站可在 www.adobe.com/products/air.html 找到。

它是如何工作的...

重要的是,你正在使用最新的 Flash Professional 和 AIR SDK 版本。随着每个新版本的发布,AIR for iOS 在 API 覆盖率和性能方面都得到了加强。

创建 AIR for iOS 文档

当你创建一个新的 FLA 文件时,你可以从几种文档类型中选择。

每种文档类型都会配置发布设置、舞台大小和帧率,以最适合你打算创建的内容。你的文档选择将取决于你是否想针对 Flash Player 及其 API,或者利用 AIR 的额外功能。

本食谱将指导你完成创建针对 AIR for iOS 的新 FLA 的必要步骤。我们将使用此 FLA 作为在本章和下一章中创建的简单应用程序的起点。

准备工作

确保你的 Flash Professional 版本已应用所有可用更新,并且你正在使用最新的 AIR SDK。如果你还没有这样做,那么在继续之前,请执行 安装 AIR SDK 菜单中概述的步骤。

如何操作...

按照以下步骤创建你的 FLA:

  1. 启动 Flash Professional 并从下拉菜单中选择 文件 | 新建 (Ctrl + N | Cmd + N)

  2. 新建文档 对话框将出现。确保已选择 常规 选项卡,并根据你使用的 Flash Professional 版本,点击以下文档类型之一:

    • CS5: iPhone OS

    • CS5.5: AIR for iOS

      iPhone OSAIR for iOS 指的是完全相同的东西。从现在起,本书将使用 AIR for iOS 这个术语。如果你使用的是 Flash CS5,那么在创建新文档时只需选择 iPhone OS 即可。

    注意

    在 CS5.5 中,你将在 新建文档 面板的右侧看到所选文档类型的各种属性。注意,当你选择 AIR for iOS 时,舞台大小会变为 320x480 像素。这是 iPhone 3GS 竖直方向握持时的标准屏幕尺寸。

  3. 点击对话框右下角的 确定 按钮,如图所示:如何操作...

    • 你的 AIR for iOS 文档将被创建。

    注意

    此 FLA 将作为本章和下一章中创建的简单应用程序的起点。

    根据您选择的操作系统,使用 Windows 资源管理器或 Finder 导航到您的Documents文件夹中的packt\flash-ios-cookbook\。创建一个新的子文件夹并将其命名为my-first-app

  4. 从下拉菜单中选择文件 | 另存为 (Ctrl + Shift + S | Shift + Cmd + S) 并将您的 FLA 保存到my-first-app文件夹中,命名为bubbles.fla

它是如何工作的...

每次开始一个新的 AIR for iOS 项目时,您都应该执行我们刚才看到的简单步骤。

Flash 为您创建的文档将设置为利用 ActionScript 3.0 和 AIR API。舞台也将设置为有效的 iOS 屏幕大小,并且帧率默认为 24 fps。

还有更多...

您可以更改与 iOS 文档关联的许多默认设置。您可能会发现以下设置特别重要。

舞台尺寸

默认的 AIR for iOS 文档类型假定您将针对原始 iPhone 和 iPod touch 设备,并且您的应用将使用纵向屏幕方向。

在 Flash CS5.5 中,您将在新建文档面板的右侧看到您的文档默认属性。只需更改宽度高度字段以针对不同的屏幕分辨率和方向。例如,如果您的应用需要锁定到横向屏幕方向,则将舞台大小设置为 480x320。

如果您使用 Flash CS5,您可以在创建文档后调整舞台尺寸。您可以从属性面板进行此操作。

可用的 iOS 屏幕分辨率(纵向模式)包括:

  • 320x480—iPhone 3GS,第三代 iPod touch

  • 640x960—iPhone 4,iPhone 4S,第四代 iPod touch

  • 768x1024—iPad,iPad 2

当使用 Flash CS5 时,不支持 640x960 屏幕分辨率。

对于本书的大多数食谱,它将坚持默认分辨率 320x480,这是所有 iOS 设备都支持的。然而,Retina 和 iPad 显示分辨率在第八章(ch08.html "第八章。屏幕分辨率和方向变化")中有所介绍。

帧率

所有新文档都使用 24 fps 的默认帧率。虽然您可以增加此值,但请注意,由于 CPU 和 GPU 的限制,在旧一代设备上实现更高的帧率可能会有困难。鉴于不同代 iOS 设备之间的性能差异,您应该仔细考虑帧率,尤其是如果您想针对尽可能多的设备的话。

参见

  • AIR for iOS 通用设置

  • 支持多分辨率,第八章

将内容添加到舞台

使用 Flash 构建 iOS 应用的一个许多优点是能够使用您已经熟悉的创作工具。您仍然可以通过将内容从拖放到舞台上来执行大部分布局,从而实现快速开发。

让我们这样做来构建一个简单的场景。

准备工作

本书附带各种图形资源文件,您在完成某些菜谱时应使用这些文件。这将为您节省大量时间和精力,并确保您的最终结果与您遵循的菜谱相匹配。

如果您还没有这样做,请从本书的配套网站上下载代码包。

小贴士

下载示例代码

您可以从您在 www.packtpub.com 购买的 Packt 书籍的账户中下载所有示例代码文件。如果您在其他地方购买了此书,您可以访问 www.PacktPub.com/support 并注册以将文件直接通过电子邮件发送给您。

您可以在 chapter2\resources\ 中找到本章使用的资源。此外,您还可以找到本章每个菜谱的完整代码示例。

确保您正在使用前面菜谱中创建的 bubbles.fla 文件工作。本章中的每个后续菜谱都将建立在前面菜谱的基础上,随着您的进展,向 bubbles.fla 添加更多内容。

如何操作...

我们首先将库中的符号复制到您的 FLA 文件中。

  1. 选择 文件 | 打开 (Ctrl + O | Cmd + O) 并浏览到 chapter2\resources\resources.fla。点击 打开 以加载 FLA 文件。

  2. resources.fla 复制所有库中的符号,并将它们粘贴到 bubbles.fla 的库中。

    您的库现在将包含一组位图和以下五个电影剪辑:背景,大泡泡,中泡泡,中号泡泡小泡泡。从库中,双击每个电影剪辑符号,仔细查看每个的内容。您会看到每个剪辑都由单个位图图像组成。

  3. Background 电影剪辑符号从库中拖动到舞台。在 属性 面板中,展开 位置和大小 部分,并将电影剪辑定位在 (0,0)。如果您使用的是 Flash Professional CS5,那么您还应该展开 显示 部分,并勾选 缓存为位图 复选框。如果您使用的是 CS5.5,则无需设置此选项,因为这可能会降低此应用的性能。

  4. 现在,从库中将三个 Bubble Small 实例拖动到舞台。如果您使用的是 Flash CS5,那么在 属性 面板中为每个实例勾选 缓存为位图 复选框。

  5. 使用 属性 面板,将实例命名为 bubble1, bubble2bubble3。同时,将每个实例的位置分别设置为 (206, 421),(162, 160) 和 (122, 53)。以下截图显示了第一个泡泡实例在舞台上的定位:如何操作...

  6. 将三个 Bubble Medium 实例拖动到舞台。对于 Flash CS5,为每个实例勾选 缓存为位图 复选框。

  7. 将实例命名为bubble4, bubble5bubble6。分别设置它们的位置为(162,290),(318,274)和(203,119)。

  8. 只需要两个Bubble Large实例。再次检查,如果您使用的是 CS5,请从属性面板中勾选缓存为位图复选框。

  9. 分配bubble7bubble8的实例名称,并将它们的位置设置为(74,329)和(297,12)。

  10. 最后,将Bubble Huge放置在舞台上,如果您使用的是 CS5,请确保勾选缓存为位图复选框。给它一个实例名称为bubble9,并将其部分放置在舞台之外的位置(440,303)。

  11. 保存您的 FLA 文件。

它是如何工作的...

我们刚刚讲解的内容,即使是只有基础 Flash 理解的人也应该感到熟悉。你只需将各种电影剪辑实例拖放到舞台上,就可以创建一个可以在 iOS 设备上显示的场景。

您可能不熟悉缓存为位图的渲染选项。这将在第六章中详细解释;但就目前而言,只需知道当使用 Flash Professional CS5 时,选择此选项将显著提高您应用在特定情况下的图形性能。

注意,在这个菜谱中,所有的图形内容都是以 PNG 格式提供的,而不是矢量格式。这是故意的,因为 iOS 设备可以将位图渲染到屏幕上比 Flash 的矢量内容更快。在适当的情况下,尽量使用位图,但这并不意味着您应该完全忽略 Flash 的矢量渲染器,因为它是 Flash 的许多优点之一。

现在我们已经有了一些视觉内容,我们可以开始配置 Flash 的额外 iOS 特定设置,以便构建和部署您的应用到设备上。

相关内容

  • 使用缓存为位图,第六章

AIR for iOS 常规设置

在将您的 FLA 编译成原生 iOS 应用之前,Flash 需要一些额外的信息。首先,您需要指定一些一般的 iOS 设置,我们将在下面介绍。

准备工作

我们将继续在bubbles.fla文件上工作。

如何操作...

当从 AIR for iOS 文档工作的时候,Flash Professional 会提供一个额外的设置面板。通过它,您将能够应用一些 iOS 特定的设置,这些设置将在输出原生 iOS 应用时被 Flash 使用。

选择文件 | AIR for iOS 设置以打开面板。确保已选择常规选项卡。

提示

如果您正在使用 Flash Professional CS5,请选择文件 | iPhone OS 设置。记住,CS5 使用iPhone OS这个术语,而 CS5.5 则将其称为AIR for iOS

AIR for iOS 设置面板中,可以为以下字段设置选项:

选项 描述
输出文件 您原生 iOS 应用的文件名
应用名称 您应用的名字
版本 您应用的版本号
纵横比 应用程序的默认屏幕方向
全屏 是否使用全屏或显示顶部状态栏
自动旋转 屏幕方向是否自动随设备旋转
渲染 设置你的应用使用的渲染模式
设备 你要针对的 iOS 设备
分辨率 标准或 Retina 屏幕分辨率支持
包含的文件 与你的应用捆绑在一起的其他资源

让我们设置一些这些选项:

  • 输出文件应用名称 字段将默认为你的 FLA 名称。对于本章的示例应用,确保 输出文件 设置为 bubbles.ipa,并且 应用名称 设置为 Bubbles

  • 版本 字段中设置一个值为 0.1

  • 气泡应用是为纵向屏幕方向设计的,并将占用你设备屏幕显示的全部。因此,确保将 纵横比 字段默认设置为 纵向,并检查 全屏 复选框。

  • 请不要勾选 自动旋转 选项。

  • 渲染 字段的下拉框中选择 GPU

  • 确保将 设备 字段设置为 iPhone,并将 分辨率 字段设置为 标准。在 Flash CS5 中,分辨率 字段不可用。

现在点击面板底部的 确定 按钮并保存你的 FLA。

它是如何工作的...

让我们更详细地检查一下之前做出的某些选择。

当你发布 FLA 文件时,Flash 会生成输出文件 .ipa,其中包含你的原生应用。这是你将在设备上安装的文件,通常被称为 IPA。

应用名称是在你的设备主屏幕上显示在应用图标下的名称。仔细考虑应用名称。长度超过 13 个字符的名称将因屏幕空间限制而被截断。

版本号编译到构建的每个应用中,并包含主版本号和次要版本号。当你在设备上安装应用的新版本时,你需要记住增加版本号。如果不这样做,则应用实际上不会覆盖现有版本进行安装。

虽然你的舞台尺寸可能已经暗示了这一点,但你仍然需要通过将 纵横比 字段设置为 纵向横向 来明确声明你应用的纵横比。

渲染模式指定你的应用程序应该使用设备的 图形处理单元 (GPU) 还是使用 CPU 进行渲染。在某些情况下,GPU 渲染可以提高你应用的渲染性能。有关 GPU 加速的更多信息,请参阅 第六章。

选择 设备 字段告诉 Flash 你要针对哪个设备系列,并决定了你的 IPA 在特定设备上的运行方式。你可以选择 iPhone、iPadiPhone 和 iPad

选择iPhone将限制你的屏幕大小与 iPhone 的屏幕大小相同。你的 IPA 仍然可以在 iPad 上运行,但应用程序不会尝试利用 iPad 的屏幕分辨率。相反,iPad 将使用 iPhone 的标准 320x480 分辨率运行应用程序,并将图像放大以适应 iPad 的屏幕。选择iPad将利用 iPad 的分辨率,并将你的应用程序限制在该设备上。如果你编写了一个可以利用 iPhone 和 iPad 屏幕分辨率的程序,那么你应该选择iPhone 和 iPad

还应注意的是,iPod touch 被视为 iPhone。因此,从设备字段中选择iPhoneiPhone 和 iPad将允许你的.ipa文件安装到 iPod touch 上。

AIR 2.6 及以上版本提供了利用在 iPhone 4 和第四代 iPod touch 上引入的Retina 显示屏的能力。这将为你提供 640x960 的屏幕分辨率。如果你确实想利用 Retina 显示屏,并且还想支持 320x480 的标准分辨率,那么你需要编写一个可以处理两者的单一应用程序。App Store 不允许你上传两个不同的版本;每个分辨率一个。Flash Professional CS5 不支持 Retina 显示屏支持。

这本书的大部分内容将集中在标准分辨率上,这将确保示例可以在所有 iOS 设备上运行。iPad 和 Retina 显示屏设备都将放大针对标准 320x480 分辨率的 内容。然而,有关 Retina 和 iPad 分辨率的更多详细信息,请参阅第八章。

还有更多...

以下是一些你应该考虑的更多选项。

添加状态栏

你可以通过取消选择全屏复选框来将默认的 iOS 状态栏添加到你的应用程序中。

状态栏消耗 20 个垂直像素(Retina 显示屏上的 40 个像素)并位于屏幕顶部。Flash 将尝试缩小你的应用程序以适应剩余的屏幕高度,并在屏幕两侧留下边框。

有几种方法可以防止这种情况发生。最简单的方法是将舞台高度降低以适应剩余的垂直空间。

或者,保持舞台的尺寸不变,并使用 ActionScript 防止其缩放。这样做的话,你将需要从舞台的顶部或底部牺牲一些像素空间。

在以下示例中,状态栏将覆盖并遮挡舞台顶部的内容:

stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.BOTTOM_LEFT;

而以下代码片段将舞台直接放置在状态栏下方,裁剪掉舞台底部的内容:

stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;

在任何情况下,你还需要导入flash.display.StageScaleModeflash.display.StageAlign类。

注意

状态栏在 iPad 上也消耗 20 个垂直像素。

包含文件

在 AIR for iOS 设置面板的底部是 包含的文件 列表,其中包含要捆绑到你的 .ipa 文件或用于编译的资源。

默认情况下,列表中会出现两个文件:代表你的应用程序的 .swf 文件以及一个名为应用程序描述符文件的 XML 文件。应用程序描述符文件包含整个应用程序的属性,包括在 AIR for iOS 设置面板中设置的属性。

可以通过将它们添加到列表中来将附加文件捆绑到你的 IPA 中。我们将在本书的各个部分看到如何做到这一点以及为什么它是有用的。

相关内容

  • 包含应用程序启动图像,第三章

  • 编辑应用程序描述符文件,第三章

AIR for iOS 部署设置

我们几乎准备好从 Flash 发布原生 iOS 应用程序了。现在实际上是时候使用你在 第一章,开始 iOS 应用程序开发中创建的开发文件了。作为部署过程的一部分,Flash Professional 需要你的 P12 证书文件和你的开发配置文件。没有这些文件,它将无法将你的 FLA 编译成原生 iOS 应用程序。

让我们通过配置 iOS 部署设置的步骤进行说明。

准备工作

在尝试此配方之前,你需要创建一个 P12 证书文件和一个开发配置文件。如果你还没有这样做,那么首先完成以下配方:

  • 使用 Windows 创建 P12 证书,第一章

  • 使用 Mac OS X 创建 P12 证书,第一章

  • 创建开发配置文件,第一章

你还应该在 Flash Professional 中设置你的通用 iOS 设置,这在 AIR for iOS 通用设置 配方中已有介绍。

如何做...

你将再次在 AIR for iOS 设置面板中工作。

  1. 通过从 Flash Professional 的下拉菜单中选择 文件 | AIR for iOS 设置 来打开 AIR for iOS 设置 面板。

  2. 点击设置面板中的 部署 选项卡。

    从这里你将能够设置以下内容:

    • 用于数字签名你的应用程序所需的 P12 证书文件

    • 与你的应用程序关联的配置文件

    • 应用 ID

    • 要使用的部署类型

  3. 让我们先指定 P12 证书文件。点击 证书 字段右侧的 浏览 按钮。从文件浏览器中,导航到你的 Documents 文件夹中的 packt\flash-ios-cookbook\developer-files\。选择 .p12 文件,然后点击 打开

  4. 在直接位于下方的密码字段中,输入与你 P12 证书关联的密码。这是你在第一章中从使用 Windows 创建 P12 证书菜谱或使用 Mac OS X 创建 P12 证书菜谱中设置的导出密码。

  5. 此外,直接在密码字段下方勾选记住本次会话的密码复选框。

    注意

    记住本次会话的密码选项将防止 Flash 在每次发布 FLA 时要求你输入密码。然而,每次重新启动 Flash 时你都需要再次输入密码,因为它仅在会话基础上存储。

  6. 现在 Flash Professional 知道要使用哪个证书,你可以指定应用要关联的配置文件

    点击配置文件字段右侧的浏览按钮,从developer-files文件夹中选择.mobileprovision文件。

  7. 直接位于下方的应用 ID字段期望一个唯一的标识符。为此应用输入bubbles作为 ID。

  8. 最后一步是选择部署类型。

    默认情况下应选择快速发布以进行设备测试选项。如果没有选择,请选择它。

  9. 点击确定并保存你的 FLA。

它是如何工作的...

你的 FLA 现在已准备好编译成原生 iOS 应用。实际上,你可以直接从AIR for iOS 设置面板发布应用,但我们将在下一个菜谱中再进行发布。

更多...

在继续之前,花些时间了解应用 ID 和部署类型设置的作用是值得的。

指定应用 ID

你可能记得在第一章中创建开发配置文件菜谱中创建并关联应用 ID。

应用 ID 由两部分组成:包种子 ID 和包标识符。Flash Professional 期望你只提供包标识符。

如果你的包标识符包含通配符符号*,那么你需要用代表你应用的任意字符串替换该符号。通配符应用 ID 允许你使用相同的配置文件发布多个应用。

与你的配置文件关联的应用 ID 仅是通配符符号,这意味着你需要在 Flash Professional 中的应用 ID字段中输入一个完全由你选择的任意字符串。

在这种情况下,分配与应用名称相关的应用 ID 是有意义的,使得bubbles成为本章示例应用的合适 ID。

部署类型

在 Flash Professional 中,有四种不同的部署类型可供选择:

  • 快速发布以进行设备测试

  • 快速发布以进行设备调试

  • 部署—Ad hoc

  • 部署—Apple App Store

在开发时,你只需要从前两个中选择。

从 Flash Professional,快速发布以进行设备测试 选项是部署和运行设备上应用的最快途径。但是,如果你想直接从设备调试你的应用,那么你需要选择 快速发布以进行设备调试,这将允许你使用 Flash Professional 的远程调试器查看 trace() 语句并在断点处暂停你的应用程序。

剩余的部署类型是用于构建准备进行公测或 App Store 提交的应用,你需要拥有一个分发证书。

有关分发详情,请参阅 程序用户指南分发 部分,该部分可在 iOS 配置文件门户的 资源 部分找到。

参见

  • 获取你的开发证书,第一章

  • 创建 App ID,第一章

  • 创建开发配置文件,第一章

从 Flash Professional 编译

在 iOS 设置成功配置后,你可以继续将你的 FLA 文件编译成原生应用。

准备工作

如果你还没有为你的应用配置 iOS 设置,那么在继续之前,请执行以下两个步骤:

  • AIR for iOS 通用设置

  • AIR for iOS 部署设置

如何操作...

将你的 FLA 文件从 Flash Professional 编译成原生 iOS 应用可能需要几分钟,具体取决于你的计算机硬件配置。因此,建议首先使用 AIR 调试启动器 (ADL) 发布你的 FLA 文件。这将让你在尝试构建原生 iOS 版本之前快速找到并纠正任何编译错误。

让我们使用 ADL 快速发布 bubbles.fla

  1. 从 Flash Professional 的下拉菜单中选择 控制 | 测试影片 | 在 AIR 调试启动器 (移动) 中。

  2. 如果成功,将发布一个 .swf 文件并在 ADL 中运行。你应该能看到本章前面在 将内容添加到舞台 菜单中创建的场景。

    注意

    目前,你的 SWF 将只显示一个静态场景,其中包含各种大小的气泡,背景是静态的。随着我们在本章和下一章中添加更多功能,bubbles.fla 文件将变得更加动态。

    • 如果有任何编译错误,请纠正它们并重新发布。你可以通过按 Ctrl + Enter(在 Mac 上为 Cmd + Enter)而不是每次都使用下拉菜单来执行后续发布尝试。

      一旦你确信已经消除了所有编译错误,你就可以发布你的 FLA 文件以在 iOS 设备上部署。

  3. 要这样做,只需从 Flash 的下拉菜单中选择 文件 | 发布 (Alt + Shift + F12 | Shift + Cmd + F12),编译过程将开始。

注意

如果出现 AIR for iOS 设置 面板,那么很可能是 Flash 需要再次输入你的证书密码。这可能会发生如果你忘记勾选 记住此会话的密码 复选框,或者如果你在关闭 Flash 后重新启动了它。

在任何情况下,输入密码,勾选复选框,然后点击面板底部的发布按钮。

如果成功,将输出一个名为 bubbles.ipa 的文件到你的 FLA 所在的同一文件夹。

它是如何工作的...

.ipa 文件是应用的原生 iOS 版本,是你安装到设备上进行测试的文件。

为了将你的应用的 .swf 文件交叉编译成 .ipa 文件,Flash Professional CS5 会调用 iPhone 打包器 (PFI),而 CS5.5 会调用 AIR 开发工具 (ADT)

编译时间可能会很长,尤其是对于大型项目。

虽然没有真正的替代品可以替代实际的设备测试,但你可能想从 ADL 测试你应用的微小增量更改。这可以节省相当多的时间,但请注意,并非所有 iOS 功能都支持桌面,并将需要在设备上进行测试。

此外,Adobe 在 AIR 2.7 中引入了一个新的构建目标,称为 解释器模式,将编译时间从几分钟缩短到几秒钟。这个功能针对的是高级开发者,因为它需要使用命令行。

还有更多...

你可能好奇为什么编译 .ipa 文件比使用 ADL 发布 .swf 文件花费的时间要长得多。以下部分可能有助于你的理解。

LLVM 编译器基础设施

而不是在运行时被解释,编写了一个编译器将 .swf 文件转换为原生 iOS 应用程序。

这是通过使用广泛使用的开源 低级虚拟机 (LLVM) 编译器基础设施实现的。Adobe 为 LLVM 创建了一个新的编译器前端,使其能够理解 ActionScript 3.0。然后使用 LLVM 现有的 ARM 后端输出原生 ARM 机器代码,这是 iOS 设备中使用的 CPU 能够理解的。这通常被称为 提前编译

虽然你的应用是用 Flash 编写的,但最终结果是完全原生的 iOS 应用程序。

然而,提前编译的过程相当复杂,并且比简单地从 Flash 发布 .swf 文件花费的时间要长得多。

你可以在 llvm.org 上了解更多关于 LLVM 的信息。

使用 iTunes 安装你的应用

一旦你将你的 FLA 编译成 .ipa 文件,它就可以安装到你的设备上进行测试。有各种应用程序可供使用,其中之一是 iTunes。

让我们看看这是如何操作的。

准备工作

你必须已经在你设备上安装了你从 Flash Professional 编译 IPA 时使用的相同的配置文件。

如果您还没有这样做,那么首先执行第一章中详细说明的在您的设备上安装配置文件的步骤。

如何操作...

  1. 启动 iTunes 并通过 USB 连接您的 iOS 设备。

  2. 从 iTunes 的下拉菜单中选择File | Add File to Library (Ctrl + O | Cmd + O)

    注意

    在 Mac OS X 上,下拉菜单选项列出的为Add to Library

  3. 在文件浏览器中,导航到并选择您想要安装的.ipa文件。对于这个菜谱,只需找到您之前创建的bubbles.ipa文件。您应该能在Documents文件夹中的packt\flash-ios-cookbook\my-first-app\bubbles.ipa找到它。

  4. .ipa文件将在 iTunes 上安装。通过检查您的 iTunes 库中名为Bubbles的应用程序来确认这一点。您可以通过单击 iTunes 中LIBRARY部分下方的Apps类别来查看您的已安装应用程序。

  5. 最后一步是将应用程序从您的电脑的 iTunes 库移动到您的设备上。

    在 iTunes 的DEVICES部分下方,单击您的设备名称。默认情况下,您将看到设备的摘要信息。摘要信息上方有一行标签。单击Apps标签。

  6. 从这里,您可以同步您的设备库与电脑上的库。在左侧,您将找到存储在您电脑上的应用程序列表,而在右侧是您设备上安装的应用程序列表。将左侧的列表向下滚动,直到找到Bubbles应用程序。如果它尚未被选中,请检查其旁边的复选框。

  7. 现在要将应用程序复制到您的设备,请单击 iTunes 右下角底部的Apply按钮。

    注意

    Apps标签页,确保选中了Sync Apps复选框。如果没有,那么您必须先手动同步您的设备,才能将最新版本的应用程序复制到您的设备上。

  8. 在您的设备上找到Bubbles应用程序,并通过轻触其图标来启动它。

注意

在较旧的 iOS 设备(如第一代和第二代 iPhone 和 iPod touch)上,您可能会发现一些应用程序在首次启动时性能特别缓慢。这通常是由于您的设备在同步到电脑后,在后台更新其库所导致的。

如果您遇到问题,那么在启动应用程序之前,您可能想要等待此更新过程完成。您可以通过从主屏幕选择音乐应用程序来检查您的设备库是否正在更新。如果库目前正在更新,您将收到通知并被阻止从您的音乐库中选择。

它是如何工作的...

使用 iTunes 复制您的应用程序是一个相当简单的过程,但为了使该过程成功,您创建并从 iOS 配置文件门户获得的开发文件必须一切正常。

如果有问题,那么您的应用程序可能无法复制到您计算机上的 iTunes 库,或者无法安装到您的设备上。如果您遇到这些问题中的任何一个,那么可能是因为以下一个或多个原因:

  • 您的配置文件尚未复制到 iTunes 库中。

  • 您的配置文件尚未复制到您的设备上。

  • 配置文件已过期。

  • 该设备尚未与配置文件注册。

  • IPA 使用与设备上不同的配置文件编译。

  • 在 Flash 中指定的 App ID 与配置文件的捆绑标识符模式不匹配。

  • 您的开发计算机的防火墙可能会干扰您应用程序的安装。如果所有其他方法都失败,请禁用防火墙并重试将应用程序安装到您的设备上。

不幸的是,当应用程序安装失败时,您从 iTunes 收到的错误可能难以理解。如果您确实遇到问题,并且您仍在 iOS 开发中寻找方向,那么删除您的开发文件并再次通过配置过程可能更好。

更多...

我们已将我们的第一个应用程序部署到我们的设备上。当您安装和测试应用程序的后续版本时,您应该考虑下一节中提到的配置。

更新版本号

每次您制作一个希望在您的设备上测试的新构建时;您还需要从 Flash 的 AIR for iOS 设置面板更新您应用程序的版本号。

如果您忘记这样做,那么在同步时,iTunes 不会将最新版本的应用程序复制到您的设备上;iTunes 只会用版本号更高的应用程序替换现有的应用程序。

然而,每次构建时更新版本号很容易被忽略。为了更快速的开发,您可能希望在安装最新版本之前,从您的设备上删除现有版本的应用程序。

要直接从您的设备中删除应用程序,只需将手指放在图标上几秒钟,然后点击出现在其右上角的对勾。

iPhone Configuration Utility

作为 iTunes 的替代方案,您可能想要考虑从 Apple 下载并安装 iPhone 配置实用工具。

它允许您从您的设备安装和删除应用程序,并让您查看实际安装的应用程序版本——这是 iTunes 目前无法做到的。

iPhone 配置实用工具适用于 Mac OS X 和 Windows,可以从www.apple.com/support/iphone/enterprise下载。

TestFlight

对于团队环境,请查看TestFlight。它是一个免费空中平台,用于在开发和测试期间向团队成员分发应用程序。该服务允许 iOS 开发者创建团队,邀请团队成员,添加团队成员的设备,并将他们的最新构建分发给他们。

每次新构建都会通过一封包含安装链接的电子邮件发送给测试人员。点击链接将无线下载并安装构建到设备上。团队成员无需将设备物理连接到计算机即可安装构建。

您可以在testflightapp.com.注册 TestFlight。

第三章。编写您的第一个应用程序

在本章中,我们将介绍:

  • 创建基本文档类

  • 防止屏幕空闲

  • 处理多任务

  • 优雅地退出应用程序

  • 将类链接到电影剪辑符号

  • 使用更新循环

  • 包含应用程序启动图像

  • 包含图标

  • 编辑应用程序描述文件

  • 远程调试

简介

您现在应该能够从 Flash Professional 编译和部署原生 iOS 应用程序。在本章中,我们将继续上一章的内容,基于我们的 FLA 创建我们的第一个 iOS 应用程序。

虽然与针对桌面计算机相比有一些差异,但使用 Flash 编写 iOS 应用程序的过程对任何 Flash 开发者来说都会感到熟悉。在这个过程中,我们将介绍一些最佳实践,并让您亲身体验使用一些基本的 ActionScript 编写简单应用程序是多么容易。我们还将通过添加默认启动图像和图标图形来为应用程序添加最终修饰。

创建基本文档类

虽然您可以直接在时间轴上编写 ActionScript 3.0 代码,但这并不是推荐的做法。相反,您真的应该采用更面向对象的方法,并开发自己的自定义类。这在大型项目中尤为重要。

大多数 ActionScript 开发者应该已经熟悉创建类,但我们将在这里介绍这些步骤以避免疑问。特别是,这个配方将指导您创建一个基本的文档类,该类可以应用于上一章中开始的示例应用程序。

准备工作

我们将使用 bubbles.fla 的最新版本进行工作,该版本来自 第二章。或者,您也可以从书籍的配套代码包中打开 chapter3\recipe1\bubbles.fla

如何操作...

按照以下步骤创建文档类:

  1. 首先,请确保您的舞台上的实例没有被选中。然后,从 属性 面板中的 发布 部分,点击 字段旁边的铅笔图标。

    将会显示 创建 ActionScript 3.0 类 对话框。

  2. 在对话框中,您可能被要求选择哪个应用程序用于创建 ActionScript 3.0 类。如果被提示,请选择 Flash Professional 单选按钮。

  3. 类名 字段中输入 Main 并点击 确定

    将创建一个名为 Main 的骨架类,并在 Flash IDE 的新标签中显示。

  4. 通过从 Flash 的下拉菜单中选择 文件 | 另存为 (Ctrl + Shift + S | Shift + Cmd + S) 来保存类。当提示时,将文件命名为 Main.as 并将其保存在与 bubbles.fla 相同的文件夹中。

  5. 通过单击其标签返回到 bubbles.fla

    注意

    您创建或打开的每个类都将作为一个标签显示,与任何当前打开的 FLA 文件一起。您可以直接在 Flash Professional 的下拉菜单中找到这些标签。

    • 您现在已经有一个与您的 FLA 相关的文档类。
  6. 通过使用 ADL 测试您的 FLA 来确保没有编译错误。您可以通过从 Flash 的下拉菜单中选择控制 | 测试影片 | 在 AIR 调试启动器(移动)来完成此操作。或者,如果您之前已从 ADL(移动)测试过,只需按Ctrl + Enter (Mac 上的 Cmd + Enter)即可。

它是如何工作的...

文档类为您的应用程序提供了一个主要入口点。您添加到类构造函数中的任何代码在应用程序启动时都会执行,这为您提供了一个理想的位置来执行初始化。

下面是构造函数当前的样子:

public function Main() {
//constructor code
}

如您所见,构造函数目前是空的,但在本章剩余部分将会发生变化。

更多内容...

下面是关于类创建的几个更多要点。

命名文档类

文档类的名称并不重要。您可以为类选择任何有效的名称;然而,在本书中,我们将遵循为每个新应用程序命名文档类为Main的惯例。

使用包

由于本章示例的简单性,将所有代码添加到与bubbles.fla相同的文件夹中就足够了。当然,对于更复杂的项目,您可能会将类打包到单独的子文件夹中,以防止与第三方编写的类发生命名空间冲突。

使用 Flash Builder 进行编辑

一些开发者认为 Flash Professional 的代码管理和编辑功能过于有限。Adobe 通过将 Flash Professional 与 Flash Builder 集成来解决这个问题。

Flash Builder是一个功能强大的编码环境,它提供的功能超过了 Flash Professional 所提供的。现在您可以从 Flash Builder 中编辑和编译您的 iOS 项目。

当您在 Flash Professional 中创建类时,您将可以选择是否直接在 Flash Professional 中编辑该类,或者打开并使用 Flash Builder 进行代码编辑。

本书不会涵盖 Flash Builder,但您可以从 Adobe 网站www.adobe.com/downloads购买或下载试用版。

虽然您可以使用其他第三方 IDE,如 Flash Develop 和 FDT,来编辑您的 ActionScript,但它们不能直接从 Flash Professional 启动。

创建其他 ActionScript 3.0 类

可以从 Flash Professional 创建其他自定义 ActionScript 3.0 类。然而,这些类文件是从 Flash Professional 的下拉菜单创建的。

简单地选择文件 | 新建 (Ctrl + N | Cmd + N)以打开新建文档面板。从这里,您可以选择ActionScript 3.0 类类型并为类提供名称。

参见

  • 将类链接到电影剪辑符号

防止屏幕空闲

为了节省电池寿命,移动设备在最后一次触摸后不久会锁定屏幕。然而,对于用户可能不会经常与屏幕交互的应用程序来说,这可能是不方便的。

对于这种情况的应用,可以禁用屏幕锁定。

准备工作

我们将在之前菜谱中创建的骨架文档类中添加代码。如果你还没有这样做,那么在继续之前,请完成创建基本文档类菜谱。或者,使用本书的配套代码包,在 Flash Professional 中打开chapter3\recipe2\bubbles.fla,并从那里开始工作。

如何做...

让我们编写一些 ActionScript 来禁用屏幕锁定:

  1. 通过从 Flash Professional 的下拉菜单中选择文件 | 打开 (Ctrl + O | Cmd + O) 来打开 FLA 文档类。从文件浏览器中选择Main.as

  2. 将以下两个导入语句添加到你的类中:

    import flash.display.MovieClip;
     import flash.desktop.NativeApplication;
    import flash.desktop.SystemIdleMode; 
    
    
  3. 为了防止屏幕空闲时设备锁定,这两个类都是必需的。

  4. 创建一个成员变量,用于存储一个NativeApplication对象:

    public class Main extends MovieClip {
    private var application:NativeApplication; 
    
    
  5. 在构造函数中,获取一个NativeApplication引用并将其存储在你的application成员变量中:

    public function Main() {
    application = NativeApplication.nativeApplication; 
    }
    
    
  6. 使用application变量强制设备的屏幕保持唤醒状态:

    public function Main() {
    application = NativeApplication.nativeApplication;
    application.systemIdleMode = SystemIdleMode.KEEP_AWAKE; 
    }
    
    
  7. 保存你的类文件。

  8. 通过单击其选项卡来移动到你的 FLA,并通过从下拉菜单中选择文件 | AIR for iOS 设置来打开 AIR for iOS 设置面板。

  9. 从设置面板中,确保已选择常规选项卡,并将版本字段更新为0.2

  10. 点击确定并保存你的 FLA。

  11. 现在,通过使用 ADL 测试你的电影来检查 FLA 中是否存在任何编译时错误。

    一旦你确认没有错误,通过选择文件 | 发布 (Alt + Shift + F12 | Shift + Cmd + F12) 来发布你的 iOS 应用,并使用 iTunes 将生成的.ipa 文件部署到你的设备上。

  12. 启动应用。你应该注意到在应用的生命周期内,屏幕不会变暗或锁定。

注意

每次你想将新构建部署到设备时,都需要增加应用版本号。如果你启动应用后没有看到任何变化,那么很可能是版本问题。

为了测试目的,将你的 iOS 设备的自动锁定时间设置为最短持续时间。你可以通过在 iOS 设备上选择设置 | 通用 | 自动锁定来完成此操作。这将减少你等待确认在应用中禁用自动锁定所需的时间。

如何工作...

NativeApplication类提供了一个systemIdleMode属性,可以设置为允许或防止你的设备屏幕锁定。从NativeApplication,你还可以获取应用信息,访问应用级函数,并捕获应用级事件。

在代码示例中,我们将systemIdleMode设置为SystemIdleMode.KEEP_AWAKE,确保在应用的生命周期内屏幕不会锁定。可以通过将SystemIdleMode.NORMAL重新启用来自动锁定。

为了防止过度使用电池,建议谨慎使用SystemIdleMode.KEEP_AWAKE。你可能只想在绝对必要时禁用应用程序内的自动锁定。

此外,你可能已经注意到你的代码中没有显式创建NativeApplication的实例。NativeApplication是一个单例对象,当你的应用程序启动时自动创建。只能存在一个实例,并且通过使用类的静态nativeApplication属性来访问。

处理多任务

iOS 4 或更高版本支持多任务处理。当用户通过按设备的主按钮退出应用程序时,应用程序会被移动到后台而不是完全关闭。这也可以由多种其他原因引起,例如用户接受来电或应用程序本身启动另一个应用程序。

当用户或其他应用程序再次启动应用程序时,它可以直接从上次离开的地方继续,而不是完全重新加载。这也显著减少了返回应用程序时的启动时间。

当你的应用程序被移动到后台或由操作系统恢复时,会触发事件。本食谱将解释如何监听和捕获这些事件。

准备工作

我们将扩展 Bubbles 应用程序,为我们的文档类提供可以处理应用程序移动到后台和恢复的方法。

此食谱是在防止屏幕闲置食谱的基础上进行的。

注意

AIR 2.0 SDK 不提供对 iOS 多任务处理的支持。如果你使用的是 Flash Professional CS5,则跳过此食谱,转到优雅退出应用程序食谱。

如何操作...

对你的文档类进行以下更改:

  1. 在 Flash Professional CS5.5 中打开Main.as

  2. 你将需要使用Event类。将其添加到你的导入语句列表中:

    import flash.display.MovieClip;
    import flash.desktop.NativeApplication;
    import flash.desktop.SystemIdleMode;
    import flash.events.Event; 
    
    
  3. 在构造函数中,监听NativeApplication触发Event.ACTIVATEEvent.DEACTIVATE

    public function Main() {
    application = NativeApplication.nativeApplication;
    application.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
    application.addEventListener(Event.ACTIVATE, activate);
    application.addEventListener(Event.DEACTIVATE, deactivate); 
    }
    
    
  4. 为每个事件添加处理程序:

    private function deactivate(e:Event):void {
    application.systemIdleMode = SystemIdleMode.NORMAL;
    }
    private function activate(e:Event):void {
    application.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
    }
    
    
  5. 返回到你的构造函数并删除以下突出显示的行:

    public function Main() {
    application = NativeApplication.nativeApplication;
    application.systemIdleMode = SystemIdleMode.KEEP_AWAKE; 
    application.addEventListener(Event.ACTIVATE, activate);
    application.addEventListener(Event.DEACTIVATE, deactivate);
    }
    
    
  6. 这行代码不再需要,因为它现在由activate()方法执行。

  7. 保存你的类文件,并通过使用 ADL 测试bubbles.fla来检查任何编译时错误(Ctrl + Enter | Cmd + Enter)。

它是如何工作的...

当你的应用程序即将被移动到后台时,NativeApplication类会触发Event.DEACTIVATE事件。或者,当 iOS 恢复你的应用程序或它被启动时,会触发Event.ACTIVATE事件。你可以监听并响应这些事件,以便初始化你的应用程序,准备将其移动到后台,或再次激活。

在本食谱的示例中,我们只是利用了在应用程序启动或恢复时禁用自动锁定的机会,并在应用程序挂起时启用自动锁定。

更多内容...

你可能会对以下有关 iOS 多任务处理的信息感兴趣。

后台处理

iOS 上的大多数后台应用程序实际上是被挂起的。它们仍然在系统内存中,但实际处于暂停状态。这节省了 CPU 资源并增加了设备的电池寿命。

然而,某些类型的应用程序可以在后台继续运行而不是被挂起。这些应用程序被分配有限的 CPU 资源来执行一些特定的任务,例如播放音频或访问基于位置的信息。

在任何情况下,AIR 的 NativeApplication 类都会触发 Event.DEACTIVATE 事件。

应用程序关闭

不要假设您的后台应用程序将保留在内存中。

用户或操作系统本身可能会决定关闭您的应用程序。如果您的应用程序被用户关闭,那么您可能会获得保存其状态和执行任何最终清理代码的机会。

从应用程序中优雅地退出

在 iOS 3 设备上按下主页按钮将关闭当前应用程序并将其从内存中移除。在运行 iOS 4 或更高版本的设备上执行相同操作将应用程序置于挂起或后台状态,而不是关闭它。然而,用户可以使用快速应用程序切换器关闭并从内存中移除这些应用程序。此外,当系统内存不足时,iOS 本身可能会决定关闭挂起或后台应用程序。

如果用户决定关闭您的应用程序,那么在它退出之前,您将有机会执行任何必要的维护操作,例如保存状态或释放内存。

准备工作

我们将在您的 Bubbles 应用程序的当前版本中添加一些代码,使其能够优雅地退出。或者,从本书的配套代码包中打开 chapter3\recipe4\bubbles.fla 并从那里开始工作。

如何操作...

让我们监听并处理 Bubbles 应用程序被关闭:

  1. 在 Flash Professional 中打开 Main.as 文件。

  2. 我们将使用 Event 类。确保将其添加到您的类的导入语句列表中:

    import flash.display.MovieClip;
    import flash.desktop.NativeApplication;
    import flash.desktop.SystemIdleMode;
    import flash.events.Event; 
    
    
  3. 在构造函数中,监听 NativeApplication 对象触发的 Event.EXITING 事件:

    application.addEventListener(Event.EXITING, exiting);
    
    
  4. 添加一个事件处理器,在您的应用程序退出之前执行任何必要的清理操作:

    private function exiting(e:Event):void {
    application.removeEventListener(Event.EXITING, exiting);
    application.systemIdleMode = SystemIdleMode.NORMAL; 
    }
    
    
  5. 如果您正在使用 Flash Professional CS5.5 并已完成之前的配方——处理多任务——那么请将以下行添加到您的 exiting() 事件处理器中:

    private function exiting(e:Event):void {
    application.removeEventListener(Event.ACTIVATE, activate);
    application.removeEventListener(Event.DEACTIVATE, deactivate);
    application.removeEventListener(Event.EXITING, exiting);
    application.systemIdleMode = SystemIdleMode.NORMAL;
    }
    
    
  6. 保存您的类文件并检查任何编译时错误。

它是如何工作的...

每当您的应用程序即将退出时,NativeApplication 类会触发 EXITING 事件。通过响应此事件,您可以执行任何必要的清理操作,例如保存状态或释放内存。

您还可能注意到在 exiting() 方法中,我们已经利用机会重新启用自动锁定。尽管 iOS 应该在您的应用程序退出时为您启用自动锁定,但明确在代码中这样做是一种良好的实践。

进行其他形式的清理也是良好的实践,例如移除事件监听器,我们也已经这样做。从对象中移除事件监听器很重要,因为不这样做是内存泄漏的常见原因。这适用于应用程序的整个生命周期,而不仅仅是退出时。

还有更多...

最后,关于退出序列的更多细节。

应用切换器

在 iOS 4 或更高版本上,你必须使用快速应用切换器显式地关闭一个应用。要访问应用切换器,双击主屏幕按钮。要关闭一个应用,点击并按住其图标,直到图标角落出现减号符号。点击减号符号,应用将从后台移除。这将强制Event.EXITING从应用中发出,当它正在关闭时。

清理工作

除了保存应用程序的状态外,你还应该对Event.EXITING事件做出必要的清理响应。你的应用通过完全释放内存来自我清理是很重要的。你应该销毁任何对象,移除你添加的任何剩余的事件监听器,停止任何仍在运行的计时器和时间轴动画,停止所有正在播放的声音,取消任何网络请求,最后关闭任何套接字、文件流或数据库连接。

脚本执行时间

确保你的事件处理程序中的代码尽可能快地执行。如果它需要超过几秒钟,iOS 可能会提前终止你的应用程序。如果在保存状态信息到设备的过程中发生这种情况,这可能会特别有害。

为了最大限度地减少超时的可能性,在退出过程中尽量减少保存的数据量。你还应该确保在执行任何其他清理任务之前保存数据。这将增加在执行长时间退出和清理操作时保存应用程序状态的可能性。

将类链接到电影剪辑符号

通过创建和将自定义类链接到电影剪辑符号,可以给电影剪辑符号添加额外的行为。通常,该类会监听并响应由电影剪辑发出的事件。其中,Event.ENTER_FRAME是最广泛使用的,它提供了一种在每一帧重绘时程序化更新电影剪辑外观的方法。

我们将编写一个自定义类,使我们的示例应用最新版本中的每个气泡向上浮动。

如何做到这一点...

让我们编写一个自定义类并将其链接到每个气泡:

  1. 在 Flash Professional 中选择文件 | 新建 (Ctrl + N | Cmd + N)。从新建文档面板中,创建一个ActionScript 3.0 类并将其命名为Bubble。将创建一个骨架类。

  2. 将以下代码添加到类中:

    package {
    import flash.display.Sprite;
    import flash.events.Event;
    public class Bubble extends Sprite {
    private var _speed:Number = 1;
    public function Bubble() {
    addEventListener(Event.ENTER_FRAME, enterFrame);
    }
    public function set speed(s:Number):void {
    _speed = s;
    }
    private function enterFrame(e:Event):void {
    y -= _speed;
    if(y < -(height / 2))
    {
    y = stage.stageHeight + (height / 2) + (height * Math.random());
    x = -(width / 2) + ((stage.stageWidth + width) * Math.random());
    }
    }
    }
    }
    
    
  3. 将类保存为与Main.as相同的文件夹中的Bubble.as。通过点击其标签返回到你的 FLA。

  4. 现在,你可以将你的Bubble类链接到库中每个气泡电影剪辑符号。让我们从Bubble Huge开始。

    移动到 LIBRARY,右键单击 Bubble Huge,然后选择 Properties

  5. Symbol Properties 对话框的 Advanced 部分中勾选 Export for ActionScript 复选框。Class 字段将包含你的符号名称,但空格将被移除。在 Base Class 字段中,将现有文本替换为 Bubble,如以下截图所示:如何操作...

  6. 点击面板右上角的 OK 按钮。

  7. 根据你在 Flash Professional 中的偏好设置,可能会出现一个包含以下文本的警告面板:

    在类路径中找不到此类的定义,因此将在导出 SWF 文件时自动生成。

    这是预期的。虽然你已经编写了代表符号基类的代码,但你将依赖 Flash 生成符号实际类的代码。点击 OK 按钮。

  8. 重复此过程,将 Bubble 类链接到以下电影剪辑符号:Bubble Large, Bubble Medium, 和 Bubble Small

  9. 保存你的 FLA 文件,并使用 ADL 进行测试。你应用中之前静止的气泡现在将向上漂浮屏幕。

它是如何工作的...

该类的结构相当传统。其核心是一个事件处理器,每当电影剪辑派发 Event.ENTER_FRAME 事件时都会被调用。在处理器内部是控制并更新剪辑的逻辑。

在我们这个例子中,类的 enterFrame() 处理器用于在每一帧重绘时更新气泡的位置。如果气泡移出屏幕顶部,那么它将被随机重新定位到屏幕底部,在那里它可以再次开始向上漂浮。

使用名为 _speed 的私有成员变量来定义气泡每次在 Event.ENTER_FRAME 被派发时移动的像素数。尽管它尚未被使用,但类中添加了一个公共设置器,允许使用 speed 属性更改气泡的垂直速度。

虽然在你的演示中不会很明显,但过度使用 ENTER_FRAME 事件实际上会降低你 iOS 应用的性能。我们将在下一个菜谱中解决这个问题,并整理演示中气泡的移动。目前,由于所有气泡都以相同的速度移动,深度感已经丢失。

还有更多...

你可能已经注意到,你的 Bubble 类实际上扩展了 Sprite 而不是 MovieClip。以下就是原因。

扩展精灵

虽然库中的气泡实际上是电影剪辑,但 Bubble 类是从 flash.display.Sprite 继承,而不是从 flash.display.MovieClip 继承。

扩展 MovieClip 是完全可以接受的,但考虑到气泡库符号仅使用其时间轴上的单个帧,实际上是不必要的。只有当你打算导航剪辑的时间轴时,才需要扩展 MovieClip;否则,Sprite 提供的功能就足够了,并且开销更小。

使用更新循环

监听事件可能会很昂贵。为了处理程序能够接收一个事件,Flash 必须在内存中创建一个代表该事件的对象。重复分配内存可能会损害应用程序的性能,尤其是当你从大量显示对象中监听 Event.ENTER_FRAME 时。

让我们看看如何通过调整示例应用程序的架构来最小化处理多个 ENTER_FRAME 事件的影响。我们还将添加一些额外的代码来单独控制每个气泡的速度,使应用程序更加完善。

如何做到这一点...

您将需要修改 Main.asBubble.as 中的代码:

  1. 首先打开 Bubble.as

  2. 在构造函数中,删除监听 Event.ENTER_FRAME: 的突出显示代码行。

    public function Bubble() {
    addEventListener(Event.ENTER_FRAME, enterFrame); 
    }
    
    
  3. 通过将 enterFrame() 方法重命名为 update() 并删除其 Event 参数来更改 enterFrame() 方法的签名。同时使其公开访问:

    public function update():void { 
    y -= _speed;
    if(y < -(height / 2))
    {
    y = stage.stageHeight + (height / 2) +
    (height * Math.random());
    x = -(width / 2) +
    ((stage.stageWidth + width) * Math.random());
    }
    }
    
    
  4. 删除不再需要的 Event 类导入语句:

    import flash.events.Event; 
    
    
  5. 保存类并移动到 Main.as

  6. 将以下两个成员变量添加到 Main.as 中:

    private var bubbles:Array;
    private var speeds:Array;
    
    
  7. 在类的构造函数中,填充 bubblesspeeds 数组。bubbles 数组将包含放置在 FLA 阶段上的每个气泡实例的引用。speeds 数组将包含用于每个气泡实例的垂直速度:

    bubbles = [bubble1, bubble2, bubble3, bubble4, bubble5, bubble6, bubble7, bubble8, bubble9];
    speeds = [1.3, 1.5, 1.8, 2, 2.2, 2.4, 4.5, 5, 8];
    
    
  8. 现在仍然在构造函数中,添加一些代码来遍历 bubbles 数组,使用 speeds 数组中的值设置每个气泡的垂直速度:

    for(var i:uint = 0; i < bubbles.length; i++)
    {
    bubbles[i].speed = speeds[i];
    }
    
    

    注意

    在前面的代码片段中,注意使用 speed 属性,该属性是在前面的配方中添加到 Bubble 类中的,将类链接到电影剪辑符号

  9. 通过在构造函数末尾放置以下语句来监听 ENTER_FRAME 事件:

    addEventListener(Event.ENTER_FRAME, update);
    
    
  10. exiting() 处理程序的末尾添加一行代码来删除 Event.ENTER_FRAME 监听器:

    removeEventListener(Event.ENTER_FRAME, update);
    
    
  11. 最后,向类添加一个 Event.ENTER_FRAME 事件处理程序,该处理程序调用每个气泡实例的 update() 方法:

    private function update(e:Event):void {
    for each(var b:Bubble in bubbles)
    {
    b.update();
    }
    }
    
    
  12. 保存类。

  13. 使用 ADL 测试 bubbles.fla

    注意

    在发布时,您可能会收到类似以下内容的编译错误列表:

    1120: 访问未定义属性 bubble1

    通常这发生在 Flash 没有被指示为每个显示对象实例在舞台中自动声明成员变量时。

    您可以通过勾选 Advanced ActionScript 3.0 Settings 面板中的 Automatically declare stage instances 复选框来纠正这一点。

    • 现在气泡将以更令人信服的方式移动,最近的气泡比远处的气泡移动得更快。更重要的是,应用程序的架构已经改变,不再需要每帧都监听和处理多个 ENTER_FRAME 事件。

    如何操作...

  14. AIR for iOS 设置 面板更新应用程序的版本号到 0.3 并发布它。

  15. 将生成的 .ipa 文件部署到您的设备并测试它。

它是如何工作的...

我们现在只有一个监听器,它会对每个气泡调用 update() 调用,而不是让每个气泡实例都监听和处理自己的 ENTER_FRAME 事件。

实际上,文档类中的 update() 方法充当应用程序的主循环。每个需要更新的对象都有自己的 update() 方法,该方法由文档类的主循环调用。

以下又是主要的更新循环:

private function update(e:Event):void {
for each(var b:Bubble in bubbles)
{
b.update();
}
}

在这个例子中,bubbles 数组被用作一个方便的机制来引用需要更新的每个气泡实例。您可以在主循环中看到它的使用。

在您的应用程序中使用集中式更新循环的优势不容忽视。在本章示例应用程序中,性能优势可能并不明显,但对于更复杂的项目,这项技术有助于在尝试实现一致且高帧率时发挥作用,尤其是在旧设备上。

包含应用程序启动图像

每个 iOS 应用程序都可以捆绑一个静态启动图像。当应用程序加载时,这将被显示给用户。

让我们在示例应用程序中添加一个启动图像。

如何操作...

我们将继续从 使用更新循环 的配方开始。如果您还没有完成它,那么您可以从书籍附带代码包中的 chapter3\recipe7\bubbles.fla 开始工作。

  1. 使用 Windows 资源管理器或 Finder,将 chapter3\resources\Default.png 复制到与您的 FLA 相同的文件夹中。

  2. 通过从 Flash 的下拉菜单中选择 文件 | AIR for iOS 设置 来重新访问 AIR for iOS 设置 面板。

  3. 如果它还没有被选中,请点击面板的 常规 选项卡。

  4. 在面板底部是 包含的文件 列表。点击列表上方的 + 符号,然后从您的 FLA 根目录中选择 Default.png。点击 确定 以选择文件。现在您应该在 包含的文件 列表中看到 Default.png

  5. 将应用程序的 版本 字段更改为 0.4

  6. 现在,点击 确定 以关闭 AIR for iOS 设置 面板。

  7. 保存 FLA。

如何操作...

发布并部署应用程序的最新版本到您的 iOS 设备。如图所示,当应用程序加载时,您应该看到启动图像。

它是如何工作的...

Default.png 文件是一个 24 位 320x480 的 PNG 图像,与 Bubbles 应用的初始视觉状态相匹配。此外,图像上还叠加了文本,以通知用户应用正在加载。一旦应用的二进制文件完全加载,iOS 将将其从视图中移除并运行应用。启动图像与你的应用第一帧之间的切换将是无缝的。

重要的是你的文件应命名为 Default.png,其中 D 为大写,因为 iOS 在加载你的应用时会寻找这个确切的文件名。如果你的图像找不到或未包含,则在应用加载期间将显示一个黑色屏幕。

你还应该确保将 Default.png 复制到与你的 FLA 相同的文件夹中。

还有更多...

将启动图像添加到你的应用中并不困难,但在支持多个 iOS 设备、屏幕分辨率和方向时,还有其他选项需要考虑。

横屏方向

对于为横屏设计的 iPhone 和 iPod touch 应用,你仍然需要嵌入一个 320x480 的 PNG 图像,但确保图像以该方向提供。

支持视网膜显示屏

对于具有视网膜显示屏的 iOS 设备,你可以将一个额外的启动图像捆绑到你的 IPA 中,该图像利用了更高的分辨率。只需创建一个 640x960 的 PNG 文件,并将其命名为 Default@2x.png。当在支持视网膜显示屏的设备上加载时,将使用 Default@2x.png 作为启动图像,而不是 Default.png

iPad 应用启动图像

与 iPhone 和 iPod touch 不同,在 iPad 上运行的 iOS 应用可以根据其方向选择多个启动图像。这是通过捆绑一系列 PNG 文件并带有方向修饰符字符串的文件名来实现的。

例如,如果用户在应用启动时手持设备为肖像方向,iOS 将寻找一个名为 Default-Portrait.png 的 PNG 文件。当手持设备为横屏时,iOS 将尝试显示 Default-Landscape.pngDefault-Portrait.png 的尺寸应为 768x1024,而 Default-Landscape.png 应为 1024x768。

通过包含一个名为 Default-PortraitUpsideDown.png 的 PNG 文件,甚至可以指定一个颠倒的肖像版本的应用启动图像。如果同时存在 Default-Portrait.png,则它将优先使用。

类似地,通过捆绑名为 Default-LandscapeLeft.pngDefault-LandscapeRight.png 的图像,可以在设备手持横屏方向时获得额外的控制。如果也存在 Default-Landscape.png,则这两个文件都将优先使用。

如果找不到具有方向修饰符的 PNG 文件,则将使用 Default.png

通用应用

可以嵌入一系列启动图像,覆盖所有 iOS 设备类型的各种屏幕分辨率和纵横比。例如,考虑一个通用应用程序,它可以利用 iPhone 的标准屏幕分辨率和 Retina 屏幕分辨率,以及 iPad 的纵向和横向方向。嵌入名为 Default.png, Default@2x.png, Default-Portrait.pngDefault-Landscape.png 的图像将覆盖这些。

使用状态栏

如果你计划在应用程序中包含状态栏,那么就没有必要减小启动图像的大小。状态栏消耗 20 个垂直像素(Retina 显示屏上的 40 个像素)并将简单地放置在图像顶部,当你的应用程序加载时。状态栏在 iPad 上也消耗 20 个垂直像素。

打包其他文件

在这个菜谱中,我们通过将其添加到 AIR for iOS 设置面板的包含文件列表中,将启动图像与我们的应用程序捆绑在一起。从这个面板中,你还可以包含其他文件或文件夹,这些文件或文件夹将与你的应用程序捆绑在一起,甚至可以在运行时使用 ActionScript 加载。像启动图像一样,要添加的其他文件或文件夹必须存在于 FLA 的根文件夹中。

参见

  • 针对设备,第八章

包含图标

我们的应用程序几乎完成了。最明显的遗漏是图标作品,我们现在将添加。

如何操作...

图标是从 AIR for iOS 设置面板中添加的。

  1. 移动到AIR for iOS 设置面板,并点击图标选项卡。

    从这里你可以将各种图标与你的应用程序捆绑在一起。图标类型列在面板顶部。

  2. 从列表中点击图标 29x29。图标列表下方直接的字段将被重新标记为29x29。在此字段右侧有一个浏览图标。点击它,如图下截图所示。浏览到并选择chapter3\resources\icon29.png如何操作...

  3. 将出现一个包含以下信息的对话框:

    图标必须复制到根内容文件夹的相对文件夹中,以便可以发布。你想继续吗?

    点击确定,将在与 FLA 相同的位置创建一个名为 AppIconsForPublish 的子文件夹。你选择的图标将被复制到这个新位置。

  4. 现在从列表中选择图标 57x57,并浏览到chapter3\resources\icon57.png。同样,你会被询问是否希望图标被复制到根内容文件夹的相对文件夹中。点击确定按钮。

  5. 逐个处理列表中的剩余图标,从 resources 文件夹添加适当的 PNG 文件。

  6. 一旦添加了图标,点击面板的常规选项卡,并将版本字段更新为0.5

  7. 点击确定以退出AIR for iOS 设置面板。

发布并部署应用程序的最新版本到你的设备。现在你的应用程序应该由 iTunes 和设备上的图标表示。

工作原理...

所有图标艺术作品都应创建并保存为 24 位 PNG 格式。不要在你的艺术作品中添加反射光泽、圆角或阴影,因为这些将由 iOS 应用。另外,考虑到你添加的最大图标是 512x512 像素,至少在这个尺寸设计你的原始图标艺术作品是有意义的;你不想需要放大一个较小的版本。

你实际上可以在你的应用中包含六个图标。以下是每个图标的描述:

  • 29x29—iPhone 3GS 的 Spotlight 搜索结果图标

  • 48x48—iPad 的 Spotlight 搜索结果图标

  • 57x57—iPhone 4/4S 的 Spotlight 搜索结果图标和 iPhone 3GS 的主屏幕图标

  • 72x72—iPad 的主屏幕图标

  • 114x114—iPhone 4/4S 的主屏幕图标

  • 512x512—iTunes 图标

注意

Flash Professional CS5 不支持 Retina 显示屏分辨率,因此不允许包含 iPhone 4/4S 主屏幕的 114x114 像素图标。将使用 57x57 像素的图标代替。

iPhone 3GS 的图标也适用于第三代 iPod touch,而 iPhone 4/4S 的图标适用于第四代 iPod touch。

尽管 Bubbles 应用只使用了标准的 320x480 分辨率,但这并不会阻止你为更高分辨率的屏幕(如 iPhone 4/4S 和 iPad)捆绑替代图标。

此外,iTunes 图标仅用于开发目的。当将你的最终应用提交到 App Store 时,你需要单独提交一个 512x512 像素的图标作为 JPEG 文件。它不包括在最终的.ipa文件中。虽然你应该确保 iTunes 图标可以被识别为你的应用程序图标,但使其外观更加丰富和详细是完全可接受的。此外,视觉效果,如反射光泽,不会添加到这个图标中。

至于你的图标艺术作品的设计,苹果的iOS 人类界面指南强调了在创建一个可以立即识别的图标时,强大视觉设计的重要性。你的图标必须以某种方式传达你的应用程序的目的。还请避免使用文本,并记住你的图标将在各种尺寸下被查看。在设计时使用矢量格式是明智的,因为这将在输出每个所需的位图版本之前允许图标进行缩放而不损失保真度。

编辑应用程序描述文件

与你的 FLA 一起提供的还有应用程序描述文件。这是一个 XML 文件,包含发布 AIR 应用程序时使用的设置。此文件还包含描述你的 iOS 应用程序的属性,包括在 AIR for iOS 设置面板中设置的属性。应用程序描述文件可以编辑,以进行无法直接从 Flash Professional 的各种设置面板中设置的更改。

让我们修改应用程序描述文件,以移除 iOS 应用于 Bubbles 应用图标的反射光泽。

准备中

对于这个配方,从您当前的 Bubbles 应用版本开始工作,或者使用随附代码包中提供的 FLA,位于 chapter3\recipe9\bubbles.fla

当您从 AIR for iOS 设置面板进行更改时,Flash Professional 会写入应用描述符文件。如果您打开了 AIR for iOS 设置面板,请在尝试从外部文本编辑器编辑应用描述符文件之前关闭它。

如何操作...

您也可以在 Flash 中打开并编辑应用描述符文件,这正是我们将要做的:

  1. 选择 文件 | 打开 (Ctrl + O | Cmd + O) 并选择 bubbles-app.xml

  2. 将 XML 文件向下滚动,直到找到以下 XML 片段:

    <iPhone>
    <InfoAdditions>
    <![CDATA[<key>UIDeviceFamily</key> <array><string>1</string></array>]]>
    </InfoAdditions>
    
    
  3. CDATA 节点是您可以添加额外的 iOS 设置信息的地方。请继续在 XML 中添加以下键值对:

    <iPhone>
    <InfoAdditions>
    <![CDATA[<key>UIDeviceFamily</key> <array><string>1</string></array>
     <key>UIPrerenderedIcon</key><true/>]]> 
    </InfoAdditions>
    
    
  4. 保存文件。

  5. 移动到您的 FLA,并从 AIR for iOS 设置 面板更新其 版本 字段为 0.6

发布 FLA 并将新的 .ipa 文件部署到您的设备上。您的应用主屏幕图标不再应用反射光泽。

它是如何工作的...

应用描述符文件使用输出 SWF 的名称命名,并采用以下格式:<swf_name>-app.xml。默认情况下,输出 SWF 名称与 FLA 的名称相同。

所有 iOS 特定设置都可以在 XML 文件的 <iPhone> 节点中找到。在 <iPhone> 节点中是 <infoAdditions> 节,您可以通过添加键值对来设置任何自定义 iOS 设置。这些键值对应放置在 CDATA 标签内。

在配方过程中,您添加了以下键值对以禁用图标的反射光泽:

<key>UIPrerenderedIcon</key><true/>

您也可以通过将值更改为 <false/> 或简单地完全删除键值对来重新启用光泽。在继续之前,请将值改回并重新编译您的应用。除非您有很好的理由,否则您真的应该保持默认的反射光泽启用。

虽然您将这些 iOS 特定设置应用到应用描述符文件中,但它仅针对 AIR 应用程序,并且不被 iOS 所理解。相反,当您发布 FLA 时,Flash 会生成一个配置文件并将其包含在您的 IPA 中,iOS 可以理解这个配置文件。这被称为 信息属性列表 文件,按照惯例命名为 Info.plist,其中包含许多用于描述您的应用的属性,包括您设置的任何自定义属性。

您可以通过访问苹果的 iOS 开发者库了解有关信息属性列表和可以设置的属性更多信息:developer.apple.com/library/ios/#documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html

还有更多...

尽管我们只使用了应用程序描述符文件来移除图标的反光光泽,但还有许多更多的配置选项。另一个常用的选项,已经在本章和上一章中提到过,是状态栏及其外观。

状态栏样式

在 iPhone 和 iPod touch 上,可以更改状态栏的外观;iPad 上无法更改状态栏,它始终为黑色。虽然你可以在应用程序中指定是否显示状态栏,但 Flash 没有提供任何控制外观的选项。如果你决定使用状态栏,你可以将UIStatusBarStyle键添加到应用程序描述符文件中,以设置 iOS 支持以下三种样式之一:

  • UIStatusBarStyleDefault — 默认灰色状态栏

  • UIStatusBarStyleBlackOpaque — 不透明的黑色状态栏

  • UIStatusBarStyleTranslucent — 具有透明度为 50%的黑色状态栏

要选择不透明的黑色状态栏,请将以下键值对添加到应用程序描述符文件中:

<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleBlackOpaque</string>

尝试使用UIStatusBarStyleBlackOpaqueUIStatusBarStyleTranslucent。你的选项有限,但它们可以在某些默认状态栏与设计不匹配的应用程序中派上用场。如果你想使用默认状态栏,则无需在应用程序描述符文件中显式添加键值对。

参见

  • 指定持久的 Wi-Fi 连接,第十三章

  • 声明设备功能,第十三章

远程调试

调试是开发过程中的一个关键方面。Flash Professional 允许你将设备上的调试信息直接发送到 Flash IDE 进行检查。

在完成示例 Bubbles 应用程序后,我们将通过学习如何使用 Flash Professional 的远程调试器部署调试构建并从中接收跟踪数据来结束本章。

准备工作

我们将在本课程和上一章中创建的 Bubbles 应用程序的文档类中添加一行 ActionScript。或者,从本书的配套代码包中,在 Flash Professional 中打开chapter3\recipe10\bubbles.fla,并从那里开始工作。

如何操作...

调试过程分为两个主要步骤:

  • 创建调试构建

  • 连接到远程调试器

让我们首先创建一个包含单个跟踪语句的调试构建。

创建调试构建

按照以下步骤操作:

  1. 如果你还没有这样做,请通过从 Flash Professional 的下拉菜单中选择文件 | 打开 (Ctrl + O | Cmd + O) 来打开文档类。从文件浏览器中,选择Main.as

  2. 在类的构造函数开头添加一个简单的trace()语句:

    public function Main() {
    trace("Inside the constructor."); 
    
    
  3. 保存你的更改,并点击其标签返回到 FLA。

  4. 通过从下拉菜单中选择文件 | AIR for iOS 设置来打开 AIR for iOS 设置面板。

  5. 在设置面板中,确保已选择常规选项卡,并将版本字段更新为0.7。现在转到部署选项卡,并在iOS 部署类型部分选择设备调试的快速发布

  6. 点击确定并保存您的 FLA。

  7. 现在通过选择文件 | 发布(Alt + Shift + F12 | Shift + Cmd + F12)来发布您的 FLA 以供 iOS 使用,并在您的设备上安装 IPA。

连接到远程调试器

在启动应用程序之前,您需要执行以下操作,以便从它接收调试信息:

  1. 将您的设备连接到 Wi-Fi 网络。

  2. 获取您的开发计算机的 IP 地址。

  3. 从 Flash IDE 开始远程调试会话。

让我们详细说明这些步骤:

  1. 远程调试通过 Wi-Fi 进行。通过从设备主屏幕选择设置 | Wi-Fi来验证您的设备是否连接到与您的开发计算机相同的网络。如果不是,请从选择网络部分选择正确的网络。这将在下一页的屏幕截图中显示。

  2. 您还需要知道您从 Flash Professional 运行的计算机的 IP 地址。如果您使用 Microsoft Windows,请打开命令提示符窗口并输入以下内容:

    ipconfig
    
    
    • 网络配置详细信息将输出到命令窗口。您的计算机的 IP 地址由四个由点分隔的数字组成,您可以通过在输出中查找IPv4 地址来找到它。以下是一个示例:
    IPv4 Address. . . . . . . . . . . : 192.168.0.4 
    
    
    • 对于使用 Mac OS X 的用户,从苹果菜单中选择系统偏好设置。在系统偏好设置窗口中,点击网络部分中的网络图标。您的 IP 地址将在网络窗口的状态标题下显示。

      现在我们已准备好执行远程调试。

  3. 首先,通过从下拉菜单中选择调试 | 开始远程调试会话 | ActionScript 3.0来激活 Flash 的远程调试器。这将使 IDE 切换到其调试工作区,并向输出窗口发送以下消息:

    Waiting for Player to connect... 
    
    
  4. 实际上,Flash IDE 现在已准备好接收来自调试应用程序的调试信息,并等待最多两分钟以等待应用程序连接到它。

    注意

    如果调试工作区中尚未打开,请通过从 Flash 的下拉菜单中选择窗口 | 输出(F2)来打开输出窗口。

  5. 现在,回到您的设备主屏幕并启动应用程序。连接到远程调试器

  6. 应用程序将尝试自动连接到 Flash IDE。如果失败,将出现一个类似于前面屏幕截图的Flash 调试器对话框,要求您输入应连接到的计算机的 IP 地址。如果提示,请输入您的开发计算机的 IP 地址,然后点击确定以连接。

  7. 连接成功后,应用的 .swf 文件名将被发送到 Flash IDE 的 输出 窗口,随后是执行的所有 trace() 语句。对于这个示例,以下内容将被输出:

    [SWF] bubbles.swf - 327469 bytes after decompression
    Inside the constructor. 
    
    
  8. 如你所见,来自构造函数的 trace() 语句的消息已经发送到输出窗口。

  9. 现在,通过从 Flash Professional 的下拉菜单中选择 调试 | 结束调试会话 (Alt + F12) 来终止调试会话。Flash IDE 将返回到你之前使用的工位。

它是如何工作的...

远程调试对于识别和修复错误非常有价值,并且应该为经验丰富的 Flash 开发者所熟悉。使用 trace() 语句,你可以将应用的信息发送到 Flash IDE 的 输出 窗口。

在调试时,请记住从 AIR for iOS 设置 面板中选择 快速发布以进行设备调试 部署类型。同样重要的是,你的测试设备和开发计算机连接到相同的网络。尽管你的设备可能通过 USB 线缆连接到你的计算机,但远程调试仅适用于通过 Wi-Fi 的 AIR for iOS 应用程序。

本示例专注于 trace() 语句,但远程调试 iOS 支持包括断点控制、代码单步执行和变量监控在内的其他功能。不幸的是,这些高级调试功能超出了本书的范围。然而,Adobe Flash 开发者中心提供了对 ActionScript 3.0 调试器的全面介绍,网址为 www.adobe.com/devnet/flash/articles/as3_debugger.html

还有更多...

希望如此,你的应用将成功连接到远程调试会话。然而,如果你在连接时遇到问题,请继续阅读。

远程连接尝试

你的应用的调试版本默认会尝试连接到你的开发计算机的 IP 地址。如果连接尝试失败,你将被要求手动输入正确的 IP 地址。不幸的是,使用较旧版本的 AIR 发布的应用可能需要等待长达一分钟才会放弃并提示输入 IP 地址,这在快速部署和测试新的调试版本时几乎是不理想的。

在这段时间内,屏幕将保持空白,如果你的 iOS 设备未被操作,最终可能会自动锁定。如果设备锁定,你可能会错过应用对正确 IP 地址的提示,这会导致你的调试会话超时。

为了防止这种情况发生,请考虑通过从主屏幕选择 设置 | 通用 | 自动锁定 来增加你的 iOS 设备的自动锁定时间。

使用 Flash Professional CS5.5 和最新版本的 AIR 的用户不太可能遇到如此长时间的超时。

第四章. 将 Flash 项目移植到 iOS

在本章中,我们将涵盖:

  • 处理用户交互

  • 保存应用程序状态

  • 展示列表扁平化

  • 将矢量图转换为位图

  • 调整位图大小

  • 遮罩内容

  • 与外部 SWF 文件一起工作

简介

苹果禁止在 iOS 上安装第三方插件,这阻止了 Safari 或其他任何浏览器运行 Flash 内容。不幸的是,这阻止了使用 iOS 设备的用户访问那些流行的基于 Web 的 Flash 游戏和应用。

直到最近,iOS 日益增长的流行度让希望将现有内容发布到苹果平台的 Flash 开发者处于困境之中。唯一现实的解决方案是完全用 Objective-C 重写他们的项目以适应 iOS,同时继续维护其他平台上的 Web 用户现有的 ActionScript 代码库。

然而,AIR for iOS 的一个主要优势是开发者可以将现有的 Flash 内容重新发布为原生 iOS 应用,同时保留项目的大部分代码库不变。Adobe 对 Flash 平台的跨平台目标意味着 Flash 开发者可以在使用他们熟悉的相同开发环境的同时针对 iOS。

本章将带你了解在将现有 Flash 项目移植到 iOS 平台时将帮助你的菜谱。这些应该让你迈出正确的步伐,并在继续使用 iOS AIR 工作时增强你的信心。记住,这里学到的不仅仅是适用于移植现有内容;你也应该将相同的技巧和原则应用到任何你计划创建的新应用程序中。

当然,仅凭本章内容并不能保证你的 Flash 项目能够成功移植,但选定的菜谱应该能给你一个成功的味道。移动平台的限制可能会使开发变得令人畏惧。然而,随着你对 iOS AIR 的了解不断增长,你识别应用程序中可以优化以适应这些限制的区域的技能也会提高。

处理用户交互

鼠标交互允许达到手指无法实现的精确度。以菜单屏幕中的一个简单按钮为例。使用鼠标,用户将能够以几乎像素级的精确度进行选择。然而,手指会遮挡屏幕的一部分,包括被选中的项目,并且还会与更大的区域接触。

如果你的现有 Flash 应用程序主要是为鼠标交互设计的,那么你需要重新设计你的用户界面以适应触摸。你可以做出的最有益的更改是增加按钮的大小,并在它们周围创建更大的点击目标。

准备工作

已提供 FLA 文件作为本菜谱的起点。

如果你还没有这样做,请从本书的配套网站下载这本书的代码包。

chapter4\recipe1\recipe.fla打开到 Flash Professional 中。

在其库中包含您将用于创建按钮的位图。此外,其 AIR for iOS 设置已应用,节省了您在最终需要将菜谱构建和部署到设备时的时间和精力。

今后,将为所有菜谱提供一个起始 FLA,其中每个菜谱的大多数 AIR for iOS 设置已预先配置。

如何操作...

我们将把这个菜谱分成两部分。首先,我们将创建一个代表按钮的电影剪辑,然后再编写并链接一个自定义类。

创建按钮电影剪辑

让我们从创建电影剪辑开始:

  1. 选择插入 | 新符号 (Ctrl + F8 | Cmd + F8)。在创建新符号面板中,将Start Button输入到名称字段,并从类型字段的下拉框中选择电影剪辑。点击确定按钮。

    在库中创建一个空的电影剪辑符号,并将您移动到其时间轴。

  2. button-normal.png位图从库拖动到舞台。从属性面板中展开位置和大小部分,并将位图定位在(0, 0)。

  3. 点击时间轴的第 2 帧,选择插入 | 时间轴 | 空白关键帧。同时将button-select.png从库拖动到舞台,并定位在(0,0)。

  4. 通过从 Flash Professional 的下拉菜单中选择插入 | 时间轴 | 来在时间轴上创建一个新层。该层默认命名为层 2,并位于层 1之上。

  5. 工具面板中选择矩形工具 (R)。在层 2上绘制一个宽度为 290 像素、高度为 77 像素的矩形。将其定位在(-28,-14)。该矩形应跨越时间轴的两个帧,代表按钮的点击区域。

  6. 最后,通过双击矩形来选择它,然后从属性面板将矩形填充和描边的 alpha 设置为0%,使其不可见。

    您现在应该有一个按钮电影剪辑,其时间轴与以下截图相同:

    创建按钮电影剪辑

  7. Start Button电影剪辑符号中移出,回到您的 FLA 根时间轴。

  8. 保存 FLA。

将类链接到按钮

在处理完按钮的视觉后,是时候添加一些使用 ActionScript 的交互性了:

  1. 选择文件 | 新建并创建一个新的ActionScript 3.0 类。将类命名为Button

  2. 将以下代码添加到类中:

    package {
    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    public class Button extends MovieClip {
    public function Button() {
    addEventListener(MouseEvent.ROLL_OVER, touched);
    addEventListener(MouseEvent.ROLL_OUT, released);
    gotoAndStop(1);
    }
    private function touched(e:MouseEvent):void {
    gotoAndStop(2);
    }
    private function released(e:MouseEvent):void {
    gotoAndStop(1);
    }
    }
    }
    
    
  3. 将类保存为Button.as到与您的 FLA 相同的目录。

  4. 返回到您的 FLA。现在您可以将类链接到您的按钮。

  5. 中,右键单击 Start Button 电影剪辑符号并选择 属性。勾选 导出为 ActionScript 复选框。在 字段中输入 StartButton,在 基类 字段中输入 Button。单击 确定 按钮。Flash 将通知您将生成 StartButton 类的定义。单击 确定 按钮。

  6. 现在,将 Start Button 电影剪辑符号实例从 拖到舞台。将其定位在 (43,217)。

  7. 使用 ADL 测试您的 FLA 以确保没有编译错误。(Ctrl + Enter | Cmd + Enter)

  8. 最后发布您的 iOS 应用。

FLA 将被编译,并创建一个名为 c4-r1.ipa 的文件。将文件部署到您的设备上并测试它。

注意

本书剩余的食谱将遵循其 IPA 文件命名的约定。IPA 的名称将包含食谱所属的章节编号,后跟该食谱在章节中的位置。

例如,此食谱属于第四章(c4)并且是该章节的第一个食谱(r1)。因此,由该食谱的 FLA 生成的 IPA 文件将命名为 c4-r1.ipa。为了确保您可以在设备上轻松找到已安装的应用,每个应用的名字都将反映 IPA 的名字。您将在主屏幕上找到前一个食谱的示例应用,名为 c4 r1

它是如何工作的...

通过一些简单的时间轴工作和少量 ActionScript,您已经构建了一个适用于 iOS 设备的双状态按钮。

由于尺寸较大且具有宽裕的矩形点击目标,按钮易于点击。即使那些用一只手操作设备并用拇指进行选择的人也应该没有问题。

Button.as 类仅管理按钮两个状态之间的时间轴移动。当按钮未被按下时,显示时间轴的第一帧。当用户的指尖触摸按钮时,显示其时间轴的第二帧。其状态也会根据用户的指尖在按钮上或离开按钮时进行更新。

强烈的用户体验对您应用的成功至关重要。当将现有的 Flash 项目移植到 iOS 时,请花费必要的时间调整您的按钮和其他 UI 元素以适应该平台。

还有更多...

以下是一些关于用户交互的更多有趣点。

重新使用按钮类

您可以重新使用此食谱中提供的类,将其链接到您自己的项目库中的任何按钮。该类仅更新按钮的视觉状态,但您可以轻松地为任何按钮实例添加事件监听器以响应用户的选择。

作为一个快速示例,将您舞台上的按钮实例命名为 startButton。现在,为您的 FLA 创建一个文档类。将类命名为 Main 并向其中添加以下代码:

package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class Main extends MovieClip {
public function Main() {
startButton.addEventListener(MouseEvent.MOUSE_UP,
buttonPressed);
}
private function buttonPressed(e:MouseEvent):void {
startButton.visible = false;
}
}
}

上述代码只是监听 startButton 实例分发 MouseEvent.MOUSE_UP 事件。当它这样做时,buttonPressed() 处理程序被调用,该程序将按钮从视图中隐藏。当然,对于你自己的应用程序,你将在处理程序中添加自己的功能。

处理键盘控制

除了鼠标交互之外,许多为网络设计的启用 Flash 的项目还期望存在物理键盘以某种方式或形式控制应用程序。虽然 iOS 设备支持虚拟键盘,但它仅在文本字段被编辑时才出现。你的应用程序不应依赖于键盘事件作为控制机制。在将其移植到 iOS 之前,你可能需要重新设计用户与应用程序交互的方式。

参见

  • 将类链接到电影剪辑符号,第三章

  • 创建基本文档类第三章

保存应用程序状态

当为 iOS 编写应用程序时,你应该预计应用程序可能在任何时候被关闭。这可能是由于多种原因,例如用户故意退出应用程序、接收到来电或 iOS 由于内存限制而关闭应用程序。

当应用程序意外关闭时,用户会期望它在他们最终返回时从其先前状态恢复。对于你正在将其移植到 iOS 的任何 Flash 项目,在应用程序的生命周期中方便的点上添加保存应用程序状态的功能非常重要。

此菜谱将指导你完成维护应用程序状态所需的步骤。我们将使用 Flash 的 SharedObject 类将数据本地保存到您的设备。

准备工作

从本书的配套代码包中,将 chapter4\recipe2\recipe.fla 打开到 Flash Professional 中。

在舞台上,你会找到一个动态文本字段和一个代表按钮的电影剪辑。已经编写了一个最小的文档类,每次按钮被按下时都会增加计数器,并在文本字段中显示其值。

电影剪辑的库符号链接到一个名为 Button 的类,该类在先前的菜谱中介绍,即处理用户交互。

使用 ADL 测试应用程序 (Ctrl + Enter | Cmd + Enter)。通过点击按钮几次来增加计数器几次,然后关闭窗口。如果你再次测试应用程序,你会注意到计数器已重置为零——应用程序尚未记住其状态。

文档类 Main.as 可以在 FLA 的同一位置找到。打开它,熟悉代码。

已经在舞台上的按钮上添加了一个 MOUSE_UP 事件监听器。其处理函数简单地增加一个 counter 成员变量,然后将值写入动态文本字段。

让我们更新文档类,使其能够管理应用程序的状态。

如何做...

你将需要使用 SharedObject 类来完成此菜谱。

  1. Main.as 中添加一个导入语句:

    import flash.net.SharedObject;
    
    
  2. 声明一个成员变量,该变量将用于存储对共享对象的引用:

    private var so:SharedObject;
    
    
  3. 现在,添加一个私有方法,用于初始化共享对象或检索它已存储的任何数据:

    private function initSharedObject():void {
    so = SharedObject.getLocal("savedData");
    if(so.data.counter == null)
    {
    so.data.counter = counter;
    }
    else
    {
    counter = so.data.counter;
    }
    }
    
    
  4. 在构造函数中调用initSharedObject()

    public function Main() {
    initSharedObject(); 
    counterField.text = String(counter);
    btn.addEventListener(MouseEvent.MOUSE_UP, buttonPressed);
    }
    
    
  5. 添加一个私有方法,将counter成员变量的值保存到共享对象中:

    private function saveSharedObject():void {
    so.data.counter = counter;
    so.flush();
    }
    
    
  6. buttonPressed()事件处理程序中,调用saveSharedObject()方法:

    private function buttonPressed(e:MouseEvent):void {
    ++counter;
    counterField.text = String(counter);
    saveSharedObject(); 
    }
    
    
  7. 保存您的类文件。

  8. 使用 ADL 测试您的 FLA。当您关闭窗口并重新测试 FLA 时,您将看到计数器的值已成功恢复。

  9. 将您的应用程序发布到 iOS 并部署到您的设备。增加计数器然后关闭应用程序。如果您的设备正在使用 iOS 4.0 或更高版本,那么您还需要从 iOS 的应用程序切换器中强制关闭应用程序。当您重新启动它时,计数器的值将恢复。

小贴士

要访问快速应用程序切换器,请双击主按钮。要关闭应用程序,请轻触并保持其图标,直到图标角落出现减号符号。轻触减号符号,应用程序将从后台移除。应用程序切换器适用于运行 iOS 4 或更高版本的设备。

它是如何工作的...

本地共享对象是存储在您的设备上的数据文件。SharedObject类提供了一个 API,可以用来轻松地将数据保存到文件并从中检索数据。

在您可以使用共享对象之前,您必须通过调用静态getLocal()方法来获取SharedObject实例。如果共享对象尚不存在,则创建一个。当您调用getLocal()时,您必须传递一个字符串,该字符串用于命名写入设备文件系统的数据文件。这已在配方中的initSharedObject()方法中完成:

so = SharedObject.getLocal("savedData");

一旦您获得了SharedObject的引用,您可以通过其data属性添加或检索属性。每个属性代表您想要保存的数据,可以是任何 ActionScript 类型的对象,包括Array, ByteArrayXML。您甚至可以通过使用flash.net.registerClassAlias()包级函数首先注册它来保存自定义类的实例。

我们通过创建一个名为counter的属性并将其设置为成员变量的值来存储counter成员变量的值。这是在initSharedObject()方法中初始化持久数据时完成的,并在saveSharedObject()中再次完成以存储计数器的最新值。以下代码行用于实现此操作:

so.data.counter = counter;

了解你的共享对象是否包含数据或刚刚被创建也是有用的。你可以通过简单地检查你已知属性的存在来确定这一点。这是在initSharedObject()中完成的,我们检查了counter属性是否为null。如果是,我们就将其设置为counter成员变量的当前默认值;否则,我们使用存储的值来实际设置counter成员变量。以下代码再次作为提醒:

so = SharedObject.getLocal("savedData");
if(so.data.counter == null)
{
so.data.counter = counter;
}
else
{
counter = so.data.counter;
}

在数据对象内设置属性实际上并不会保存它们。你必须通过调用flush()方法来显式地这样做,这是在我们的saveSharedObject()方法中完成的。

调用flush()可能会很昂贵,因为数据必须写入文件系统。对于本食谱的示例代码,当应用程序的状态改变时,重复调用flush()是可以接受的。然而,对于现实世界的应用程序,你应该尽可能频繁地保存数据,但不要降低应用程序的性能。尝试找到方便的时刻来保存,例如,在关卡之间或用户不活跃期间。

关于SharedObject类的更多信息,请在 Adobe 社区帮助中搜索flash.net.SharedObject

参见

  • 处理多任务,第三章

  • 优雅地退出应用程序,第三章

展平显示列表

Flash 的绘图工具和渲染引擎使得创建一个深度嵌套的显示列表变得方便。当检查在 Flash 中创建的艺术作品时,通常需要深入到顶级剪辑的几个层级,并通过复杂的层次结构导航,直到找到目标显示对象。

不幸的是,虽然台式电脑可以轻松渲染复杂场景,但在 iOS 设备上运行相同的内容可能会降低性能。深度嵌套的显示列表也会导致长事件链,这可能会进一步损害性能。例如,一个触摸事件必须遍历显示列表,以确定要接收事件的显示对象。

当移植到 iOS 时,渲染通常是最大的性能瓶颈。考虑展平你的显示列表,以保持你的应用程序的帧率尽可能高。

我们将通过完全展平一个示例嵌套显示列表来了解这是如何完成的。

准备工作

从本书的配套代码包中,将chapter4\recipe3\recipe.fla打开到 Flash Professional 中。

FLA 的场景应该很熟悉。它是第二章和第三章示例气泡应用程序中使用的内容,除了这个 FLA 中的资产已经被安排在层次结构中。

在顶级是一个名为bubbles的单个容器电影剪辑,它包含所有气泡剪辑。在bubbles内部有四个额外的容器剪辑,分别命名为smallmediumlargehuge。这些容器用于按大小存储气泡集合。例如,所有小气泡都包含在small容器中。

下面的图示显示了完整的层次结构:

准备中

探索 Flash Professional 中的显示列表。它与大多数基于 Flash 的网站和游戏中的场景构建方式并不太相似。

让我们现在通过分解电影剪辑来简化这个显示列表。

如何操作...

确保您处于根时间轴上,并按照以下步骤操作:

  1. 使用选择工具 (V),点击舞台上坐着的bubbles电影剪辑。

  2. 选择修改 | 分解 (Ctrl + B | Cmd + B)

    现在,smallmediumlarge和巨大的电影剪辑将从bubbles中取消组合,bubbles现在将从显示列表中移除。

  3. 通过单击舞台上坐着的任何小气泡来选择small电影剪辑容器。现在选择修改 | 分解 (Ctrl + B | Cmd + B)来分解small电影剪辑容器,取消组合其中包含的Bubble Small实例。

  4. 重复前面的步骤来分解mediumlargehuge容器剪辑。

  5. 现在,您需要将每个气泡实例重命名,以确保它们都具有唯一的名称。当剪辑在容器内分组时,这不是问题,但现在它们都处于同一级别,它们的名称需要是唯一的。从小的气泡开始,一直工作到最大的,将电影剪辑实例命名为bubble1bubble9

  6. 最后,从库中删除不再需要的符号。为此,转到面板,并从面板菜单中选择选择未使用项。在库中右键单击一个突出显示的符号,并选择删除。所有突出显示的符号都将被删除。

    小贴士

    库的面板菜单由面板右上角的小图标表示。单击它将显示一个选项的下拉列表。

  7. 保存您的 FLA 文件。

它是如何工作的...

分解电影剪辑实例是简化显示列表的理想方式。当然,您可以减少显示列表的深度,而不是完全简化它。您希望走多远,实际上取决于您追求的性能和您希望渲染的场景的复杂性。

然而,实例命名可能会变得稍微复杂一些。分层结构允许具有相同名称的多个剪辑共存。例如,这个示例中的smallmedium电影剪辑都包含一个名为bubble1的剪辑。尽管这两个剪辑具有相同的名称,但它们属于不同的父剪辑,避免了命名冲突。然而,一旦展开,我们留下了几个具有相同名称的剪辑坐在舞台上。

如果你决定合并你的显示列表,那么仔细考虑这将对你的代码产生的影响。任何目标路径引用都需要更新,并且你需要花费时间重命名显示对象实例以避免潜在的命名冲突。合并显示列表也会影响显示对象的相对 xy 位置。然而,如果你正在移植的应用程序需要一致且高帧率的性能,那么这可能是你的唯一选择,尤其是在针对旧设备时。

将矢量转换为位图

大多数 Flash 项目都充分利用了 Flash 的矢量渲染引擎和时间轴动画系统。然而,渲染矢量内容可能会计算成本高昂,尤其是包含大量控制点、渐变和 alpha 透明度的复杂矢量形状。

尽管即使是普通的台式电脑也能轻松渲染大多数 Flash 项目中找到的矢量图形;但移动设备优化了位图图形,这意味着有时需要做出妥协。绘制位图通常比矢量便宜。

在性能至关重要的地方,考虑将复杂的矢量艺术品转换为位图。如果你的项目已经包含现有的矢量内容,那么你可以使用 Flash Professional 从每个库符号生成位图。然后你可以用位图渲染版本替换你的矢量内容。

让我们看看这是如何操作的。

准备工作

已提供 FLA 文件作为本菜谱的起点。

使用 Flash Professional,从书籍的配套代码包中打开 chapter4\recipe4\recipe.fla

你将使用上一章示例 Bubbles 应用程序中的资源。尽管该应用程序之前使用了位图,但此 FLA 库中的气泡资源现在由矢量表示。

面板中,你会找到一个名为 Bubble Vector 的电影剪辑符号。这是一个在四种气泡类型(Bubble Small、Bubble Medium、Bubble LargeBubble Huge)中使用并调整大小的母剪辑。

我们现在将使用 Flash Professional 将每个气泡的矢量表示转换为位图。

如何操作...

让我们先从将 Bubble Small 转换为位图开始:

  1. 面板中,双击 Bubble Small。这将把你带到该符号的时间轴。

  2. 从 Flash Professional 的下拉菜单中选择 文件 | 导出 | 导出图像

    将出现一个文件浏览器窗口。

  3. 使用浏览器窗口,导航到你的 FLA 的根文件夹。在 保存类型 字段中,选择 PNG 并在 文件名 字段中输入 bubble-small.png。点击 保存 按钮。

    将出现一个 导出 PNG 对话框,提供 Flash 即将创建的 PNG 的导出选项,如下截图所示:

    如何操作...

  4. 对于包含字段,从下拉框中选择最小图像区域。确保颜色字段设置为24 位带 alpha 通道,并且过滤器字段设置为。此外,确保平滑复选框未选中。

  5. 点击确定以导出 PNG。

  6. 现在,从面板中双击Bubble Medium。再次,选择文件 | 导出 | 导出图像,并输入文件名为bubble-medium.png。在导出 PNG面板中,使用之前的相同设置。

  7. 重复此过程,对于Bubble LargeBubble Huge,分别导出为bubble-large.pngbubble-huge.png

它是如何工作的...

现在,您有四个位图图像——每个气泡一个——可以导入到您的 FLA 中,并用它们替换矢量版本。

移动设备上,如 iPhone 上发现的图形处理单元(GPU),针对渲染位图进行了优化;在许多情况下,如果您选择使用位图而不是矢量,您应该会看到显著的性能提升。

无论您使用 CPU 还是 GPU 渲染模式,您的位图图像看起来都将保持一致,除了平滑处理外,它们将相对不受舞台渲染质量的影响。这与矢量形成鲜明对比,矢量会受到渲染模式和舞台质量的双重影响。

使用 CPU 渲染模式利用与安装在桌面计算机上的 Flash Player 相同的软件渲染器,并产生相同的高质量结果。然而,这是以性能为代价的,与使用 GPU 渲染管道相比。

虽然渲染矢量使用 GPU 很快,但总是会得到源艺术作品的近似值。对于快速移动的内容,这可能是可以接受的,但对于静止物体,差异可能很明显。

实际上,每种渲染路径在处理矢量时都会产生不同的结果。CPU 渲染准确但较慢,而 GPU 渲染速度快但不够准确。然而,这两种选项通常比使用位图计算成本更高。

在适当的情况下,将您的复杂矢量艺术品替换为位图。然而,请注意,与矢量相比,位图可能会显著增加您的最终.ipa文件的大小。您的 IPA 越大,您的应用加载所需的时间就越长,消耗的内存就越多。内存消耗的增加本身可能会导致性能下降。

此外,苹果目前对空中下载设置了 20 MB 的限制。确保您的 IPA 不超过此限制,因为它会阻止用户通过运营商网络下载您的应用,并可能影响销售。

查看chapter4\recipe4-final\recipe.fla,以查看导出的 PNG 文件正在替代原始矢量艺术品使用。

还有更多...

智能使用位图对于最大化您应用的性能至关重要。您可能会发现以下选项和信息有助于实现这一点。

导出为位图

对于使用 Flash Professional CS5.5 的用户,有一个更方便的选项,允许您在发布时指示 Flash 导出矢量电影剪辑的位图表示。这不仅为您提供了针对应用的优化位图内容,而且还在 FLA 中保留了原始矢量图形。

要将符号导出为位图,首先从舞台中选择符号。然后从属性面板,展开显示部分,并从渲染字段的下拉菜单中选择导出为位图。如果您的剪辑需要透明度,请确保位于下拉菜单下方的选项设置为透明

在 Flash CS5 中不可用导出为位图

转换为位图

从 Flash Professional CS5.5 中提供了一个名为转换为位图的附加选项,该选项将矢量符号转换为位图。尽管导出为位图不会更改 FLA 的显示列表,但此选项将舞台上的实例替换为位图表示。新的位图表示将添加到库中,允许您使用 Adobe Photoshop 等图像编辑器进行进一步编辑。

要将符号转换为位图,只需在舞台上的实例上右键单击,然后从上下文菜单中选择转换为位图

在 Flash CS5 中不可用转换为位图

与时间轴动画一起工作

基于矢量的时间轴动画可能会进一步影响性能。这尤其适用于复杂的补间动画,这些操作可能非常昂贵。在低端设备上,如第一代和第二代 iPhone 和 iPod touch,即使是相对简单的补间也可能表现不佳。然而,随着从 AIR 2.6 以来的巨大渲染改进以及每一代 iOS 设备硬件规格的不断提高,这个问题正在逐渐减少。记住,苹果公司本身也不再支持第一代和第二代设备。

如果您在使用时间轴动画时遇到性能问题,那么考虑将动画的每一帧导出为 PNG 格式。其长度将是一个重要因素,因为基于位图的动画可能会消耗大量内存并增加加载时间。在这种情况下,您可能需要使用矢量实现,或者考虑重新设计动画以使其适合移动设备。

针对多个屏幕尺寸

屏幕分辨率在 iOS 设备之间有所不同。例如,iPhone 3GS 的分辨率为 320x480,而 iPhone 4 支持 640x960 像素。

当针对多个屏幕尺寸时,考虑创建不同尺寸的位图版本——每个屏幕分辨率一个。这将避免由于位图缩放导致的图像质量下降,并防止与内容缩放相关的任何性能问题。

创建每个位图的多个版本将增加 IPA 的最终文件大小,但如果性能是首要考虑,那么这可能值得付出努力。

如果你希望避免在应用程序中捆绑多个位图的额外开销,那么在将位图表示存储在内存中之前,也可以在运行时缩放矢量艺术作品。这种技术被称为位图缓存,在第六章(ch06.html "第六章. 图形和硬件加速")中详细探讨。

预渲染滤镜和混合

滤镜通常在 Flash 项目中用于向显示对象添加视觉效果,如阴影、斜边和模糊。虽然滤镜可以为你的应用程序增添影响,但它们可能会严重影响性能。这在 iOS 设备上尤其如此,因为与桌面计算机相比,CPU 速度有限。此外,在 Flash Professional CS5.5 中,当使用 GPU 渲染管道时,滤镜不再受支持。

建议你将图形效果预渲染到艺术作品中,而不是使用 Flash 在运行时应用滤镜。这将有助于设备性能,并确保你的效果在 CPU 和 GPU 渲染模式下都能正常工作。

与从头开始完全重新创建效果的图像编辑器相比,你可以使用 Flash Professional 创建舞台上显示对象应用到的任何滤镜的位图表示。有各种方法可以做到这一点,包括将实例的渲染属性设置为导出为位图,将整个库剪辑转换为位图,或者导出 PNG 图像后再将其重新导入 Flash。

非正常混合模式也是昂贵的操作,应该以类似滤镜的方式将其'烘焙'到你的艺术作品中。

参见

  • 在舞台上添加内容,第二章

  • 比较矢量图形和位图图形,第六章

  • 使用缓存为位图,第六章

  • 针对 Retina 显示屏,第八章

  • 支持多分辨率,第八章

调整位图大小

在 Flash 项目中,常见到不必要地对位图进行缩放的情况。在运行时调整位图大小可能会消耗大量计算资源并降低图像质量。这样做还可能导致包含的艺术作品实际大小超过预期显示尺寸时,IPA 文件变得更大。

让我们看看如何在 Flash Professional 中调整现有的位图艺术作品的大小。

准备工作

从 Flash Professional 中,打开书籍附带代码包中的chapter4\recipe5\recipe.fla

再次,你将使用第二章和第三章示例 Bubbles 应用程序的熟悉视觉元素。这个食谱的资产由矢量和位图组成。气泡本身是矢量,而背景图像和 Flash 标志是位图。位图已缩放以适应屏幕。为了比较舞台上的缩放实例和库中存储的原始位图的大小,你可能想要将background.pngflash-logo.png都拖到舞台上。在继续之前,从舞台上删除这两个文件。

让我们使用 Flash Professional 调整库中存储的位图的大小,以防止 Flash 在运行时进行此操作。

如何做到这一点...

按以下步骤调整位图大小:

  1. 面板中,双击Bubble Huge。这将把你带到该符号的时间轴,在那里你会看到一个带有标志的巨型气泡符号的实例。

  2. 再次双击此符号以进入其中。

    在其时间轴上,你会看到两个图层——BubbleLogoLogo层包含 Flash 标志的位图表示。此剪辑已从 894x894 像素缩小到 200x200 像素。让我们创建一个已经缩放到正确大小的位图的新版本。

  3. 中,右键单击flash-logo.png,从上下文菜单中选择使用编辑。当提示时,浏览并选择一个外部编辑器,例如 Adobe Photoshop。

  4. 在您的编辑器中,将图像大小调整为 200x200 像素并保存。

  5. 返回到 Flash Professional。

    现在,你应该能在气泡中看到新版本的标志,然而,标志现在将比预期的大小小得多。这是因为最初应用于 894x894 版本的缩放变换现在仍然应用于新的位图。

  6. 锁定Bubble层,然后单击位于Logo层上的位图。从属性面板,更改宽度和高度设置到源位图的精确尺寸 200x200。

  7. 在库中双击Background电影剪辑符号。

    此剪辑使用名为background.png的位图,实际上它是 640x960 像素缩小到 320x480。再次让我们在图像编辑器中调整此位图的大小,以防止在应用程序运行时对其进行缩放。

  8. 在库中找到background.png。右键单击它,并选择使用您选择的图像编辑器编辑位图。将图像大小调整为 320x480 并保存。

  9. 返回到 Flash Professional。使用选择工具 (V),单击位于背景电影剪辑符号中的background.png,并将其宽度设置为 320,高度设置为 480。

  10. 保存您的 FLA 文件。

它是如何工作的...

你已经成功用预渲染到预期观看大小的版本替换了 FLA 中现有的位图。这将节省宝贵的 CPU 周期,因为不需要在运行时缩放位图。只要这些位图最初是在运行时缩小而不是增大,调整位图大小也可以显著减小你的 SWF 的整体大小。

查看chapter4\recipe5-final\recipe.fla,以了解正在使用的调整大小的位图替代原始过大的位图。在较新的设备上运行时,可能难以察觉原始版本(recipe5\recipe.fla)和最终版本(recipe5-final\recipe.fla)之间在性能上的任何明显差异,但对于低端设备或更复杂的项目,这种改进可能是显著的。

还有更多...

以下信息在调整或优化资源时也会对你有所帮助。

针对多个屏幕尺寸

iOS 设备的屏幕分辨率各不相同。例如,iPhone 3GS 的分辨率为 320x480,而 iPhone 4 支持 640x960 像素。

当编写针对多个屏幕尺寸的应用程序时,你可能倾向于简单地通过运行时缩放位图内容来适应每个分辨率。如果你采取这种方法,那么请注意,如果你的应用程序尝试以高帧率渲染复杂场景,你可能会遇到性能问题。此外,随着位图的缩放,其质量也会受到影响。

相反,考虑为每个资产创建不同的版本——每个你希望支持的屏幕尺寸一个。当然,拥有每个资产的多个版本会增加你 IPA 的最终文件大小,但最终结果可能值得付出的努力。

如果你必须在运行时调整图像大小,那么你可以利用硬件加速来缩放位图,从而对性能的影响更小。你可以在第六章中了解更多信息。

优化矢量形状

虽然这个配方主要关注位图,但很容易创建不必要的详细矢量内容,这会影响渲染时间,并使你的.ipa文件体积膨胀。

为了减少绘制矢量艺术品所需的计算量,花时间移除不必要的控制点。通过智能使用子选择工具(A)删除锚点工具(-),你可以在不降低图像质量的情况下简化资产内的路径。

屏幕的像素密度使得用户难以看到他们在标准显示器上通常能注意到的许多细节。移除不必要的控制点可以减少你的 IPA 最终大小,并提高渲染性能。

阶段质量

您可以通过降低应用程序使用的阶段渲染质量来进一步提高性能。目前 iOS 提供了三种质量设置——低、中、高(AIR 2.0-2.7 仅支持低和中)。默认情况下,AIR for iOS 使用中等设置,但您可以通过在 ActionScript 中设置Stage.quality属性为flash.display.StageQuality类提供的常量之一来更改此设置。

例如,将以下代码行添加到您的文档类中,将使用最低的渲染质量设置:

stage.quality = StageQuality.LOW;

阶段渲染质量是一个全局设置,并应用于应用程序中的所有矢量内容。然而,位图相对不受影响,除了平滑处理外,在所有质量设置下看起来都相同。这方便地让您在不影响应用程序中任何位图质量的情况下,从矢量资产中获得最高性能。

参见

  • 将矢量转换为位图

  • 比较矢量图形和位图图形,第六章

  • 使用缓存为位图矩阵,第六章

  • 针对视网膜显示屏,第八章

  • 支持多分辨率,第八章

蒙版内容

在整个 Flash 项目中,蒙版层经常被用来部分显示位于蒙版层直接下方的图层上的内容。蒙版本身可以是填充形状、文本、图形符号的实例或电影剪辑。甚至可以通过对蒙版应用形状或运动补间来创建动态效果。

这种灵活性和复杂性可能会对 CPU 提出很高的要求,导致帧率下降。尽管桌面计算机可以处理大多数蒙版操作,但相同的效果会降低您的 iOS 应用程序的性能。在可能的情况下,限制您对蒙版的用途。对于现有项目,而不是使用蒙版,可以用位于其上的其他剪辑来遮蔽内容。

在这个菜谱中,我们将做的是;移除蒙版层,而是使用两个电影剪辑来遮蔽之前由蒙版剪辑的内容。

准备工作

从本书的配套代码包中,将chapter4\recipe6\recipe.fla打开到 Flash Professional 中。

FLA 显示了一个游戏的信用屏幕。使用蒙版层来剪辑滚动向上的信用文本,确保只显示屏幕中央矩形区域内的文本。

要自己查看被遮罩的区域,请解锁 FLA 时间轴中的遮罩层。任何滚动进入此区域的文本都将显示在屏幕上。位于此区域之外的文本将被隐藏。文本本身是一个位于字幕层上的电影剪辑,并直接位于遮罩层下方。再次锁定图层以重新应用遮罩。以下截图显示了遮罩区域以及当遮罩应用于字幕文本时屏幕将呈现的样子:

准备中

通过选择控制 | 测试影片 | 在 AIR 调试启动器(移动) (Ctrl + Enter | Cmd + Enter) 来测试 FLA 在 ADL 中的效果。

现在发布 FLA 以供 iOS 使用,并将生成的 IPA 部署到你的设备上。在旧款 iOS 设备,如第一代和第二代 iPhone 以及 iPod touch 上,你可能发现性能严重受损。遮罩在旧硬件上尤其有问题。在继续之前,请从你的设备上删除该应用。

现在我们将逐步说明如何移除遮罩,并使用电影剪辑来遮挡字幕文本。

如何操作...

我们将首先移除遮罩层。

  1. 在时间轴上右键点击遮罩层,然后从上下文菜单中选择删除图层如何操作...

    • 现在我们将复制一些新的库符号到你的 FLA 中。
  2. 选择文件 | 打开,浏览到 chapter4\recipe6\resources\resources.fla。点击打开以加载 FLA。

  3. resources.fla 复制所有库符号并将其粘贴到 recipe.fla 的库中。

    你复制的两个新的电影剪辑符号——背景顶部背景底部——将被用来遮挡任何位于之前由遮罩定义的矩形区域之外的字幕文本。

  4. 字幕层上方直接创建一个新图层,并将其命名为背景前如何操作...

  5. 从库中将背景顶部的一个实例拖动到背景前图层上。从属性面板中,将实例的 x 和 y 位置分别设置为 0。如果你使用的是 Flash Professional CS5,那么你也应该展开显示部分并勾选缓存为位图复选框。

  6. 此外,从库中将背景底部的一个实例拖动到背景前图层上。将其 x 位置设置为 0,y 位置设置为 385。再次提醒,如果你使用的是 Flash Professional CS5,那么在显示部分,请勾选缓存为位图复选框。

  7. 保存你的 FLA 并使用 ADL 测试 (Ctrl + Enter | Cmd + Enter)

  8. 最后,发布并部署到你的设备上。如果你使用的是旧一代设备,那么性能提升将会非常显著。

它是如何工作的...

虽然实现方式不同,但最终结果应该与原始遮罩层实现相同。然而,使用电影剪辑来遮挡内容相比使用遮罩裁剪要计算成本低。

隐藏是一个相当简单的技术。在本例中,使用了两个包含 FLA 背景图像位图内容的新剪辑。然后,将字幕文本夹在原始背景图像和两个新剪辑之间,给人一种正在对文本应用遮罩的错觉。

您可能不熟悉缓存为位图渲染选项。在本例中,它用于利用 Flash Professional CS5 构建的应用程序的 GPU 加速。缓存为位图和 GPU 加速将在第六章中更详细地介绍。

参见

  • 使用缓存为位图,第六章

  • 使用缓存为位图矩阵,第六章

使用外部 SWF

为了减少初始加载时间,基于 Web 的 Flash 项目通常将资源(如图形)保存在单独的.swf文件中,这些文件在需要时加载。例如,跨越多个级别的游戏可能每个级别都有一个外部 SWF。当玩家完成一个级别时,包含下一个级别资源的 SWF 将在运行时加载。

由于苹果公司实施的限制,iOS 应用程序不能从外部源运行解释代码。这给希望加载包含类文件或嵌入在库符号时间线中的 ActionScript 的外部 SWF 的人带来了问题。目前还没有创建包含原生 ARM 机器代码的外部 SWF 的方法。

如果您正在尝试移植加载包含 ActionScript 的外部 SWF 的 Flash 项目,那么您需要将资源直接包含在您的 iOS 应用程序中。任何资源文件都需要作为 SWC 文件发布,而不是 SWF,以便它们可以静态链接并与您的 iOS 应用程序编译。

让我们看看如何做到这一点。

准备工作

我们将需要使用书籍配套代码包中的各种文件。在chapter4\recipe7\resources\assets.fla中提供了一个资源 FLA。我们将将其发布为.swc文件,并将其静态链接到第二个 FLA,即chapter4\recipe7\recipe.fla

如何操作...

本菜谱分为两个主要步骤。首先,我们将从资源 FLA 发布一个 SWC,然后我们将静态链接 SWC 到我们的应用程序 FLA。

发布 SWC

让我们先从创建assets.fla的 SWC 开始。

  1. chapter4\recipe7\resources\assets.fla导入到 Flash Professional 中。

    本 FLA 包含一组资源,旨在由recipe.fla加载和使用。FLA 的舞台是空的,但在其库中您将找到具有链接 ID 的电影剪辑符号,允许它们在运行时实例化并添加到显示列表中。

    现在,让我们配置 FLA 的发布设置,允许从其 SWF 导出.swc文件。

  2. 从下拉菜单中选择文件 | 发布设置

    您的下一步取决于您使用的 Flash Professional 版本。对于 Flash CS5.5,取消选择 Flash (.swf) 复选框,并在 发布 部分内选中 SWC 复选框。如果您使用的是 CS5,则在点击 SWF 设置 部分的 导出 SWC 复选框之前,先点击 Flash 选项卡。

  3. 点击 确定 以设置更改并关闭 发布设置 面板。

  4. 保存 FLA 的更改,然后通过从下拉菜单中选择 文件 | 发布 (Alt + Shift + F12 | Shift + Cmd + F12) 来发布它。一个名为 assets.swc 的文件将被输出到与您的 FLA 相同的文件夹中。

静态链接 SWC 文件

现在,让我们编写一个简单的 iOS 应用程序,并将资产 SWC 静态链接到它。

  1. 首先,在 Flash Professional 中打开 chapter4\recipe7\recipe.fla

  2. 创建一个文档类。将类命名为 Main 并向其中添加以下代码:

    package {
    import flash.display.Sprite;
    public class Main extends Sprite {
    public function Main() {
    var background:Background = new Background();
    background.x = 0;
    background.y = 0;
    addChild(background);
    var bubble:BubbleHuge = new BubbleHuge();
    bubble.x = stage.stageWidth / 2;
    bubble.y = stage.stageHeight / 2;
    addChild(bubble);
    }
    }
    }
    
    
  3. 保存文档类。

  4. 返回到 FLA 文件,从下拉菜单中选择 文件 | 动作脚本设置。这将打开 高级动作脚本 3.0 设置 面板,您可以在其中将 assets.swc 静态链接到您的应用程序。静态链接 SWC

  5. 要这样做,首先点击 库路径 选项卡,然后点击表示为 + 符号的 添加新路径 图标。现在点击 浏览到 SWC 文件 图标。浏览并选择您的 assets.swc 文件。它将被添加到要随应用程序发布的 SWC 文件列表中。通过点击其路径左侧的图标展开资产 SWC 条目。确保其 链接类型 设置为 合并到代码

  6. 通过点击底部的 确定 按钮关闭 高级动作脚本 3.0 设置 面板。

  7. 保存您的 FLA。

  8. 在 ADL 中发布并测试您的 FLA (Ctrl + Enter | Cmd + Enter)。应用程序应该实例化并将 assets.swc 中的 BackgroundBubble Huge 符号添加到其显示列表中。

  9. 最后,发布并部署应用程序到 iOS,并确保它在您的设备上按预期工作。

它是如何工作的...

我们从资产 FLA 创建了一个 SWC 文件,并将其静态链接到我们的 iOS 应用程序。SWC 文件是一个包含预编译的 Flash 符号和动作脚本代码的包。虽然 SWC 文件通常可以在运行时加载,但在编写针对 iOS 的应用程序时,您必须静态链接 SWC 文件。这保证了 Flash Professional 将 SWC 的动作脚本字节码编译成本机 ARM 机器代码。

本食谱示例中的文档类简单地使用与资产 SWC 库符号关联的链接 ID 来实例化和向应用程序的显示列表添加对象。具体来说,该类创建并显示 BackgroundBubbleHuge 的实例,它们来自 assets.swc

您应该考虑您将链接到您的 iOS 应用中的资源文件的总大小。所有静态链接的内容都必须预先加载,这将影响您应用的初始加载时间和它消耗的内存量。在大型项目中,如果内存消耗过高,iOS 可能会关闭应用。内存阈值会因设备而异,并且还取决于后台保留的应用数量。

还有更多...

加载外部 SWF 文件并非不可能,但您能做的事情有限。

SWF 文件不能包含任何 ActionScript,包括将链接 ID 分配给库符号。这阻止了您从您的应用中动态实例化 SWF 的任何库符号。同样,您也无法在 SWF 的时间线上嵌入 ActionScript 以执行简单的程序控制您的动画。

然而,您可以在 SWF 的舞台上放置内容;将 SWF 加载到您的应用中;然后将 SWF 添加到显示列表中。您还可以在外部 SWF 的时间线上嵌入声音并播放它。此外,您可以从您的应用中调用 ActionScript 到外部 SWF,允许对显示列表中的实例进行程序控制。与许多 Flash 开发者习惯的相比,这有限制,但在 iOS 项目中仍然有外部 SWF 的用途。

参见

  • 创建基本文档类,第三章

  • 将类链接到电影剪辑符号,第三章

第五章. 多点触控和手势支持

在本章中,我们将介绍:

  • 设置触摸点输入模式

  • 检测多个触摸点

  • 拖动多个显示对象

  • 跟踪移动

  • 设置手势输入模式

  • 处理滑动手势

  • 平移一个对象

  • 旋转一个对象

  • 缩放一个对象

简介

iPhone 并非第一个使用这项技术的设备,但它的成功启动了触摸屏革命。对这一成功至关重要的是苹果决定包含多点触控支持。无论是单次点击、滑动还是捏合;与 iPhone 屏幕的交互总是直观而自然。

Flash 平台允许应用程序开发者充分利用多点触控,当针对 iOS 时。在本章中,我们将探讨如何处理多个触摸点,然后再介绍如何检测和响应手势。

设置触摸点输入模式

iPhone 的成功改变了人们使用移动设备的方式,现在用户期望通过物理触摸屏幕直接与设备交互。虽然鼠标仅限于选择单个点,但 iOS 设备可以检测多个触摸并同时跟踪它们的每个移动。

Flash 提供了对多点触控的全面支持,但为了利用它,您必须首先通知平台您的意图,即接收和使用基于触摸的事件。

让我们看看这是如何完成的。

准备工作

已提供一个 FLA 作为本菜谱的起点。

从本书的配套代码包中,将 chapter5\recipe1\recipe.fla 打开到 Flash Professional 中。

阶段上有一个名为 output 的动态文本字段。我们将编写一些代码以启用多点触控输入并将请求的成功或失败写入文本字段。

如何做...

执行以下步骤:

  1. 创建一个名为 Main 的文档类。

  2. 添加以下两个导入语句:

    import flash.display.MovieClip;
    import flash.ui.Multitouch;
    import flash.ui.MultitouchInputMode; 
    
    
  3. 现在在构造函数中添加一些代码以启用多点触控支持:

    public function Main() {
     if(Multitouch.supportsTouchEvents)
    {
    Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
    output.text = ("inputMode = " + Multitouch.inputMode);
    }
    else
    {
    output.text = "Multi-touch events not supported.";
    } 
    }
    
    
  4. 将类文件保存为 Main.as

  5. 发布 FLA 并将 IPA 文件部署到您的 iOS 设备上。

当您运行应用程序时,以下文本应输出到屏幕上:

  • inputMode = touchPoint

它是如何工作的...

Flash 提供了各种多点触控输入模式,这些模式决定了您的应用程序可以接收的事件类型。为了接收触摸事件,您需要将 Multitouch.inputMode 属性设置为 MultitouchInputMode.TOUCH_POINT。这是您文档类中执行此操作的代码行:

Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;

除了设置 Multitouch.inputMode,您还可以查询它以确定当前选定的输入模式。对于这个菜谱,当前输入模式被写入 output 文本字段以确认它已成功设置:

output.text = ("inputMode = " + Multitouch.inputMode);

虽然 Flash 支持所有 iOS 设备的多触控,但并非所有其他操作系统和平台都如此。在编写跨平台代码时,您可能需要通过检查Multitouch.supportsTouchEvents属性来确认支持。在我们的代码示例中,这是在设置输入模式之前完成的。

如需了解更多关于多触控输入模式的信息,请在 Adobe 社区帮助中搜索flash.ui.Multitouchflash.ui.MultitouchInputMode

还强烈建议您花时间研究苹果的 iOS 人机界面指南,在那里您将找到通过多触控驱动用户体验的最佳实践。文档可以在 iOS 开发中心developer.apple.com/devcenter/ios找到。

更多内容...

让我们看看一些额外的细节。

可用的触控事件

设置触控的输入模式允许您监听由类型为InteractiveObject或继承自InteractiveObject的对象(如Sprite, MovieClipStage)分发的特定于触控的事件。在多触控屏幕上,每个手指可以接触的点称为触点。

以下可用的触控事件:

触控事件 描述
TOUCH_BEGIN 触点已被按下。
TOUCH_END 触点已被释放。
TOUCH_MOVE 触点正在移动。这发生在手指在屏幕上拖动时。
TOUCH_TAP 快速的手指轻触。
TOUCH_OVER 触点已移至交互对象上。
TOUCH_OUT 触点已从交互对象移开。
TOUCH_ROLL_OVER 触点已移至交互对象上。与TOUCH_OVER不同,此事件不会对对象的所有子对象触发。
TOUCH_ROLL_OUT 触点已从交互对象移开。与TOUCH_OUT不同,此事件不会对对象的所有子对象触发。

在接下来的几个示例中,我们将看到一些这些事件的实际应用。

确定支持的触点数量

您可以通过检查静态属性Multitouch.maxTouchPoints来确定您的 iOS 设备支持的触点数量。

虽然您会发现 iOS 设备支持 5 个触点,但此属性在跨平台项目中更有实用价值,因为在不同的操作系统和输入设备选择下,触点数量可能会有很大的变化。当针对多个平台时,请考虑这一点来优化您的内容。

触点击中目标

对于您应用程序中可以点击的元素,请确保使用至少与指尖大小相当的击中区域。在标准分辨率屏幕上,这相当于大约 44x44 像素,在 Retina 显示屏上为 88x88 像素。

鼠标事件

默认输入模式是 MultitouchInputMode.NONE,这表示所有与触摸设备交互的用户操作都被解释为鼠标事件。然而,与 MultitouchInputMode.TOUCH_POINT 不同,任何时刻只能处理一个触摸点。

注意,当输入模式设置为 MultitouchInputMode.TOUCH_POINT 时,你可以继续监听和响应由 flash.events.MouseEvents 提供的鼠标事件。

在 ADL 中测试

很可能在 ADL 中测试此菜谱代码会导致以下消息输出到屏幕:

  • 不支持多点触控事件。

并非所有台式计算机或操作系统都支持多点触控。当在代码中使用基于触摸的事件时,建议直接在 iOS 设备上测试。

参见

  • 创建基本文档类,第三章

  • 处理用户交互,第四章

  • 检测多个触摸点

  • 设置手势输入模式

检测多个触摸点

多点触控术语指的是同时检测和跟踪触摸屏上两个或更多不同接触点的功能。触摸事件类似于 Flash 提供的鼠标事件,除了你可以同时监听和响应多个触摸事件。

让我们回顾一下第三章 中的 Bubbles 应用程序,并向其中添加多点触控交互。我们将添加功能,使用户可以通过在每个气泡上方放置手指来捕获多个气泡。

准备工作

已为你提供了一个 Bubbles FLA 版本供你工作。

从 Flash Professional 打开书籍附带代码包中的 chapter5\recipe2\recipe.fla

如何实现...

我们将对 FLA 的文档类和 Bubble.as 进行修改。

更新 Bubble 类

让我们从向 Bubble.as 添加一些代码开始,以防止在触摸时移动任何气泡实例:

  1. 打开 Bubble.as 类。

  2. 添加以下成员变量:

    private var _held:Boolean = false;
    
    
  3. 现在为 _held 变量编写获取器和设置器方法:

    public function set held(h:Boolean):void {
    _held = h;
    }
    public function get held():Boolean {
    return _held;
    }
    
    
  4. 移动到 update() 方法,并在开始处编写几行代码以防止在触摸时更新气泡的逻辑:

    public function update():void {
     if(_held)
    {
    return;
    } 
    
    
  5. 最后,在构造函数中,禁用气泡内任何子显示对象的用户输入——我们只对接收气泡容器的事件感兴趣:

    public function Bubble() {
    mouseChildren = false; 
    }
    
    
  6. 保存 Bubble.as

响应多个触摸事件

现在在 FLA 的文档类中,让我们监听多点触控事件并捕获任何被触摸的气泡:

  1. 打开 Main.as 文档类。

  2. 包含以下三个导入语句:

    import flash.ui.Multitouch;
    import flash.ui.MultitouchInputMode;
    import flash.events.TouchEvent;
    
    
  3. 在构造函数中设置输入模式,并监听从舞台派发的 TouchEvent.TOUCH_BEGINTouchEvent.TOUCH_END

    public function Main() {
     Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
    stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBegin);
    stage.addEventListener(TouchEvent.TOUCH_END, touchEnd); 
    application = NativeApplication.nativeApplication;
    
    
  4. TOUCH_BEGIN 事件编写处理程序:

    private function touchBegin(e:TouchEvent):void {
    var b:Bubble = e.target as Bubble;
    if(b != null)
    {
    b.held = true;
    }
    }
    
    
  5. 并为 TOUCH_END 事件添加处理程序:

    private function touchEnd(e:TouchEvent):void {
    var b:Bubble = e.target as Bubble;
    if(b != null)
    {
    b.held = false;
    }
    }
    
    
  6. 保存 Main.as

  7. 发布 FLA 文件并将 IPA 文件部署到您的设备上。

运行应用,并将手指放在多个气泡上以阻止它们向上漂浮。将手指从气泡上抬起将再次释放它。

它是如何工作的...

此菜谱利用了多点触控,允许同时检测多个对象的触摸点。

Main类的构造函数中,通过以下代码行启用了触摸功能:

Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;

任何InteractiveObject或其子类,如Sprite, MovieClipStage,都可以分发触摸事件。

已经将以下两个事件的监听器添加到了舞台:

  • TouchEvent.TOUCH_BEGIN

  • TouchEvent.TOUCH_END

当用户将手指按在任何舞台的子交互对象上时,会触发TOUCH_BEGIN事件。即使屏幕的其他区域已经被触摸,这也是这种情况。当用户从交互对象上抬起手指时,会分发TOUCH_END事件。

在此菜谱中,舞台的子对象包括气泡实例和单个背景电影剪辑。事件处理程序只是检查事件是否是从Bubble实例分发的,如果是,则将气泡的held属性设置为。对于TOUCH_BEGIN事件,将气泡的held属性设置为true,从而将其冻结。当接收到TOUCH_END事件时,将气泡的held属性设置为false,允许它再次向上移动。

您可以从 Adobe 社区帮助中获取有关flash.events.TouchEvent类的更多信息。

处理滚动退出

有时用户的指尖可能从气泡上滑开,而不是干净地抬起。当在此菜谱的示例代码中发生这种情况时,被持有的气泡不会收到TOUCH_END事件,因此不会再次开始向上漂浮。

您可以通过监听每个气泡实例分发的TouchEvent.TOUCH_ROLL_OUT来纠正这一点。只需在Main类的构造函数中添加以下行:

for(var i:uint = 0; i < bubbles.length; i++)
{
bubbles[i].speed = speeds[i];
bubbles[i].addEventListener(TouchEvent.TOUCH_ROLL_OUT, touchEnd); 
}

现在,当用户将手指从气泡上滑开时,touchEnd()处理程序将被调用,气泡将再次开始移动。

注意

您可以将此菜谱中的代码带入下一个菜谱。如果您为TouchEvent.TOUCH_ROLL_OUT添加了事件监听器,则在继续之前请将其再次移除,因为它不是必需的,如果保留它会产生奇怪的行为。

还有更多...

您的处理程序收到的每个事件对象都包含与该触摸事件相关的多个属性。在检测多个触摸点时,您可能会发现以下属性很有用。

主要触摸点

当在屏幕的多个位置触摸时,首先触摸的位置被认为是主要触摸点。当您的处理程序接收到TouchEvent对象时,您可以通过查询其isPrimaryTouchPoint属性来确定这一点。

触摸点 ID

每个新的触摸点都会分配一个唯一的 ID,并用于所有与该接触点相关的事件。您可以通过检查事件的 touchPointID 属性来确定与事件相关联的触摸点。

本地触摸坐标

您可以使用 localXlocalY 属性来确定触摸事件相对于交互对象的坐标。请注意,由于技术的性质和指尖覆盖的表面积,这两个属性在触摸屏设备上不会提供像素级的精确度。

全局触摸坐标

您还可以获取事件发生的位置,在全局舞台坐标中。只需检查事件的 stageXstageY 属性的值。

参见

  • 将类链接到电影剪辑符号,第三章

  • 使用更新循环,第三章

  • 设置触摸点输入模式

  • 拖动多个显示对象

拖动多个显示对象

在触摸屏上,用手指拖动显示对象的行为非常直观。Adobe AIR 提供了 API 调用,允许这种类型的交互而不需要太多努力。此外,iOS 的多点触控功能可以被利用,以允许同时拖动多个对象。

我们将继续在 检测多个触摸点 配方中留下的地方,并添加拖动气泡在屏幕周围的能力。

准备工作

如果您还没有这样做,请在继续之前完成 检测多个触摸点 配方。

您可以继续使用在该配方中编写的代码。或者,从本书的配套代码包中,将 chapter5\recipe3\recipe.fla 打开到 Flash Professional 中,并从那里开始工作。

如何做...

打开 FLA 的文档类并执行以下步骤:

  1. 声明以下成员变量:

    private var touching:Array;
    
    
  2. 此数组将用于将触摸点映射到 Bubble 实例。

  3. 在构造函数中,将 touching 成员变量设置为空数组:

    public function Main() {
    touching = [];
    Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
    stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBegin);
    stage.addEventListener(TouchEvent.TOUCH_END, touchEnd);
    
    
  4. 移动到 touchBegin() 事件处理程序并做出以下更改:

    private function touchBegin(e:TouchEvent):void {
    var b:Bubble = e.target as Bubble;
    if(b != null && !b.held)
    {
    b.held = true;
    b.startTouchDrag(e.touchPointID);
    touching[e.touchPointID] = b;
    }
    }
    
    
  5. 现在也修改 touchEnd() 处理程序:

    private function touchEnd(e:TouchEvent):void {
    var b:Bubble = touching[e.touchPointID];
    if(b != null)
    {
    b.held = false;
    b.stopTouchDrag(e.touchPointID);
    delete touching[e.touchPointID];
    touching[e.touchPointID] = null;
    }
    }
    
    
  6. 保存 Main.as

  7. 发布 FLA 并将 IPA 部署到您的设备上。

当您运行应用程序时,您现在将能够停止并拖动气泡。您甚至可以同时拖动多个气泡。试试看。

它是如何工作的...

该配方中的大部分工作都是由 startTouchDrag()stopTouchDrag() 执行的。这两个方法都是由 flash.display.Sprite 定义的,并且也适用于继承它的类,包括我们的 Bubble 类。

startTouchDrag() 方法允许用户拖动气泡穿过屏幕。它是通过将触摸点 ID 与气泡关联,并持续更新气泡的位置以反映触摸点的位置来实现的。

另一方面,stopTouchDrag() 方法通过指定的触摸点 ID 停止气泡的拖动。

让我们看看调用 startTouchDrag()touchBegin() 事件处理器。有两行代码特别引人注目:

private function touchBegin(e:TouchEvent):void {
var b:Bubble = e.target as Bubble; 
if(b != null && !b.held)
{
b.held = true;
b.startTouchDrag(e.touchPointID); 
touching[e.touchPointID] = b;
}
}

首先,通过查询事件对象的 target 属性来获取被触摸的交互对象,并尝试将其转换为 Bubble 对象。如果对象是气泡,则使用事件对象的触摸点 ID 作为参数调用其 startTouchDrag() 方法。

屏幕上的每个接触点都被分配了一个唯一的 ID,这些 ID 可以用于 startTouchDrag()stopTouchDrag() 等方法。您可以通过检查事件的 touchPointID 属性来确定与事件相关联的触摸点。我们利用这些唯一的 ID 在代码中将气泡与触摸点关联起来。您可以在 touchBegin() 事件处理器的末尾看到这种映射:

private function touchBegin(e:TouchEvent):void {
var b:Bubble = e.target as Bubble;
if(b != null && !b.held)
{
b.held = true;
b.startTouchDrag(e.touchPointID);
touching[e.touchPointID] = b; 
}
}

处理器使用 touching 成员变量来存储用户正在拖动的气泡的引用。气泡实例被放置在 touching 数组中,事件对象的触摸点 ID 被用作索引位置。

现在,让我们看看 touchEnd() 事件处理器,我们从 touching 数组中获取用户刚刚释放的气泡:

private function touchEnd(e:TouchEvent):void {
var b:Bubble = touching[e.touchPointID]; 
if(b != null)
{
b.held = false;
b.stopTouchDrag(e.touchPointID); 
delete touching[e.touchPointID];
touching[e.touchPointID] = null; 
}
}

在上述方法中,通过获取事件对象的 touchPointID 并使用它从 touching 数组中检索相关的气泡。如果检索到了气泡实例,则使用事件对象的触摸点 ID 作为参数调用其 stopTouchDrag() 方法。这将停止用户用手指拖动气泡。

最后,在方法末尾,从 touching 数组中移除气泡引用,因为它不再需要:

private function touchEnd(e:TouchEvent):void {
var b:Bubble = touching[e.touchPointID];
if(b != null)
{
b.held = false;
b.stopTouchDrag(e.touchPointID);
delete touching[e.touchPointID];
touching[e.touchPointID] = null;
}
}

那就是全部内容。通过使用 Sprite 类的 startTouchDrag()stopTouchDrag() 方法以及跟踪触摸点 ID,我们能够管理多个交互对象的拖动。

您可以从 Adobe 社区帮助中获取有关 flash.display.Sprite 类的更多信息。

还有更多...

以下是一些关于 startTouchDrag() 方法的更多信息。

startTouchDrag() 参数

startTouchDrag() 方法期望有三个参数,其中只有第一个是必需的:

  • touchPointID: 将用于拖动精灵的触摸点的 ID。

  • lockCenter: 是否将精灵的中心锁定到触摸点(true),还是锁定到与精灵接触的点(false)。默认为 false

  • bounds: 定义正在拖动的精灵的约束区域的 Rectangle。默认为 null,表示没有约束区域。

此菜谱的示例代码只使用了第一个参数。这意味着气泡的中心没有被锁定到用户的指尖,用户可以自由地将气泡拖动到屏幕上的任何位置。

要强制将气泡的中心锁定到用户的指尖,只需将 true 作为第二个参数传递:

b.startTouchDrag(e.touchPointID, true);

以下示例还将气泡限制在屏幕左上角的 200x200 像素区域内:

b.startTouchDrag(
e.touchPointID, true, new Rectangle(0, 0, 200, 200));

尝试将每个示例应用到你的代码中。

参见

  • 设置触摸点输入模式

  • 跟踪移动

跟踪移动

我们还没有详细研究的一个重要基于触摸的事件是 TouchEvent.TOUCH_MOVE。当用户在屏幕上移动手指时,此事件被触发,可以通过查询来确定接触点的坐标。每次用户的手指改变位置时,都会派发一个新的 TOUCH_MOVE 事件。

虽然 startTouchDrag()stopTouchDrag() 建议用于拖动对象,但你也可以通过响应 TOUCH_MOVE 事件来更新对象的位置。

让我们对 拖动多个显示对象 配方中的代码进行一些修改以实现这一点。

准备工作

在继续之前,如果你还没有这样做,请完成 拖动多个显示对象 配方。

你可以继续使用那个配方中的代码。或者,从本书的配套代码包中,打开 chapter5\recipe4\recipe.fla 到 Flash Professional 中,并从那里开始工作。

如何操作...

在 FLA 的文档类中执行以下步骤:

  1. 移动到构造函数并添加对 TouchEvent.TOUCH_MOVE: 的监听器:

    public function Main() {
    touching = [];
    Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
    stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBegin);
    stage.addEventListener(TouchEvent.TOUCH_END, touchEnd);
    stage.addEventListener(TouchEvent.TOUCH_MOVE, touchMove); 
    
    
  2. 通过从 if 语句中删除高亮显示的代码行,从 touchBegin() 处理器中删除对 startTouchDrag() 的调用:

    private function touchBegin(e:TouchEvent):void {
    var b:Bubble = e.target as Bubble;
    if(b != null && !b.held)
    {
    b.held = true;
    b.startTouchDrag(e.touchPointID, true); 
    touching[e.touchPointID] = b;
    }
    }
    
    
  3. 还要从 touchEnd() 处理器中删除对 stopTouchDrag() 的调用,通过从 if 语句中删除高亮显示的代码行:

    private function touchEnd(e:TouchEvent):void {
    var b:Bubble = touching[e.touchPointID];
    if(b != null)
    {
    b.held = false;
    b.stopTouchDrag(e.touchPointID); 
    delete touching[e.touchPointID];
    touching[e.touchPointID] = null;
    }
    }
    
    
  4. 现在编写 touchMove() 事件处理器:

    private function touchMove(e:TouchEvent):void {
    var b:Bubble = touching[e.touchPointID] as Bubble;
    if(b != null)
    {
    b.x = e.stageX;
    b.y = e.stageY;
    }
    }
    
    
  5. 保存 Main.as

  6. 发布 FLA 并将 IPA 部署到您的设备上。

此示例应与上一个配方以相同的方式表现。

它是如何工作的...

虽然之前通过 startTouchDrag()stopTouchDrag() 来处理拖动,但在这个配方中,我们通过响应 TouchEvent.TOUCH_MOVE 来手动更新气泡的位置。

大部分工作是在 touchMove() 事件处理器中完成的,如下所示:

private function touchMove(e:TouchEvent):void {
var b:Bubble = touching[e.touchPointID] as Bubble;
if(b != null)
{
b.x = e.stageX;
b.y = e.stageY;
}
}

使用事件的触摸点 ID,从 touching 数组中检索与其关联的气泡(如果有)。然后更新气泡的 xy 属性,以反映用户手指在屏幕上的位置,该位置是从事件的 stageXstageY 属性中检索到的。

每当用户的手指在设备屏幕上改变位置时,TOUCH_MOVE 事件就会被派发,并且与该接触点关联的任何气泡都会重新定位以匹配手指的位置。

尽管这个配方主要集中在使用 TOUCH_MOVE 来执行拖动,但此事件可以应用于许多其他任务。例如,它可以用于跟踪绘画应用程序中的手指移动或为游戏角色绘制路径。

如果你正在你的应用中实现拖动,建议你使用 startTouchDrag()stopTouchDrag(),这比监听 TOUCH_MOVE 事件有更好的性能。然而,既然你已经熟悉了 TOUCH_MOVE 事件,你应该能够将其用于各种其他用途。

参考也

  • 设置触摸点输入模式

  • 拖动多个显示对象

设置手势输入模式

除了处理简单的多触点事件外,AIR for iOS 还提供了对缩放、旋转和滑动等手势的支持。手势是由一系列简单的多触点事件组成的单个事件。虽然你可以捕获多触点事件并将它们转换为手势,但 Flash 平台也提供了对最常见手势的支持,从而减轻了你的工作量。

为了接收手势事件,你必须选择适当的输入模式。

让我们看看这是如何完成的。

准备工作

从 Flash Professional 中,打开书籍附带代码包中的 chapter5\recipe5\recipe.fla

在舞台上坐着的是一个名为 output 的动态文本字段。我们将编写一些代码以启用手势输入,并将请求的成功或失败写入文本字段。

如何操作...

执行以下步骤:

  1. 创建一个文档类,并将其命名为 Main

  2. 添加以下两个导入语句:

    import flash.display.MovieClip;
     import flash.ui.Multitouch;
    import flash.ui.MultitouchInputMode; 
    
    
  3. 现在在构造函数中,添加一些代码以启用手势支持:

    public function Main() {
     if(Multitouch.supportsGestureEvents)
    {
    Multitouch.inputMode = MultitouchInputMode.GESTURE;
    output.text = ("inputMode = " + Multitouch.inputMode);
    }
    else
    {
    output.text = "Gesture events not supported.";
    } 
    }
    
    
  4. 将类文件保存为 Main.as

  5. 发布 FLA 并将 IPA 文件部署到你的 iOS 设备上。

当你运行应用时,以下文本应显示在屏幕上:

  • inputMode = gesture

它是如何工作的...

Flash 提供了各种多触点输入模式,这些模式决定了你的应用可以接收的事件类型。为了接收手势事件,你需要将 Multitouch.inputMode 属性设置为 MultitouchInputMode.GESTURE。以下是从你的文档类中执行此操作的代码行:

Multitouch.inputMode = MultitouchInputMode.GESTURE;

除了设置 Multitouch.inputMode,你还可以查询它以确定当前选定的输入模式。在这个菜谱的代码示例中,当前输入模式被写入 output 文本字段以确认它已成功设置:

output.text = ("inputMode = " + Multitouch.inputMode);

虽然 Flash 在所有 iOS 设备上提供手势支持,但在编写跨平台代码时,你可能想通过检查 Multitouch.supportsGestureEvents 属性来确认支持。在我们的代码示例中,这是在设置输入模式之前完成的。

应注意,当输入模式设置为处理手势时,你将无法从 TouchEvent 类接收基本的触摸事件。如果你需要同时接收触摸和手势事件,那么你需要选择 MultitouchInputMode.TOUCH_POINT 输入模式,并在将它们合成手势事件之前捕获多个触摸事件。

关于手势输入模式的更多信息,请在 Adobe 社区帮助中搜索flash.ui.Multitouchflash.ui.MultitouchInputMode

苹果非常重视手势的正确使用,以确保应用程序之间的一致性。苹果的 iOS 人机界面指南包含了一系列标准手势以及用户通常使用它们执行的操作。当在您自己的应用程序中支持手势时,尽量不偏离预期的行为。

还有更多...

以下是一些关于手势的额外细节。

可用的手势事件和类型

设置手势的输入模式允许您监听由类型为InteractiveObject或继承自InteractiveObject的对象(如Sprite, MovieClip, 和Stage)分发的特定手势事件。

与触摸点输入一样,手势也可以利用多个触摸点。

以下手势事件可用:

  • GestureEvent.GESTURE_TWO_FINGER_TAP: 当使用两个手指轻击屏幕时触发。

  • TransformGestureEvent.GESTURE_PAN: 尝试移动通常太大而无法适应屏幕的内容。当两个手指在屏幕内容上移动时,平移手势被触发。

  • TransformGestureEvent.GESTURE_ROTATE: 当两个触摸点相互旋转时触发。此手势通常用于旋转屏幕上的内容。

  • TransformGestureEvent.GESTURE_SWIPE: 用手指快速在屏幕上划过。滑动手势通常用于滚动列表或快速在信息页之间切换。

  • TransformGestureEvent.GESTURE_ZOOM: 两个触摸点要么相互靠近,要么相互远离。此手势通常用于缩放屏幕上的内容。

我们将在本章剩余部分看到一些这些事件的实际应用。

确定支持的手势

您可以使用静态属性Multitouch.supportedGestures获取您的 iOS 设备支持的手势列表。将返回一个字符串向量数组,其中每个字符串代表一个手势事件。

鼠标事件

默认输入模式是MultitouchInputMode.NONE,它指定所有与触摸设备交互的用户操作都被解释为鼠标事件。然而,与MultitouchInputMode.GESTUREMultitouchInputMode.TOUCH_POINT不同,任何时刻只能处理一个触摸点。

注意,当输入模式设置为MultitouchInputMode.GESTURE时,您可以继续监听并响应由flash.events.MouseEvents提供的鼠标事件。

在 ADL 中进行测试

很可能在 ADL 中测试此代码配方会导致屏幕上输出以下消息:

  • 不支持的手势事件。

并非所有台式电脑或操作系统都支持基于手势的事件。当在代码中使用手势时,建议您直接在 iOS 设备上进行测试。

参见

  • 处理用户交互,第四章

  • 设置触摸点输入模式

  • 处理滑动手势

  • 平移对象

处理滑动手势

触摸屏的引入使得在信息页面之间移动的过程变得更加自然。iPhone 使得简单的触摸手势,如滑动,变得流行。例如,许多图片查看器应用程序允许用户快速滑动手指以查看序列中的下一张图片。

TransformGestureEvent.GESTURE_SWIPE 事件可用,允许检测并处理垂直和水平滑动手势。

让我们看看这是如何完成的。

准备工作

从 Flash Professional 中,打开书籍附带代码包中的 chapter5\recipe6\recipe.fla

在舞台上有一个名为 content 的容器电影剪辑,其宽度是舞台的两倍以上。容器内部有两个不同的气泡,任何时刻只能有一个气泡能够显示在屏幕上。我们将编写代码,让用户可以在两个气泡之间水平滑动。

如何完成...

执行以下步骤以监听并响应水平滑动手势:

  1. 创建一个文档类,并将其命名为 Main

  2. 包含以下导入语句:

    import flash.display.MovieClip;
     import flash.events.TransformGestureEvent;
    import flash.ui.Multitouch;
    import flash.ui.MultitouchInputMode;
    import fl.transitions.Tween;
    import fl.motion.easing.Sine; 
    
    
  3. 在类的构造函数中添加以下代码:

    public function Main() {
     Multitouch.inputMode = MultitouchInputMode.GESTURE;
    stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE, swipe);
    } 
    
    
  4. 现在添加滑动手势的事件处理程序:

    private function swipe(e:TransformGestureEvent):void {
    var t:Tween;
    if(e.offsetX == -1) 
    {
    t = new Tween(content, "x", Sine.easeOut, content.x, -465, 0.25, true);
    }
    else if(e.offsetX == 1) 
    {
    t = new Tween(content, "x", Sine.easeOut, content.x, -35, 0.25, true);
    }
    }
    
    
  5. 将类文件保存为 Main.as

  6. 发布 FLA 并将 IPA 部署到您的设备上。

快速从右向左滑动手指以移动到第二个气泡,从左向右滑动以返回到第一个。

它是如何工作的...

手势事件可以由任何 InteractiveObject 或其子类(如 Sprite, MovieClipStage)触发。

在这个菜谱中,我们利用手势输入模式来监听并响应 TransformGestureEvent.GESTURE_SWIPE

通过以下代码行启用了基于手势的输入支持:

Multitouch.inputMode = MultitouchInputMode.GESTURE;

然后添加了对 GESTURE_SWIPE 事件的监听器:

stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE, swipe);

注意,监听器实际上被添加到了舞台,允许用户在屏幕上的任何位置滑动,而不仅仅是 content 电影剪辑上。

swipe() 处理程序中,我们响应用户的滑动手势并将 content 电影剪辑滑动到其最左侧或最右侧。

为了决定将电影剪辑滑动到哪个方向,我们检查 TransformGestureEvent 对象的 offsetX 属性。值为 1 表示用户向右滑动,而值为 -1 表示用户向左滑动。您可以看到以下代码被突出显示:

private function swipe(e:TransformGestureEvent):void {
var t:Tween;
if(e.offsetX == -1)
{
t = new Tween(content, "x",
Sine.easeOut, content.x, -465, 0.25, true);
}
else if(e.offsetX == 1)
{
t = new Tween(content, "x",
Sine.easeOut, content.x, -35, 0.25, true);
}
}

最后,实际的内容滚动操作被执行。使用 fl.transitions.Tween 类将 content 电影剪辑滑动到正确位置。为了在滑动过渡期间实现逐渐加速和减速,使用了 fl.motion.easing.Sine 类。有关这两个类的更多信息,请参考 Adobe Community Help。

更多内容...

以下是与滑动手势相关的 TransformGestureEvent 的另一个属性。

垂直滑动

虽然本食谱的示例代码中没有涉及,但您同样可以通过查询事件的offsetY属性来轻松检测垂直滑动。向上滑动将返回-1的值,而向下滑动将返回1

虽然水平和垂直滑动动作分别由不同的属性表示,但 AIR for iOS 不支持对角线滑动手势。用户可以水平或垂直滑动。

参见

  • 设置手势输入模式

  • 平移对象

平移对象

由于 iOS 设备(如 iPhone 和 iPod touch)屏幕的大小限制,用户可能需要平移或滚动以显示隐藏的内容。Flash 平台提供了TransformGestureEvent.GESTURE_PAN事件,您可以通过监听该事件来检测任何交互对象的平移手势。手势是通过用户将两个手指放在一个对象上并在屏幕上滑动它们来触发的。

本食谱将向您展示如何利用平移手势在您的项目中。

准备工作

从 Flash Professional 中,打开书籍附带代码包中的chapter5\recipe7\recipe.fla

舞台上有一个名为bubble的电影剪辑,它太大而无法完全显示在屏幕上。我们将编写一些 ActionScript 代码,让用户可以平移电影剪辑,以便看到隐藏的部分。

如何操作...

执行以下步骤:

  1. 创建一个名为Main的文档类。

  2. 添加以下三个导入语句:

    import flash.display.MovieClip;
     import flash.events.TransformGestureEvent;
    import flash.ui.Multitouch;
    import flash.ui.MultitouchInputMode; 
    
    
  3. 在构造函数中,设置输入模式并监听TransformGestureEvent.GESTURE_PAN:

    public function Main() {
     Multitouch.inputMode = MultitouchInputMode.GESTURE;
    bubble.addEventListener(TransformGestureEvent.GESTURE_PAN, pan); 
    }
    
    
  4. 编写GESTURE_PAN事件的处理程序:

    private function pan(e:TransformGestureEvent):void {
    bubble.x += e.offsetX;
    bubble.y += e.offsetY; 
    }
    
    
  5. 将类文件保存为Main.as

  6. 发布 FLA 并将 IPA 部署到您的设备上。

用两个手指触摸屏幕上的气泡,然后滑动它们以平移内容。

它是如何工作的...

为了响应平移手势,添加了一个监听器TransformGestureEvent.GESTURE_PAN

bubble.addEventListener(TransformGestureEvent.GESTURE_PAN,
pan);

当用户在屏幕上滑动两个手指时,GESTURE_PAN事件会重复发送。实际的内容平移发生在pan()事件处理程序中。在这里,我们使用传递给方法的TransformGestureEvent对象的offsetXoffsetY属性:

private function pan(e:TransformGestureEvent):void {
bubble.x += e.offsetX;
bubble.y += e.offsetY;
}

两个属性共同提供了用户自上次GESTURE_PAN事件以来手指移动的水平和垂直距离。我们只需使用这些偏移量来重新定位bubble电影剪辑。

更多信息,请在 Adobe 社区帮助中搜索flash.events.TransformGestureEvent

更多...

以下是一些关于平移的最终事项,包括TransformGestureEvent类的一个可能对你有用的属性。

手势阶段

一些手势事件被分为三个不同的阶段,称为开始、更新和结束。如果您的应用程序需要响应手势事件的各个阶段,则可以查询事件的phase属性。每个阶段都由flash.events.GesturePhase类提供的常量表示。

例如,当用户在屏幕上平移内容时,GESTURE_PAN事件将经历这些阶段中的每一个:

  • GesturePhase.BEGIN: 用户用两只手指触摸屏幕并开始在其上移动

  • GesturePhase.UPDATE: 用户正在屏幕上移动两只手指

  • GesturePhase.END: 用户从屏幕上抬起一个或两个手指

让我们看看一个简单的例子,其中此菜谱中的bubble电影剪辑在手势阶段的开始时扩大尺寸,然后在手势阶段的结束时缩小回原始尺寸。在更新阶段,用户将能够像以前一样平移内容:

private function pan(e:TransformGestureEvent):void {
if(e.phase == GesturePhase.BEGIN)
{
bubble.scaleX += 0.2;
bubble.scaleY += 0.2;
}
else if(e.phase == GesturePhase.END)
{
bubble.scaleX -= 0.2;
bubble.scaleY -= 0.2;
}
else if(e.phase == GesturePhase.UPDATE)
{
bubble.x += e.offsetX;
bubble.y += e.offsetY;
}
}

修改您的代码,并添加对flash.events.GesturePhase的导入语句。将 IPA 部署到您的设备上,尝试平移屏幕内容,以感受手势的各个阶段发生时的感觉。

注意

您可以将此菜谱中的代码带入下一个菜谱。如果您已经做了上述更改,那么在继续之前请删除它们,因为它们不是必需的。

抓取和双指轻触手势都没有多个阶段。当使用这两种手势之一时,phase属性将始终返回GesturePhase.ALL

单指平移

GESTURE_PAN事件仅检测使用两只手指发起和控制的平移。在 iOS 上预期的单指平移可以通过使用flash.display.Sprite提供的startTouchDrag()stopTouchDrag()方法来实现。有关详细信息,请参阅本章前面的拖动多个显示对象菜谱。

参考内容

  • 设置手势输入模式

  • 拖动多个显示对象

  • 旋转对象

旋转对象

旋转是 iOS 应用中另一种流行的手势。它通过在您的设备屏幕上放置两只手指,并围绕另一个接触点旋转一个接触点,或者围绕彼此旋转两个接触点来执行。为了允许内容的旋转,您可以监听并响应TransformGestureEvent.GESTURE_ROTATE事件。

我们将从平移对象菜谱继续,并添加旋转屏幕内容的功能。

准备工作

如果您还没有这样做,请在继续之前完成平移对象菜谱。

您可以继续使用在该菜谱中编写的代码。或者,从书籍的配套代码包中打开chapter5\recipe8\recipe.fla,并从那里开始工作。您也可以在同一个文件夹中找到 FLA 的文档类。

如何操作...

在 FLA 的文档类中执行以下步骤:

  1. 在构造函数中,监听TransformGestureEvent.GESTURE_ROTATE:

    public function Main() {
    Multitouch.inputMode = MultitouchInputMode.GESTURE;
    bubble.addEventListener(TransformGestureEvent.GESTURE_PAN, pan);
    bubble.addEventListener(TransformGestureEvent.GESTURE_ROTATE, rotate); 
    }
    
    
  2. 添加一个响应事件的处理器:

    private function rotate(e:TransformGestureEvent):void {
    bubble.rotation += e.rotation;
    }
    
    
  3. 保存您的更改。

  4. 发布 FLA 并在你的设备上测试它。

你现在应该能够旋转屏幕上的内容,同时也能够平移它。

注意

如果你正在较旧的设备上进行测试,可能会发现应用程序性能不佳,帧率远低于目标。如果你使用 Flash Professional CS5 进行开发,这一点尤其正确。不用担心;有方法可以显著提高性能,我们将在第六章图形和硬件加速中介绍。

它是如何工作的...

仅需要几个简单的步骤即可添加旋转支持。

首先,向bubble电影剪辑中添加了对TransformGestureEvent.GESTURE_ROTATE事件的监听器:

bubble.addEventListener(TransformGestureEvent.GESTURE_ROTATE,
rotate);

最后,实际的事件处理程序查询了事件的rotation属性,以确定如何旋转电影剪辑:

private function rotate(e:TransformGestureEvent):void {
bubble.rotation += e.rotation; 
}

rotation属性指定了自上次手势事件以来的旋转变化,以度为单位。然后,将此值添加到气泡的当前旋转角度,以正确更新它。

相关内容

  • 设置手势输入模式

  • 缩放对象

  • 使用缓存为位图矩阵,第六章

缩放对象

本章我们将探讨的最后一个手势是“缩放”,它允许用户缩放内容。通常是通过用两个手指捏合屏幕来执行。将手指靠近会缩小视图,而将手指分开则会放大视图。Flash 平台提供了TransformGestureEvent.GESTURE_ZOOM事件,你可以监听并响应它。

准备工作

如果你还没有这样做,请在执行此操作之前完成旋转对象配方。

你可以继续使用在那个配方中编写的代码。或者,从书中附带代码包中的 FLA 和文档类开始工作,位于chapter5\recipe9\

如何实现...

对 FLA 的文档类进行以下更改:

  1. 在构造函数中,监听GESTURE_ZOOM事件:

    public function Main() {
    Multitouch.inputMode = MultitouchInputMode.GESTURE;
    bubble.addEventListener(TransformGestureEvent.GESTURE_PAN, pan);
    bubble.addEventListener(TransformGestureEvent.GESTURE_ROTATE, rotate);
    bubble.addEventListener(TransformGestureEvent.GESTURE_ZOOM, zoom); 
    }
    
    
  2. 现在,为缩放手势添加事件处理程序:

    private function zoom(e:TransformGestureEvent):void {
    bubble.scaleX *= e.scaleX;
    bubble.scaleY *= e.scaleY;
    }
    
    
  3. 保存类文件。

  4. 发布 FLA 并将 IPA 部署到你的设备上。

你现在应该能够使用 Flash 平台提供的手势来平移、旋转和缩放气泡。

注意

如果你正在较旧的设备上进行测试,可能会发现应用程序性能不佳,帧率远低于目标。如果你使用 Flash Professional CS5 进行开发,这一点尤其正确。不用担心;有方法可以显著提高性能,我们将在第六章图形和硬件加速中介绍。

它是如何工作的...

与本章中介绍的其他手势一样,实现捏合缩放并不困难。

TransformGestureEvent.GESTURE_ZOOM添加了一个事件监听器,随后是事件处理器,该处理器负责实际放大bubble电影剪辑。

以下是用以注册监听器的代码行:

bubble.addEventListener(TransformGestureEvent.GESTURE_ZOOM, zoom);

您可以在zoom()事件处理器中看到气泡的scaleXscaleY属性被设置如下:

private function zoom(e:TransformGestureEvent):void {
bubble.scaleX *= e.scaleX;
bubble.scaleY *= e.scaleY;
}

TransformGestureEvent对象的scaleXscaleY属性指定了自上次手势事件以来的水平和垂直缩放变化。要将这些值应用到显示对象上,只需将显示对象的scaleXscaleY属性分别与事件对象的scaleXscaleY属性相乘。您可以在之前的代码中看到这一操作。

这可能不是立即显而易见的,但气泡的库符号其注册点设置在其中心。在缩放内容时,确保您容器剪辑内的艺术品居中,否则当用户执行缩放手势时可能会遇到意外的行为。

参见

  • 设置手势输入模式

  • 使用缓存作为位图矩阵,第六章

第六章. 图形和硬件加速

在本章中,我们将涵盖:

  • 比较矢量图形和位图图形

  • 理解 GPU-混合模式

  • 理解 GPU-矢量模式

  • 使用缓存作为位图

  • 使用缓存作为位图矩阵

  • 使用 ActionScript 访问位图

  • 在运行时加载位图

  • 使用精灵图集工作

  • 使用 ActionScript 执行位图动画

简介

CS5 的发布使得 Flash 开发者能够在不改变工作流程的情况下为 iOS 设备创建令人兴奋的内容。然而,由于现代桌面或笔记本电脑计算能力的只有一小部分,为 iPhone 等设备开发需要特殊的设计和编码考虑。

最大的瓶颈之一是图形渲染,它已经成为许多人的烦恼之源。简单地构建与桌面交付相同的图形密集型 FLA,并期望它们在移动设备上运行良好,这是不现实的。即使看似简单的图形操作,如果实现不当,在 iOS 设备上也可能表现不佳。

通过提供你已熟悉的强大绘图和动画工具,Flash IDE 实际上可能会让你产生一种虚假的安全感。例如,复杂的矢量图形、蒙版、时间轴动画、深度嵌套的显示列表和 alpha 透明度都很容易创建,但可能会对你的应用程序性能产生负面影响。针对移动设备需要仔细规划、分析和了解你正在为哪个硬件开发。

在本章中,我们将探讨许多优化渲染性能的技术。我们将涵盖 Flash 的渲染管道以及你将在其中工作的硬件限制。此外,我们还将了解如何利用硬件加速,将大部分渲染工作量从 CPU 卸载到图形处理单元(GPU)。

比较矢量图形和位图图形

尽管 Flash 提供了位图支持,但它主要被视为矢量动画工具。矢量内容可以直接在 IDE 中创建和编辑,这使得矢量图形成为比必须在外部编辑的位图更明显的选择。

然而,考虑到移动设备如 iPhone 的硬件限制,矢量图形是否合适,或者你应该考虑使用位图以最大化性能?

准备工作

为此配方提供了两个 FLA,可以在书的配套代码包中找到,位于chapter6\recipe1\

两者都执行一个简单的渲染性能测试。每个都尝试渲染十个动画电影剪辑的实例。五秒后,测试将结束,并显示达到的平均每秒帧数(FPS)。这个数字越高,测试的渲染性能就越快。

第一个 FLA— recipe-vectors.fla —为每个电影剪辑的动画帧使用矢量图形。第二个—recipe-bitmaps.fla—则使用位图表示。

如何做...

按以下步骤在你的设备上运行这两个测试:

  1. recipe-vectors.fla打开到 Flash Professional 中。

  2. 在库中,你会找到一个名为Monkey的符号,它包含一个四帧的矢量动画。双击该符号并探索其显示列表。其结构对于 Flash 项目来说是典型的,包含许多嵌套的矢量图形剪辑。

  3. 发布 FLA 文件并部署c6-r1-v.ipa。在你的设备主屏幕上找到名为c6 r1 v的应用并启动它。等待五秒钟,然后记录达到的帧率。

  4. 现在打开recipe-bitmaps.fla。双击Monkey库符号并探索其时间轴。这个 FLA 执行与第一个相同的测试,但它使用位图而不是矢量作为每个动画帧。

  5. 发布 FLA 并部署c6-r1-b.ipa到你的设备。启动c6 r1 b并记录帧率。

它是如何工作的...

每个 iOS 设备的渲染性能可能会有所不同,但无论你使用什么设备,基于位图的动画都将优于基于矢量的等效动画。

为了确认这一点,让我们看看从 Flash Professional CS5 编译的两个 FLA 在多个设备上运行的结果。以下图表显示了每个测试达到的平均帧率,以每秒帧数衡量:

如何工作...

注意

图表中显示的结果是从每个测试的五次运行中得出的平均值。每个设备都运行 iOS 5,除了第一代 iPod touch,它安装了 iOS 3.1。

使用这些结果作为粗略的指南,因为它们可能在不同的运行中略有差异。

那么为什么位图渲染到屏幕上的速度比矢量快?

矢量图形由线条、填充、颜色和渐变组合而成,渲染它们需要昂贵的数学计算。另一方面,位图只是图像所需每种颜色的像素逐个表示。由于位图的每个点都已经知道,它可以快速绘制到屏幕上。

这是否意味着你应该在为 iOS 开发时专门使用位图代替矢量?不一定。与位图不同,矢量图形可以无失真地缩放和转换。这是由于矢量图形是数学上表示的。矢量的另一个优点是文件大小。在许多情况下,矢量比它们的位图对应物消耗的空间要少得多。

然而,如果帧率对你的应用程序的成功至关重要,那么你应该始终尝试选择最快的渲染选项。此外,请注意,这样做可能会以增加内存使用、更大的文件大小和延长开发时间为代价。

还有更多...

无论你选择使用矢量还是位图,调整渲染质量都可以帮助提高性能。

阶段质量

您可以通过降低应用程序使用的渲染质量来进一步提高性能。这在您试图在操作复杂矢量图形的同时最大化帧率时特别有用。

使用 ActionScript,将Stage.quality属性设置为以下常量之一:

  • StageQuality.HIGH: 提供位图平滑和抗锯齿

  • StageQuality.MEDIUM: 提供位图平滑并使用较低质量的抗锯齿

  • StageQuality.LOW: 不平滑位图或抗锯齿图形

从 AIR 3.0 开始,所有三个质量设置都可用,而 AIR 2.0-2.7 仅支持低质量和中等质量。iOS 的所有版本都将StageQuality.MEDIUM作为默认设置。

渲染质量应用于应用程序中的所有内容。然而,位图却相对不受影响,除了平滑处理外,在所有质量设置下看起来都相同。这方便您在不影响应用程序中任何位图质量的情况下,从矢量资源中获得最高性能。您可以在应用程序的生命周期内重复更改质量设置,以最好地适应任何特定时刻的需求。

尝试在此菜谱的 FLA 中降低舞台的渲染质量。只需打开由两者共享的Main.as文档类,并在构造函数的开始处添加以下代码行:

stage.quality = StageQuality.LOW;

此外,添加以下导入语句:

import flash.display.StageQuality;

发布并重新部署两个.ipa文件。

尽管矢量图形的质量将明显降低,但渲染速度现在应该更快。对于许多情况,这种牺牲可能是可以接受的,尤其是在紧凑的移动设备屏幕上,任何质量的降低可能都难以察觉。

参见

  • 将矢量转换为位图,第四章

  • 调整位图大小,第四章

理解 GPU-混合模式

与为 Flash 桌面播放器开发不同,针对 iOS 的 AIR 提供了两种渲染模式。与桌面播放器中存在的相同软件渲染器作为第一个选项提供,并由设备的 CPU 处理。第二个选项允许您利用设备的 GPU,并在某些情况下显著提高渲染性能。

在编译 iOS 的 FLA 之前必须选择渲染模式,且在运行时无法更改。因此,了解两种模式之间的差异并在早期做出决定,关于您希望支持哪种模式,是非常重要的。渲染器的选择可以决定您如何构建应用程序。

虽然 Flash Professional CS5 和 CS5.5 都提供了一个在 GPU 上执行渲染的选项,但实际上实现渲染模式的方式不同。

在这个菜谱中,我们将发布和部署一些示例 FLA,以帮助您了解两种模式之间的差异。特别是,我们将重点关注 Flash Professional CS5 提供的 GPU 渲染模式。

准备工作

本书附带代码包中提供了两个 FLA——“render-test-cpu.fla”和“render-test-gpu.fla”——可以在 chapter6\recipe2\ 中找到。

两个 FLA 都是相同的,每个在每一帧更新时都会随机重新定位十个电影剪辑实例。五秒后,测试将结束,并显示达到的平均每秒帧数(FPS)。这个数字越高,测试的渲染性能就越快。

对于这个菜谱,FLA 应仅使用 Flash Professional CS5 编译。但是,如果您使用的是 CS5.5,请在进入下一个菜谱之前阅读这里涵盖的材料。

如何操作...

让我们为每个 FLA 选择一个渲染模式,并看看它们在实际设备上的表现。

  1. 在 Flash Professional CS5 中打开 render-test-cpu.fla

  2. 选择 文件 | iPhone OS 设置

  3. iPhone OS 设置 面板中,从 渲染 字段的下拉菜单中选择 CPU。点击 确定 以确认更改。如何操作...

  4. 保存 FLA。

  5. 发布 FLA 并将 c6-r2-cpu.ipa 部署到您的设备上。在您的设备主屏幕上找到名为 c6 r2 cpu 的应用程序并启动它。记录测试达到的帧率,然后关闭应用程序。

  6. 现在,打开 render-test-gpu.fla

  7. 选择 文件 | iPhone OS 设置。这次,将面板的 渲染 字段设置为 GPU

  8. 点击 确定 关闭面板。

  9. 保存 FLA。

  10. c6-r2-gpu.ipa 发布并部署到您的设备上。启动名为 c6 r2 gpu 的应用程序。记录达到的帧率。

工作原理...

从 iPhone OS 设置面板中,我们为每个 FLA 设置了不同的渲染模式。两个 FLA 执行了相同的测试,但使用了不同的渲染路径。第一个使用 CPU 渲染所有图形内容,而第二个我们选择了 GPU。

下面的图表显示了在一系列设备上运行测试的结果。结果显示了每个测试达到的帧率,以每秒帧数(fps)来衡量。

工作原理...

注意

图表中显示的结果是从每个测试的五次运行中取出的平均值。每个设备都运行 iOS 5,除了第一代 iPod touch,它安装了 iOS 3.1。

将这些结果作为大致的指南,因为它们可能在不同的运行中略有差异。

如您所见,实际结果在不同设备上有所不同,但令人惊讶的是,两种模式之间的性能差异非常小,CPU 略快。您可能预计 GPU 渲染会比 CPU 显著更好,但为了理解为什么情况并非如此,我们需要更详细地检查渲染过程。特别是,我们需要查看 AIR 2.0 在 Flash Professional CS5 中如何实现 GPU 渲染。

渲染过程

渲染被分为以下两个不同的部分:

  • 光栅化

  • 场景合成

光栅化过程中,您显示列表中的每个元素都会绘制到一个单独的离屏像素缓冲区中。

一旦光栅化完成,那些像素缓冲区就会被取出并排列以重新创建由显示列表表示的场景。这被称为场景合成

无论您使用的是 Flash CS5 还是 CS5.5,CPU 和 GPU 模式都会执行此渲染过程。然而,每种渲染模式如何实现这一点是不同的。

CPU 模式与 GPU-混合模式

当使用 CPU 模式时,光栅化和场景合成完全由 CPU 在软件中执行。

在 Flash CS5 中,当选择 GPU 模式时,设备的 GPU 将用于合成场景。然而,光栅化仍然由 CPU 执行,每个离屏像素缓冲区都会上传到 GPU 进行合成。换句话说,渲染过程只在 GPU 上部分执行。这种实现被称为 GPU 混合,与 CS5.5 中使用的实现不同:

CPU 模式与 GPU-混合模式

下表可以帮助您了解 Flash CS5 中 AIR 2.0 使用的 CPU 和 GPU-混合模式之间的区别:

渲染模式 光栅化 场景合成
CPU CPU CPU
GPU 混合 CPU GPU

iOS 设备上发现的 GPU 可以比 CPU 更快地合成场景。然而,由于需要发送的数据量,从 CPU 上传像素缓冲区到 GPU 的过程可能非常昂贵。因此,为了在使用 Flash CS5 时从 GPU 加速中受益,您必须最小化从 CPU 到 GPU 的位图流量。换句话说,您需要减少显示对象重新光栅化的频率。

重新绘制脏区域

当场景中的内容发生变化时,会发生重新光栅化。每当发生变化时,Flash 都会记录下场景中需要重新绘制的矩形区域。这些区域被称为脏区域,并用作仅重新渲染整个屏幕的替代方案。以下图示中星形剪辑的位置移动说明了这一点:

重新绘制脏区域

在这个例子中,星星电影剪辑在帧之间改变位置,从而创建了一个脏区域。脏区域表示为一个矩形区域,它包含了星星之前和当前位置所消耗的空间。圆形、背景图像以及星星本身都触及这个脏区域,这意味着所有三个都需要重新光栅化。任何与脏区域相交的显示对象都需要重新光栅化。

当使用 GPU 混合时,需要将每个重新光栅化的显示对象的位图数据上传到 GPU,以便进行合成。正如所述,上传到 GPU 可能很昂贵。

对于经常变化的场景,当使用 GPU 加速时,你的应用程序的性能可能会受到影响。这就是为什么 render-test-gpu.fla 的表现不如你预期的那么好。每一帧都有很多变化,将重新绘制的像素缓冲区传输到 GPU 的带宽惩罚实际上抵消了利用 GPU 获得的许多性能。

可以采用技术直接在 GPU 上缓存位图数据,而不是从 CPU 持续重新光栅化和上传。我们很快就会讨论这些,但应该清楚的是,充分利用 AIR 2.0 的硬件加速并不像在 iPhone OS 设置面板中更改渲染模式那样简单。

更多内容...

还有一件事,你可能在选择渲染模式时已经注意到了:

自动渲染

除了 CPU 和 GPU,还有一个名为 Auto 的额外渲染选项可用。目前,Auto 实际上默认为 CPU 渲染器,因此与选择 CPU 没有区别。这在 Flash Professional CS5 和 CS5.5 中都是如此。

参见

  • 理解 GPU-矢量模式

  • 使用缓存为位图

  • 使用缓存为位图矩阵

理解 GPU-矢量模式

理解 GPU-混合模式 菜谱中,我们花费时间介绍了 Flash Professional CS5 提供的 GPU 渲染模式的复杂性。尽管 Flash Professional CS5.5 也支持 GPU 渲染,但其实现方式与 CS5 不同。

在这个菜谱中,我们将介绍如何使用 CS5.5 选择渲染模式,并使用 理解 GPU-混合模式 菜谱中的相同测试,以便查看两个 GPU 渲染器之间的性能差异。

准备工作

提供了两个 FLA 文件—render-test-cpu.flarender-test-gpu.fla,可以在本书的配套代码包中找到,位于 chapter6\recipe3\

两个 FLA 文件完全相同,每个在每一帧更新时都会随机重新定位十个电影剪辑实例。五秒后,测试将结束,并显示达到的平均每秒帧数(FPS)。这个数字越高,测试的渲染性能就越快。

FLA 应仅使用 Flash Professional CS5.5 编译。然而,对于使用 CS5 的用户,建议阅读此处涵盖的材料,而不是跳到下一个菜谱。

如何操作...

让我们为每个 FLA 选择不同的渲染模式,并查看在实际设备上两种模式之间的性能差异。

  1. 在 Flash Professional CS5.5 中打开 render-test-cpu.fla

  2. 从 Flash 的下拉菜单中选择 文件 | AIR for iOS 设置

  3. 从 AIR for iOS 设置面板中,从 渲染 字段的下拉框中选择 CPU。点击 确定

  4. 保存 FLA。

  5. 发布 FLA 并将 c6-r3-cpu.ipa 部署到您的设备上。从主屏幕上,启动标有 c6 r3 cpu 的应用程序。让应用程序运行五秒钟,然后记录帧率。

  6. 现在,打开 render-test-gpu.fla

  7. 移动到 AIR for iOS 设置 面板,并将这次 渲染 字段设置为 GPU

  8. 保存 FLA。

  9. c6-r3-gpu.ipa 发布并部署到您的设备上。启动 c6 r3 gpu 并记录应用程序的帧率。

工作原理...

从 AIR for iOS 设置面板中,我们为每个测试 FLA 设置了不同的渲染模式。两个 FLA 执行了相同的测试,但使用了不同的渲染路径。第一个使用 CPU 渲染所有图形内容,而第二个我们选择了 GPU。

下面的图表显示了在一系列设备上运行测试的结果。每个结果都显示了每个测试达到的平均帧率。

工作原理...

备注

本菜谱中显示的结果是从每个测试的五次运行中取出的平均值。每个设备都运行 iOS 5。

使用这些结果作为大致指南,因为它们在运行之间可能会有所不同。

显然,当在 Flash Professional CS5.5 中设置 GPU 渲染时,可以获得令人印象深刻的性能提升。这与使用 Flash Professional CS5 的 理解 GPU-混合模式 菜单的结果形成鲜明对比。以 iPhone 4 为例。当从 CS5 发布时,使用 GPU 没有带来任何好处,但从 CS5.5 发布的相同测试显示了 252% 的渲染性能提升——CPU 使用时每秒 23 帧,而 GPU 使用时为 58 帧。

下面的图表让您可以轻松比较 render-test-gpu.fla 在 Flash Professional 两个版本中的 GPU 渲染结果:

工作原理...

当从 CS5 发布并在 iPhone 4 上运行时,在五秒钟内平均只达到了 17 帧/秒。使用 CS5.5 发布的 FLA 在同一设备上达到了 58 帧/秒。这是一个相当大的改进!

备注

您可能已经注意到,在这个图表中,从 Flash CS5.5 编译的 GPU 测试没有在第一代 iPod touch 上运行。在 AIR 2.6 中取消了第一代 iPod touch 等 ARM v6 设备的支持。

那么,为什么 GPU 渲染在 CS5.5 中比 CS5 产生了如此巨大的提升?这归因于自 AIR 2.6 以来 GPU 渲染实现的改变,我们现在将介绍这一点。

GPU-Vector 模式

Flash CS5 支持的 GPU 混合渲染模式实际上只在实际的 GPU 上执行场景合成——光栅化完全在 CPU 上进行。然而,CS5.5 支持的 GPU 渲染模式既在 GPU 上执行光栅化也在 GPU 上执行场景合成,从而消除了从 CPU 到 GPU 转移位图数据的需求。这种实现被称为 GPU 向量,并且比 GPU 混合快得多。

当选择 GPU 渲染时,从 Flash Professional CS5.5 发布的 AIR for iOS 应用将使用 GPU 向量,而从 CS5 发布的应用将使用 GPU 混合。

以下表格总结了各种渲染模式以及它们在 Flash 和 AIR 中各自的可用版本:

渲染模式 光栅化 场景合成 Flash AIR
CPU CPU CPU CS5 和 CS5.5 2.0 - 3.x
GPU 混合 CPU GPU CS5 2.0
GPU 向量 GPU GPU CS5.5 2.6 - 3.x

当使用 Flash Professional CS5 时,即使是一个普通的 FLA 文件,如果没有理解 GPU 混合并知道如何最小化 CPU 和 GPU 之间的位图流量,要获得高帧率也是困难的。另一方面,使用 Flash Professional CS5.5 的人不必过于担心。GPU-Vector 模式大大减少了困难,使得为 iOS 应用编写 AIR 的过程更接近于桌面应用编写。

使用 GPU 模式而不是 CPU 模式可以获得更好的性能。这对 CS5 和 CS5.5 都适用,尽管使用 CS5 的人需要付出更多努力才能利用 GPU 提供的硬件加速。

GPU 向量是从 Flash Professional CS5 升级到 CS5.5 的一个非常有力的理由。当然,如果你针对的是旧款 iOS 设备,如第二代 iPod touch 或 iPhone 3G,那么你仍然需要依赖于 CS5 和 GPU 混合。

更多...

GPU-Vector 模式的惊人性能确实是有代价的。

使用 GPU-Vector 模式渲染向量

GPU-Blend 和 GPU-Vector 模式之间的性能差异并非唯一显著的差异。虽然 GPU 混合和 CPU 会产生相同的向量艺术作品渲染效果,但 GPU 向量并不总是那么精确。

GPU 优化用于渲染位图,并且在重新创建 Flash 使用的复杂向量形状时,并不提供与软件渲染器相同的保真度。GPU-Vector 模式要求 Flash 的向量形状被转换为 GPU 可以快速渲染的简单三角形。另一方面,GPU 混合在 CPU 上执行所有光栅化,从而可以利用软件渲染器,但以牺牲性能为代价。

当使用 Flash Professional CS5.5 时,请注意,在 GPU 上渲染矢量图形不会像在 CPU 上渲染那样精确。CPU 渲染准确但速度慢,而 GPU 速度快但不够准确。然而,两者之间的任何差异可能都难以察觉。

使用 Flash Professional CS5 的 GPU-Vector 模式

尽管 Flash Professional CS5 只支持 AIR 2.0,但实际上可以利用 AIR 2.6 及以上版本支持的 GPU-Vector 渲染模式。为此,您需要首先从 Flash CS5 发布一个 SWF 文件,然后使用 AIR 开发工具(ADT)从命令行将该 SWF 文件打包成一个原生 iOS 应用程序。ADT 包含在最新的 AIR SDK 中,并可以从 www.adobe.com/products/air/sdk 下载。

命令行打包超出了本书的范围;然而,Adobe 在此主题上提供了详细的文档,可在以下地址找到:help.adobe.com/en_US/air/build/WS901d38e593cd1bac35eb7b4e12cddc5fbbb-8000.html

Stage 3D

除了 AIR 的现有渲染模式之外,Adobe 最近发布了一种名为 Stage 3D 的新渲染模型(之前代号为 Molehill),它利用 GPU 硬件提供高级的 2D 和 3D 功能。

在撰写本文时,Stage 3D 仅在桌面上的 Flash 和 AIR 中可用。然而,Adobe 正在积极努力将其引入移动设备。当它到来时,Stage 3D 的性能应该远超目前通过 AIR for iOS 的现有渲染管线所能实现的。

您可以在 Adobe 开发者连接处了解更多关于 Stage 3D 的信息:www.adobe.com/devnet/flashplayer/stage3d.html

参见

  • 使用缓存位图

  • 使用缓存位图矩阵

使用缓存位图

光栅化可能很昂贵,应该尽量减少。对于仅在 X 和 Y 轴上经历平移的显示对象,有一种技术可以消除该对象需要重新光栅化的需求。这种技术被称为缓存位图,并且在大多数情况下可以加速应用程序的渲染性能。

缓存位图从显示对象中提取并生成其内部的位图表示。然后使用缓存的位图进行渲染,而不是重新光栅化原始显示对象。这可能导致巨大的性能提升,尤其是在处理复杂矢量图形时,这些图形的光栅化可能对 CPU 来说非常耗时。

通常,当一个显示对象改变位置时,它需要重新光栅化。然而,一旦被缓存,任何二维平移都不会导致该对象被重新绘制。相反,将使用其缓存的位图。

让我们看看如何使用 ActionScript 和 Flash IDE 两种方式应用缓存位图。

准备工作

在继续之前,您应该了解矢量图形和位图图形之间的区别,并且对开发 iOS 应用程序时可用各种渲染路径有牢固的理解。如果您还没有这样做,请完成以下菜谱:

  • 比较矢量图形和位图图形

  • 理解 GPU-混合模式

  • 理解 GPU-矢量模式

为此菜谱提供了一个 FLA,可以在本书的配套代码包中找到,位于chapter6\recipe4\recipe.fla

其文档类将十个猴子电影剪辑实例放置在背景电影剪辑的上方。在每一帧更新时,十个猴子被随机重新定位。经过五秒钟后,显示平均帧率。

用于此菜谱的电影剪辑是由矢量图形而不是位图构建的。此外,此菜谱的 FLA 已被设置为使用 GPU 渲染。

如何做到这一点...

我们将首先查看现有版本的 FLA 的性能,然后再利用位图缓存。

  1. 打开recipe.fla

  2. 发布当前版本的 FLA 并将其部署到您的设备上。

  3. 从您的设备主屏幕启动应用程序。

  4. 记录帧率;然后从您的设备中删除应用程序。

  5. 现在,回到 Flash 中的recipe.fla

    让我们将缓存作为位图应用于 FLA 中使用的显示对象。使用选择工具(V),点击舞台上的背景电影剪辑。从属性面板,展开显示部分并启用缓存作为位图。如果您使用的是 Flash Professional CS5,那么这通过勾选缓存为位图复选框来完成。对于 CS5.5,从渲染字段的下拉框中选择缓存为位图

  6. 打开 FLA 的文档类,并在构造函数中添加以下代码行:

    for(var i:uint = 0; i < 10; i++)
    {
    var monkey:MovieClip = new Monkey();
    monkey.x = Math.random() * stage.stageWidth;
    monkey.y = Math.random() * stage.stageHeight;
    monkey.cacheAsBitmap = true;
    monkeys.push(monkey);
    addChild(monkey);
    }
    
    
  7. 保存类。

  8. 发布并部署新版本到您的设备上。

  9. 将帧率与应用程序的先前版本进行比较。应用程序的性能应该有明显的提升。

它是如何工作的...

DisplayObject类提供了cacheAsBitmap属性,该属性从任何扩展DisplayObject的类中可用,例如SpriteMovieClip

我们使用 ActionScript 为每个猴子实例设置了cacheAsBitmap属性:

monkey.cacheAsBitmap = true;

对于位于舞台上的背景电影剪辑,通过属性面板激活了缓存。

要了解位图缓存为何有益,让我们首先检查当未设置缓存为位图时,此菜谱示例中发生的情况。

在每一帧更新时,十个猴子电影剪辑实例的位置都会改变,迫使每个剪辑创建一个脏区域。尽管背景电影剪辑的位置没有改变,但它位于脏区域中。因此,在每一帧更新时,背景和所有十个猴子实例都需要在合成为场景之前重新光栅化。

通过利用缓存为位图,可以减少每帧的渲染时间。在设置缓存为位图后,每个剪辑最初都会进行光栅化,并存储一个内部表示。现在在每次帧更新时,将不需要重新光栅化任何Monkey电影剪辑或背景电影剪辑,因为每个都有缓存的位图表示,可以在场景组成期间使用。

在除了第一次之外的所有帧更新中,我们已经成功完全跳过了光栅化。

不论是使用 Flash Professional CS5 还是 CS5.5,你应该已经通过使用缓存为位图体验到了显著的性能提升。以下图表显示了使用 CS5 发布此示例配方并在一些设备上测试的结果:

如何工作...

以下图表显示了使用 CS5.5 和 AIR 3.0 发布的相同测试:

如何工作...

注意

这些图表中显示的结果是从每个测试的五次运行中取的平均值。每个设备都运行 iOS 5,除了第一代 iPod touch,它安装了 iOS 3.1。

将这些结果作为粗略的指南,因为它们可能在不同的运行中略有差异。

如图表所示,缓存为位图可以在使用复杂矢量图形时显著提高你应用程序的帧率。这确实是以内存为代价的;然而,因为每个显示对象必须存储额外的位图。

尽管我们在本配方中使用了 GPU 渲染,但与 CPU 渲染结合使用缓存为位图也会在处理复杂矢量图形时提高性能。然而,直接在 GPU 上缓存会产生最大的性能提升。

更多内容...

缓存为位图功能非常强大,并且当正确使用时可以带来巨大的好处。然而,并不总是明显何时使用它,并且有一些陷阱你应该注意。

其他变换更改

位图缓存只有在缓存的位图不需要频繁重新生成时才有优势。虽然沿 X 轴或 Y 轴的变化是可以接受的,但其他变化将使缓存的位图无效,迫使显示对象重新缓存。

对于不经常变化的对象,你可能愿意承受性能损失。然而,频繁的变化可能会降低你应用程序的性能,因为每次新的更改都会进行光栅化,然后复制回内部像素缓冲区。

以下是一个列表,列出了将强制显示对象重新缓存的更改:

  • 可见性

  • 透明度

  • 变换—缩放和旋转

  • 在对象的时线上移动播放头

  • 对子对象的任何更改

持续重新缓存非常昂贵,并且会减慢你的应用程序。如果你需要频繁更改对象,那么要么避免使用缓存为位图,要么在这些期间将其停用。不正确地使用缓存为位图将降低你的应用程序的渲染性能,而不是提高它。

缓存包含子对象的显示对象

在设置包含子对象的显示对象的缓存为位图时要小心。

将整个容器及其所有子对象创建为内部位图。如果这些子对象相对于容器有任何变化,那么整个容器剪辑就需要重新缓存。即使子对象只改变了其xy位置,也是如此。只有容器剪辑才能成功平移而不使缓存的位图无效。

对于嵌套剪辑,将缓存为位图应用于相对于其容器发生变化的最低叶节点。不要将缓存为位图应用于容器本身。

这是一个常见的错误,可能会损害你应用程序的性能。

利用 GPU 混合的优势

如果你正在使用 Flash Professional CS5 并希望利用 GPU 渲染,那么使用缓存为位图对于 GPU 混合的有效性是必不可少的。不仅矢量可以从中受益,位图性能也可以得到加速。

缓存的位图存储位置很重要。当使用 GPU 渲染时,缓存的位图将直接存储在 GPU 上作为纹理。这在使用 GPU 混合时尤为重要,因为它消除了当位图数据反复从 CPU 传输到 GPU 时遇到的带宽瓶颈。

通过结合使用位图缓存和 GPU 混合,渲染性能将大大提高。位图数据将从 CPU 传输到 GPU 的唯一时间是在每个显示对象最初缓存时,或者当缓存的位图需要重新生成时。

对于 GPU 混合,缓存为位图将加速使用矢量的显示对象和使用位图的显示对象。尽可能利用它。

位图和 GPU 矢量

虽然将缓存为位图应用于位图可以加速 GPU 混合,但对于 GPU 矢量来说并不适用,实际上可能会略微降低性能。

当你缓存一个显示对象时,你实际上是在创建一个像素缓冲区。然而,位图本质上就是这样。在使用 GPU 矢量时缓存位图,你只是在创建位图的副本来,这只会消耗更多的内存并花费时间来执行第二次复制。

在 GPU-混合模式下,缓存为位图用于将位图复制到 GPU 内存中。在 GPU-矢量模式下,位图已经位于 GPU 内存中,因此不需要缓存为位图。

在位图之前使用矢量

当处理矢量图形时,可以使用“缓存为位图”来产生与位图通常相关的性能优势。只需使用 Flash 的绘图工具创建您的图形作品,然后为包含该矢量图形的每个电影剪辑设置“缓存为位图”。从那时起,剪辑将被光栅化,并使用缓存的位图版本。

这种技术几乎与直接使用您作品的位图表示一样快。唯一的区别是,矢量版本首先必须转换为位图,这将在对象首次出现在屏幕上时产生轻微的性能影响。如果您的 IPA 大小是问题,或者您确实需要使用矢量图形,那么这个选项是理想的。

参见

  • 将内容添加到舞台,第二章

  • 遮罩内容,第四章

  • 使用缓存为位图矩阵

使用缓存为位图矩阵

“缓存为位图”对于仅受二维平移影响的显示对象非常有用。然而,在应用其他更改到显示对象(如缩放和旋转)时,也可以从位图缓存中受益。这是通过结合使用变换矩阵和缓存的位图来实现的,被称为“缓存为位图矩阵”。

让我们通过一个示例来操作。

准备工作

已提供一个 FLA 作为起点。从本书的配套代码包中,在 Flash Professional 中打开chapter6\recipe5\recipe.fla

10 个Monkey电影剪辑被放置在背景电影剪辑的上方。所有 10 个电影剪辑都在持续旋转,并在五秒后,显示达到的平均帧率。

用于此菜谱的电影剪辑是由矢量图形构成的,并且 FLA 已设置为使用 GPU 渲染。

如何做到...

按照以下步骤操作,以查看“缓存为位图矩阵”为每个旋转电影剪辑提供的性能优势。

  1. 发布当前的 FLA 版本并将其部署到设备上。

  2. 启动应用,并在五秒后记录报告的帧率。

  3. 从您的设备中删除该应用。

  4. 返回 Flash Professional 中的recipe.fla

  5. 打开 FLA 的Main.as文档类,并在构造函数中添加以下代码行:

    var matrix:Matrix = new Matrix();
    for(var i:uint = 0; i < 10; i++)
    {
    var monkey:MovieClip = new Monkey(); 
    monkey.x = Math.random() * stage.stageWidth;
    monkey.y = Math.random() * stage.stageHeight;
    monkey.rotation = Math.random() * 360;
    monkey.cacheAsBitmap = true;
    monkey.cacheAsBitmapMatrix = matrix; 
    monkeys.push(monkey);
    addChild(monkey);
    }
    
    
  6. 最后,添加对Matrix类的导入语句:

    import flash.geom.Matrix;
    
    
  7. 保存文档类。

  8. 发布并部署到您的设备。

  9. 将渲染的帧数与应用的上一版本进行比较。应该有所改进。

它是如何工作的...

“缓存为位图矩阵”可以防止在应用任何二维变换时,显示对象的缓存的位图变得无效。同样,对于可见性或 alpha 透明度的更改也是如此。因此,对于这些更改中的任何一种,缓存的位图都不会被重新生成;更改将直接应用于缓存的位图的内部像素缓冲区,这有利于显示对象不需要重新光栅化。

与“缓存为位图”不同,“缓存为位图矩阵”不能从 Flash 的属性面板中设置。相反,请使用 ActionScript 来设置由DisplayObject类提供的cacheAsBitmapMatrix属性。

通过传递一个Matrix对象来设置cacheAsBitmapMatrix属性,并用于生成缓存的位图。对于本食谱,我们传递了单位矩阵,这强制显示对象以不改变外观的方式被光栅化。

注意

在数学中,矩阵是一个数字的矩形数组,可以用于将变换应用于 2D 或 3D 空间中的点。矩阵可以用于将各种图形变换应用于 Flash 显示对象,例如平移、旋转、缩放和扭曲。单位矩阵是一个特殊的矩阵,它不会改变其应用到的任何点的外观。

flash.geom.Matrix类由 Flash API 提供,这使得创建可用于在显示对象上执行变换的矩阵变得容易。当实例化Matrix对象时,如果您没有向构造函数提供任何参数,将创建一个单位矩阵。

cacheAsBitmapMatrix属性不能单独使用,必须始终与cacheAsBitmap属性一起设置。您可以在以下代码片段中看到这一点,该片段取自本食谱的示例代码:

monkey.cacheAsBitmap = true;
monkey.cacheAsBitmapMatrix = matrix;

如果您已经在显示对象上应用了“缓存为位图”,那么再应用“缓存为位图矩阵”也不会有任何惩罚。实际上,这是推荐的做法,因为它可以防止在除了对象的xy属性之外进行更改时出现性能惩罚。

以下表格通过突出显示不会使缓存的位图无效的更改,显示了使用“缓存为位图矩阵”的好处。

平移 缩放 旋转 扭曲 透明度 可见性
cacheAsBitmap 如何工作...
cacheAsBitmapcacheAsBitmapMatrix 如何工作... 如何工作... 如何工作... 如何工作... 如何工作... 如何工作...

当缩放或旋转一个已经被缓存的矢量显示对象时,由于变换将应用于缓存的位图而不是原始矢量艺术品,因此可能会出现保真度损失。因此,最终呈现的效果将显示出与缩放或旋转位图图像相关的伪影。

设置 cacheAsBitmapMatrix 属性即使在显示对象在屏幕外或其 visible 属性设置为 false 时也会生成缓存的位图。

如果您对矩阵感兴趣,请在 Adobe Community Help 中搜索 flash.geom.Matrix。为了更好地理解矩阵数学,请参考维基百科:en.wikipedia.org/wiki/Matrix_(mathematics)

更多内容...

现在,让我们更详细地探讨缓存为位图矩阵。

选择矩阵变换

您将 cacheAsBitmapMatrix 属性设置为的矩阵变换将用于生成缓存的位图。

例如,您可以选择使用缩放矩阵来创建一个缓存的向量电影剪辑版本,其实际大小是原始电影剪辑的两倍。尽管缓存的位图将消耗更多内存,但它允许电影剪辑在缩放到最大两倍大小时保持其保真度。或者,您也可以缓存一个大小为原始大小一半的版本,以减少内存开销,但会牺牲保真度。

重要的一点是,创建与实际显示对象大小不同的缓存的位图不会改变屏幕上对象的大小。换句话说,如果您的显示对象大小为 100x100 像素,其缓存的位图大小为 50x50 像素,对象在屏幕上仍然保持 100x100 像素的大小。AIR 会将 50x50 的缓存位图实际加倍其尺寸,以确保以正确的尺寸显示。

以下代码示例展示了如何创建一个大小为实际显示对象一半的缓存的位图:

var matrix:Matrix = new Matrix();
matrix.scale(0.5, 0.5);
displayObject.cacheAsBitmap = true;
displayObject.cacheAsBitmapMatrix = matrix;

然而,通常情况下,单位矩阵就足够了:

displayObject.cacheAsBitmap = true;
displayObject.cacheAsBitmapMatrix = new Matrix();

修改矩阵对象

一个常见的陷阱是尝试通过改变 cacheAsBitmapMatrix 变换来对显示对象应用二维变换。对这个矩阵的更改实际上会无效化缓存,迫使生成新的位图。

要应用缩放和旋转等变换到您的显示对象,只需使用其二维变换属性,如 scaleX, scaleYrotation

对于大多数用例,cacheAsBitmapMatrix 属性应为一个显示对象设置一次,然后保持不变。

重复使用矩阵对象

如果您要将相同的变换矩阵应用到一系列显示对象上,则创建一个 Matrix 对象的单例并重复使用它。每次都重新创建 Matrix 对象是一个常见的错误:

for(var i:uint = 0; i < 100; i++)
{
displayObjects[i].cacheAsBitmap = true; 
displayObjects[i].cacheAsBitmapMatrix = new Matrix(); 
}

此代码将编译并运行,但会创建 100 个单位矩阵的副本。这将无谓地消耗内存,并由于内存分配和最终垃圾回收的数量而降低性能。

相反,在循环外部创建矩阵,并如以下代码片段所示重复使用它:

var matrix:Matrix = new Matrix(); 
for(var i:uint = 0; i < 100; i++)
{
displayObjects[i].cacheAsBitmap = true;
displayObjects[i].cacheAsBitmapMatrix = matrix; 
}

3D 属性

当一个显示对象应用了 3D 属性时,该对象会自动被缓存,并且你无法控制用于生成缓存位图的变换矩阵。cacheAsBitmapMatrix 属性只能用于没有设置任何 3D 属性的显示对象。如果你在一个应用了位图缓存的显示对象上设置了 3D 属性,例如 zrotationX,那么你的缓存位图将被禁用,并将生成一个新的位图。

使用 3D 属性提供了手动设置 cacheAsBitmapMatrix 属性的大部分好处。唯一的例外是,将 3D 对象的 visible 属性设置为 false 将使其缓存的位图无效。

使用 GPU 混合

当使用 AIR 2.0 的 GPU-Blend 渲染模式时,一些最大的性能提升再次出现。

如果你一直在使用 Flash Professional CS5 并在较旧的 iOS 设备上开发,那么 第五章 中 旋转对象缩放对象 菜谱的示例可能表现不佳。设置 cacheAsBitmapcacheAsBitmapMatrix 属性将确保每个示例中使用的电影剪辑被存储并直接在 GPU 上变换。

如果性能是个问题,那么重新查看这些菜谱,并在每个 FLA 文档类的构造函数中添加以下两行代码:

bubble.cacheAsBitmap = true;
bubble.cacheAsBitmapMatrix = new Matrix();

此外,记得导入 Matrix 类:

import flash.geom.Matrix;

值得注意的是,当使用 GPU 混合时,受益于 Cache as Bitmap Matrix 的不仅仅是矢量图形。Cache as Bitmap Matrix 也会加速应用了二维变换的位图的渲染。然而,对于 GPU 矢量来说,Cache as Bitmap Matrix 实际上会损害性能,当使用位图时。

参见

  • 旋转对象,第五章

  • 缩放对象,第五章

使用 ActionScript 访问位图

iOS 设备上找到的 GPU 优化于渲染位图,而不是使用 Flash 可以生成的复杂矢量形状。这使得位图在构建高性能应用程序时成为首选的图形选项。虽然位图可以存储在库中,并在开发期间简单地拖放到时间轴上,但它们也可以使用 ActionScript 在运行时直接操作。

这个菜谱将展示如何在运行时向显示列表添加位图。

准备工作

从本书的配套代码包中,打开 chapter6\recipe6\recipe.fla 到 Flash Professional。

在库中有一个名为 monkey.png 的位图。我们将编写代码将这个位图添加到显示列表中。

如何操作...

我们将把这个菜谱分成两部分。首先,我们将导出位图以供 ActionScript 使用,然后再实际编写一些 ActionScript 代码在运行时显示它。

导出位图

让我们先导出位图数据以供 ActionScript 使用。

  1. 在库中,右键单击monkey.png,然后从上下文菜单中选择属性

  2. 位图属性对话框中,将压缩字段设置为无损(PNG/GIF)。如果您使用的是 Flash Professional CS5.5,请确保首先选中选项选项卡。

  3. 现在勾选导出为 ActionScript复选框,并将字段中的文本更改为MonkeyBitmapData。如果您使用的是 Flash Professional CS5.5,则应从面板的ActionScript选项卡中执行此操作。

    将会弹出一个包含以下文本的警告面板:

    在类路径中找不到此类的定义,因此将在导出时在 SWF 文件中自动生成。

    这是预期的行为。点击确定

  4. 保存 FLA 文件。

使用 ActionScript 显示位图

现在位图的数据对 ActionScript 可访问后,让我们继续编写一些代码来显示它。

  1. 创建一个文档类,并将其命名为Main

  2. 添加以下导入语句:

    import flash.display.Bitmap; 
    import flash.display.MovieClip;
    
    
  3. 在构造函数中添加一行 ActionScript 来创建库中位图数据的实例:

    public function Main() {
    var bitmapData:MonkeyBitmapData = new MonkeyBitmapData();
    ,
    }
    
    
  4. 现在,创建一个使用位图数据的Bitmap对象:

    public function Main() {
    var bitmapData:MonkeyBitmapData = new MonkeyBitmapData();
    var bitmap:Bitmap = new Bitmap(bitmapData); 
    }
    
    
  5. 最后,定位位图并将其添加到显示列表:

    public function Main() {
    var bitmapData:MonkeyBitmapData = new MonkeyBitmapData();
    var bitmap:Bitmap = new Bitmap(bitmapData);
     bitmap.x = 23;
    bitmap.y = 57;
    addChild(bitmap); 
    }
    
    
  6. 将类保存为Main.as

  7. 保存您的 FLA 文件并使用 ADL 进行测试。库中存储的位图图像将在屏幕上显示。

  8. 发布 FLA 并将其部署到您的设备。

它是如何工作的...

为了在库中访问图像,您需要明确导出图像的位图数据以供 ActionScript 使用。我们通过从位图属性对话框中将位图分配一个唯一的类名MonkeyBitmapData来实现这一点。使用这个类名,就可以使用 ActionScript 创建该位图数据的实例。

一旦获取了位图数据,我们只需创建一个Bitmap显示对象,并将其传递位图数据的引用。然后,显示它就变成了在将其添加到显示列表之前简单地设置位图的xy属性。

应该注意的是,您链接到位图的类将在发布 SWF 时自动生成——您不需要编写代码,因为这是为您完成的。生成时,它将继承自flash.display.BitmapData,这使得您可以将其任何实例视为BitmapData对象。

您为 ActionScript 导出的每个位图都将直接包含在您的应用程序的二进制文件中,这将增加其初始加载时间和内存占用。请注意,一旦您完成这些位图,就无法从内存中释放它们——例如,支持标准图形和 Retina 图形的应用程序可能会很容易地通过此技术耗尽内存。然而,由于位图数据直接存储在应用程序的二进制文件中,访问这些数据将会很快。

有关位图的更多信息,请在 Adobe Community Help 中搜索 flash.display.Bitmapflash.display.BitmapData

更多内容...

使用位图可以获得性能提升。以下信息将帮助您在直接使用位图时充分利用 GPU 加速。

管理图像大小

如果您使用 GPU 渲染并处理位图图像,那么您可以执行一些优化以最大化性能。

GPU 使用 2 的幂次为每个位图的维度分配内存。例如,一个 31x15 的位图将分配与 32x16 位图相同的内存量,而一个 33x17 的位图将消耗与 64x32 位图相同的内存量。每个位图的大小也会影响渲染性能,因为内存复制对于较大的位图来说会更耗时。

使用接近 2 的幂次的位图尺寸,但不要更大。尺寸不必是 2 的精确幂次,因为 Flash 会为您填充位图。

大小限制

GPU 施加了一个大小限制。实际大小取决于您使用的 iOS 硬件。对于旧设备,您的显示对象的大小不能超过 1024x1024 像素。较新的设备允许显示对象的最大大小为 2048x2048 像素。以下表格总结了这一点:

iPhone iPod touch iPad
原版和 3G 3GS 和 4/4S 第 1 代和第 2 代 第 3 代和第 4 代 第 1 代和第 2 代
1024x1024 大小限制 大小限制
2048x2048 大小限制 大小限制 大小限制

如果您需要处理一个比 GPU 允许的大小更大的显示对象,那么考虑使用 Cache as Bitmap Matrix 来缓存其较小的表示形式。

在 GPU 上存储位图数据

当使用 GPU 渲染时,您为 ActionScript 导出的任何 BitmapData 都将在实例化时直接存储在 GPU 内存中作为纹理。这适用于 Flash Professional CS5 的 GPU-Blend 模式和 CS5.5 的 GPU-Vector 模式,为两者提供最快的渲染路径。

没有必要显式设置 Bitmap 对象的 cacheAsBitmapcacheAsBitmapMatrix 属性,因为它使用的位图数据已经进行了 GPU 加速。实际上,这样做只会创建一个已经在 GPU 上的数据的副本,这将浪费内存。

当应用位图缓存的显示对象成为纹理时,BitmapData 对象 GPU 上的纹理。这种区别很重要,并且在管理内存时有影响。当与多个 Bitmap 实例一起工作时,每个位图都可以指向完全相同的 BitmapData 对象,这意味着 GPU 上只需要一个纹理,并由所有实例共享。然而,将位图缓存应用于同一显示对象的多个实例时,将为每个实例上传一个单独的纹理,消耗更多内存。

参见

  • 将类链接到电影剪辑符号,第三章

  • 使用缓存作为位图矩阵

  • 在运行时加载位图

在运行时加载位图

通过按需加载图形资源,这是一种常见的做法,可以最小化应用程序的前端加载时间和内存占用。当使用位图时,可以将它们存储在应用程序的二进制文件之外,并使用 ActionScript 在需要时在运行时加载它们。

让我们看看这是如何操作的。

准备工作

已提供一个 FLA 文件作为起点。

从本书的配套代码包中,将 chapter6\recipe7\recipe.fla 打开到 Flash Professional 中。其 AIR for iOS 设置已应用,并在舞台底部添加了一个动态文本字段。

此外,chapter6\recipe7\monkey.png 已经提供,这是我们将在运行时加载的位图。

如何操作...

此配方分为两部分。首先,我们将位图与应用程序捆绑在一起,然后我们将编写一些 ActionScript 来加载它。

捆绑位图

执行以下步骤以将位图与应用程序捆绑在一起。

  1. 打开 AIR for iOS 设置 面板并确保已选择面板的 常规 选项卡。

  2. 在面板底部是 包含的文件 列表。点击列表上方的 + 符号,然后从 FLA 的根文件夹中选择 monkey.png。点击 打开 选择文件。现在你应该在 包含的文件 列表中看到 monkey.png

  3. 点击 OK 关闭 AIR for iOS 设置 面板。

在运行时加载位图

现在,让我们编写加载位图并显示它的 ActionScript。

  1. 创建一个文档类并命名为 Main

  2. 添加以下导入语句:

    import flash.display.MovieClip;
     import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.net.URLRequest; 
    
    
  3. 在构造函数中,创建 Loader 类的实例;监听位图加载时发出的 Event.COMPLETE 事件;并开始加载:

    public function Main() {
    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE,
    bitmapLoaded);
    loader.load(new URLRequest("monkey.png")); 
    }
    
    
  4. 最后,添加一个处理 Event.COMPLETE 的事件处理器。

    private function bitmapLoaded(e:Event):void {
    var b:Bitmap = e.target.content as Bitmap;
    b.x = 23;
    b.y = 57;
    addChild(b);
    msgField.text = "loaded";
    }
    
    
  5. bitmapLoaded() 事件处理器会将加载的位图添加到舞台。位图从事件处理器的参数中获取,然后定位并添加到显示列表中。

  6. 保存类;当提示时,将文件命名为 Main.as

  7. 保存 FLA 并使用 ADL 测试以确保没有编译器错误。位图应该加载并定位在屏幕上。此外,文本字段应填充单词 loaded,表示成功。

  8. 最后,发布您的应用程序以供 iOS 使用并将它部署到设备上。

它是如何工作的...

您可以通过将文件添加到 AIR for iOS 设置面板的包含文件列表中来将资源打包到应用程序中。您可以单独添加文件或包含文件夹的内容。对于此配方,我们仅选择了monkey.png文件,确保它将与 IPA 打包在一起。

由于打包的资源不是其二进制的一部分,因此这不会影响您的应用程序的启动时间。相反,在安装过程中,它们将被复制到与应用程序相同的目录中,允许应用程序在运行时从设备的文件系统中加载它们。

实际加载位图时,使用了Loader类的实例并调用了其load()方法。加载操作是异步的——从设备的文件系统中加载可能需要时间——这意味着在尝试访问位图之前,我们必须监听Event.COMPLETE事件。

由于monkey.png与应用程序本身打包在同一文件夹中,因此传递给load()的是相对文件路径,而不是绝对路径:

loader.load(new URLRequest("monkey.png"));

一旦位图加载完成,COMPLETE事件的处理程序就会被调用,位图就会显示在屏幕上。

要实际获取位图,只需从Event对象中提取加载的内容并将其转换为Bitmap。以下代码行执行此操作:

var b:Bitmap = e.target.content as Bitmap;

然后,您可以自由地操作位图并将其添加到显示列表中。

在运行时加载位图而不是直接将其包含在 FLA 库中,可以减小应用程序二进制文件的整体大小,从而提高启动时间。此外,与直接嵌入到应用程序二进制文件中的资源相比,您将能够通过在完成使用后释放这些位图来管理应用程序的内存使用。虽然直接包含在应用程序中的位图将立即可用,但您实际上需要等待从文件系统中加载的位图。

Loader类异步加载内容。这很方便,因为它可以防止在资源加载时阻塞应用程序的执行。

您可以从 Adobe 社区帮助中获取有关此配方中使用的类的更多详细信息。具体来说,请查看flash.display.Loader, flash.display.Bitmapflash.display.BitmapData

更多内容...

在继续之前,让我们再讨论一些与位图数据相关的问题。

处理加载错误

在加载位图时,您还应该监听IOErrorEvent.IO_ERROR,当加载操作失败时将触发此事件。这通常发生在文件路径不正确或您尝试加载的资源缺失时。

访问位图的数据

您可以通过Bitmap.bitmapData属性轻松访问位图的数据。以下代码片段说明了这一点:

private function bitmapLoaded(e:Event):void {
var b:Bitmap = e.target.content as Bitmap;
var bd:BitmapData = b.bitmapData; 
}

您还可以将bitmapData属性指向不同的BitmapData对象,从而改变位图的外观。这对于通过编程创建动画非常有用,并且可以用于充分利用 GPU 上的硬件加速。

处理位图数据

虽然你通常依赖垃圾回收器来释放内存,但你可以在运行时强制 AIR 立即释放 BitmapData 对象占用的位图数据内存。这是通过调用 BitmapData.dispose() 来实现的,如下面的代码片段所示:

private function bitmapLoaded(e:Event):void {
var b:Bitmap = e.target.content as Bitmap;
var bd:BitmapData = b.bitmapData;
bd.dispose(); 
}

BitmapData 对象本身并没有被释放,只是它的位图数据。实际的 BitmapData 对象所占用的内存最终会被垃圾回收器释放。

当你不再需要位图时,请记住释放其数据。这将释放内存,允许你加载其他无法加载和存储的位图。然而,在释放位图数据内存时,你应该小心。内存管理可能会消耗宝贵的 CPU 周期,并阻碍应用程序的性能。你应该在应用程序性能不是关键的时候,尝试在方便的机会释放内存。

相关内容

  • 处理外部 SWF 文件,第四章

  • 使用 ActionScript 访问位图

  • 处理精灵图集

处理精灵图集

当处理多个位图资源时,你可能想要考虑使用精灵图集。精灵图集是一个包含多个单独图像的单个位图。通常,图集被分割成一个网格,每个图像占据相同大小的槽位。

一旦精灵图集被加载到内存中,其单个图像的位图数据可以被提取并单独存储。这允许应用程序快速访问每个图像的数据。

让我们看看这是如何完成的。

准备工作

从本书的配套代码包中打开 chapter6\recipe8\recipe.fla。FLA 的大多数 AIR for iOS 设置都已应用为起点。

此外,在同一文件夹中提供了名为 sprite-sheet.png 的位图。使用 Adobe Photoshop 等图像编辑器查看位图。它包含我们将从中提取并存储在内存中的图像集合。

如何操作...

首先,将位图捆绑到你的应用程序中。

  1. 要完成此操作,请打开AIR for iOS 设置面板,并确保已选择面板的常规选项卡。在包含文件列表上方单击+符号,并从 FLA 的根文件夹中选择sprite-sheet.png。最后,单击确定以关闭AIR for iOS 设置面板。

    现在,让我们编写一些 ActionScript 代码来在切割成单个位图之前加载精灵图集。

  2. 创建一个文档类并命名为 Main

  3. 添加以下导入语句:

    import flash.display.Bitmap;
     import flash.display.BitmapData;
    import flash.display.Loader; 
    import flash.display.MovieClip;
     import flash.events.Event;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.net.URLRequest; 
    
    
  4. 精灵图集包含四个图像,它们在 2x2 网格中排列。每个图像的大小为 192x256 像素。通过在类中添加以下常量来存储这些信息:

    public class Main extends MovieClip {
     static private const GRID_W:uint = 2;
    static private const GRID_H:uint = 2;
    static private const FRAME_W:uint = 192;
    static private const FRAME_H:uint = 256; 
    
    
  5. 添加一个类型为 Array 的成员变量,用于存储从精灵图集中提取后的每个图像的位图数据:

    private var bitmaps:Array = [];
    
    
  6. 让我们再添加一个类型为Bitmap的成员变量,它将用于验证位图是否已提取,通过在屏幕上显示其中一个位图来实现:

    private var monkey:Bitmap = new Bitmap();
    
    
  7. 在构造函数中,使用Loader类来加载精灵图集:

    public function Main() {
     var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, bitmapLoaded);
    loader.load(new URLRequest("sprite-sheet.png"));
    }
    
    
  8. 编写当精灵图集加载时将被调用的处理程序。处理程序本身将调用两个方法—sliceSpriteSheet()createMonkey()。第一个将提取精灵图集中的位图数据,而第二个将创建并显示一个使用提取图像之一位图数据的位图对象:

    private function bitmapLoaded(e:Event):void {
    sliceSpriteSheet(e.target.content.bitmapData);
    createMonkey();
    }
    
    
  9. 现在,添加一个方法,用于实际提取精灵图集每个图像的位图数据:

    private function sliceSpriteSheet(sheet:BitmapData):void {
    for(var y:uint = 0; y < GRID_H; y++)
    {
    for(var x:uint = 0; x < GRID_W; x++)
    {
    var bd:BitmapData = new BitmapData(
    FRAME_W, FRAME_H, true);
    var srcRect:Rectangle = new Rectangle(
    (x * FRAME_W), (y * FRAME_H), FRAME_W, FRAME_H);
    bd.copyPixels(sheet, srcRect, new Point(0,0));
    bitmaps.push(bd);
    }
    }
    sheet.dispose();
    }
    
    
  10. 最后,添加一个创建使用从精灵图集中裁剪的第一个图像的位图数据的方法:

    private function createMonkey():void {
    monkey = new Bitmap(bitmaps[0]);
    monkey.x = 64;
    monkey.y = 112;
    addChild(monkey);
    }
    
    
  11. 将你的文档类保存为Main.as

  12. 将你的 FLA 保存并使用 ADL 进行测试。

    SWF 将加载精灵图集,提取所有四个图像的数据,然后在屏幕上显示这些图像中的第一个。

  13. 一旦满意,发布 iOS 版本并将应用部署到设备上进行测试。

它是如何工作的...

这道菜谱的大部分工作是在sliceSpriteSheet()方法中完成的。使用嵌套的for循环,它遍历图集的位图数据,将每个图像的数据复制到它们自己的BitmapData对象中。这些BitmapData对象中的每一个都被添加到bitmaps数组中以便以后使用。

一旦数据被提取,精灵图集自己的位图数据将从内存中释放。由于每个图像的位图数据现在都存储在bitmaps数组中,并且可以轻松访问,因此不再需要精灵图集本身。

bitmaps数组想象成一个库,每个索引位置代表一个不同的图像。如果你正在使用 GPU 渲染模式,那么每个图像的数据将作为纹理存储在视频内存中,从而在渲染时提供硬件加速。

使用这些图像就像创建一个Bitmap对象并将它的bitmapData属性指向bitmaps数组中存储的BitmapData对象之一一样简单。或者,你也可以将BitmapData引用之一传递给Bitmap对象的构造函数。在createMonkey()方法中,我们只是创建了一个使用bitmaps数组中存储的第一个图像(索引位置0)的Bitmap对象。尽管,我们同样可以使用其他三个图像中的任何一个的位图数据。

与精灵图集一样,你可以对存储在bitmaps数组中的任何BitmapData对象调用dispose()方法,以将其从内存中释放。当任何BitmapData对象不再需要时,执行此操作非常重要。

精灵图集有许多优点。当处理在运行时加载的多个位图图像时,精灵图集只需要一个加载请求。这比从文件系统中加载单个位图要快得多。此外,除了为每个位图使用相同大小的槽位外,还可以将任意大小的位图紧密打包到精灵图集中。这样做可以在内存中保存精灵图集时节省空间,与存储每个单独的位图相比。

在许多开发环境和框架中,精灵图集的使用是处理位图的既定标准。例如,原生 iOS 和 Android 框架如 Cocos2D、Sparrow 和 Corona 都利用了精灵图集。建立在 Stage 3D 之上的 Starling 和 ND2D ActionScript 3.0 框架,在使用其硬件加速的 2D 图形 API 时,也依赖于精灵图集。

最后,不要将精灵图集与 Flash 的Sprite类混淆。Flash 中支持位图的任何显示对象都可以用来渲染来自精灵图集的内容,而不仅仅是Sprite类。

您可以从 Adobe 社区帮助中获取有关此配方中使用的类的更多详细信息。具体来说,请查看flash.display.Loader, flash.display.Bitmapflash.display.BitmapData。花些时间看看BitmapData.copyPixels(),它用于将精灵图集中的数据复制到每个单独的BitmapData对象中。

更多内容...

在使用精灵图集时,以下是一些需要考虑的额外事项。

创建精灵图集

有许多优秀的工具可以创建精灵图集。看看 TexturePacker,它可以在 Mac OS X 和 Microsoft Windows 上免费使用,网址为www.texturepacker.com

比较性能和内存消耗

提取和存储每个单独图像的位图数据,可以在最终需要时提供最快的访问速度。然而,将精灵图集切割成单独的BitmapData对象可能会以内存为代价,尤其是在直接在 GPU 上渲染时。

GPU 为每个位图的每个维度使用 2 的幂来分配内存。在创建精灵图集时,您可以使用这一知识来提高效率,将图像打包并排列到图集中,直到其尺寸是 2 的精确幂。然而,对于图集中的单个图像来说,情况可能并非如此,一旦所有图像的位图数据都被提取出来,可能会导致显著的内存开销。

在创建位图图像时,仔细考虑你的艺术作品。如果性能至关重要,那么你可能需要接受这些内存开销。否则,考虑一种替代方法——也许是将精灵表保持在内存中,并在特定时刻提取所需的数据。当然,这会比预先提取所有图像数据慢,但这是一个可行的选项,通常被专业开发者所采用。

参见

  • 处理外部 SWF,第四章

  • 使用 ActionScript 访问位图

  • 在运行时加载位图

  • 使用 ActionScript 进行位图动画

使用 ActionScript 进行位图动画

对于大多数情况来说,这可能是显而易见的选择,但时间轴并不是执行帧帧动画的唯一方法。在内存中存储一系列 BitmapData 对象的情况下,使用 ActionScript 应用动画到 Bitmap 对象是完全可能的。

我们将在本食谱中看到如何做到这一点。

准备工作

你可以继续使用你在 使用精灵表 食谱中编写的代码。或者,从书籍的配套代码包中打开 chapter6\recipe9\recipe.fla 并从那里开始工作。你还可以在同一个文件夹中找到 FLA 的文档类和精灵表。精灵表已经添加到 FLA 的 包含文件 列表中,在 AIR for iOS 设置 面板中。

如何做到这一点...

我们将通过循环遍历从精灵表中切割出的每个位图来执行动画。

  1. 打开 FLA 的文档类。

  2. 添加一个存储动画中帧数的常量:

    static private const MAX_FRAMES:uint = GRID_W * GRID_H;
    
    
  3. 我们还需要一个成员变量来跟踪当前显示的帧:

    private var frame:uint = 0;
    
    
  4. bitmapLoaded() 方法中,监听 Event.ENTER_FRAME 事件。其事件处理程序将充当应用程序的主循环:

    private function bitmapLoaded(e:Event):void {
    sliceSpriteSheet(e.target.content.bitmapData);
    createMonkey();
    addEventListener(Event.ENTER_FRAME, update);
    }
    
    
  5. 现在,让我们添加主循环的方法。在每次调用时,它将 monkey 位图指向不同的 BitmapData 对象,从而本质上使位图动画化:

    private function update(e:Event):void {
    monkey.bitmapData = bitmaps[frame];
    if(++frame == MAX_FRAMES)
    {
    frame = 0;
    }
    }
    
    
  6. 保存你的文档类和 FLA 文件。

  7. 在 ADL 中测试 FLA。你现在应该看到 monkey 位图通过一系列图像进行动画循环。

  8. 发布你的应用程序并在设备上测试它。

它是如何工作的...

一旦你有一系列 BitmapData 对象,使用它们进行动画并不需要太多的努力。

frame 成员变量被用作 bitmaps 数组的索引位置,以检索用于动画的下一个 BitmapData 对象。你可以在以下代码片段中看到这一点,其中 bitmapData 属性被更新为指向一个新的 BitmapData 对象:

monkey.bitmapData = bitmaps[frame];

还添加了一些额外的逻辑来确保动画循环回到第一帧。这是通过比较 frame 的值与 MAX_FRAMES 常量的值来实现的,当这两个值匹配时,将 frame 设置回 0

对于一个相对快速完成的任务来说,这似乎是一项相当多的工作。然而,即使是简单的基于时间轴的动画,在较旧的 iOS 设备上也会在性能上遇到困难。这尤其在使用 GPU 混合时更为明显,每当播放头的位置改变时,每一帧都需要从 CPU 复制到 GPU。

使用 ActionScript 进行程序化动画可以非常快,特别是 GPU 混合从中受益。记住,BitmapData对象直接存储在视频内存中作为纹理,因此不会像时间轴动画那样遇到相同的渲染瓶颈。

如果您使用 Flash Professional CS5,那么如果您想最大限度地提高动画的性能,这可能确实是唯一的选择。利用 GPU 混合模式并使用 ActionScript 执行位图动画可以将性能提高五到十倍。为了比较,从比较矢量图形和位图图形配方发布recipe-bitmaps.fla。当在设备上运行时,它与这个配方示例 FLA 之间的性能差异应该是相当大的。

还有更多...

下面是一些关于精灵表和动画的最终要点。

动画序列

您可能会发现现有的动画运行得太快,并倾向于降低 FLA 的帧率来纠正这个问题。更好的方法是,在移动到下一个之前,让每个位图保持几帧。这提供了对动画的更多控制,而不会降低 SWF 的帧率。

我们可以通过创建一个包含动画帧索引序列的数组来实现这一点。数组中的每个元素代表一个动画帧。因此,我们可以通过存储每个帧索引的重复副本来减慢动画。看看以下序列:

[ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 ]

每个整数代表一个帧索引,其中 0 是动画的第一个位图,3 是最后一个。因此,这个序列在移动到下一个之前,在每一个位图上保持动画,进行四次屏幕重绘。让我们在您的代码中实现这一点。

首先,添加一个包含动画序列的常量:

static private const SEQUENCE:Array = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3];

最后,用这个新版本替换update()方法,它循环遍历序列中列出的帧索引:

private function update(e:Event):void {
monkey.bitmapData = bitmaps[SEQUENCE[frame]];
if(++frame == SEQUENCE.length)
{
frame = 0;
}
}

保存您的文档类并测试您 FLA 的新版本。

虽然这个例子使用基于帧的方法进行动画,但实际上没有任何阻止您编写自己的基于时间的 ActionScript 动画库。

运行时加载资源

使用基于位图动画的 ActionScript 的另一个原因是运行时加载资源。如果您无法一次性将所有资源放入内存,或者只想减少应用程序的初始加载时间,那么您应该考虑这一点,而不是基于时间轴的动画。

记住,目前无法在您加载到 iOS AIR 应用程序中的外部 SWF 中实例化任何库符号。因此,作为替代方案,您可能希望在运行时加载精灵表单,从中提取图像,然后使用 ActionScript 执行应用程序显示对象所需的动画。

Stage 3D

使用精灵表单的最有说服力的理由可能是 Adobe 的 Stage 3D API。Stage 3D(之前代号为 Molehill)在 GPU 硬件上提供了高级的 2D 和 3D 硬件加速。它的 API 故意设计为低级,以最大化性能,但您可以使用建立在 Stage 3D 之上的各种 ActionScript 3.0 框架,这些框架仍然能够产生远超 Flash 传统显示列表的效果。

针对 2D 图形的两个这样的 API 是 Starling 和 ND2D,它们大量使用精灵表单。Flash 的传统显示列表不能与这些框架一起使用。相反,所有操作都必须通过 ActionScript 和每个框架提供的图形元素进行编程实现。

在撰写本文时,Stage 3D 尚未对移动设备可用。然而,Adobe 正在积极工作,将其引入到 iOS 的 AIR 中。如果您想在 Stage 3D 可用时利用它,那么您应该考虑在当前项目中使用精灵表单。这应该会使将它们移植到 Stage 3D 的过程相对简单。

您可以在 Adobe 开发者连接处了解更多关于 3D 舞台的信息:www.adobe.com/devnet/flashplayer/stage3d.html。在那里也可以找到 Starling 和 ND2D 的链接。

参见

  • 使用更新循环,第三章

  • 处理外部 SWF,第四章

  • 处理精灵表单

第七章. 使用文本和虚拟键盘

在本章中,我们将涵盖:

  • 在文本字段中使用设备字体

  • 在文本字段中使用嵌入式字体

  • 提供文本输入

  • 捕获文本输入

  • 可配置的平移与虚拟键盘激活

  • 更新动态文本字段

  • 使用原生 iOS 文本控件

简介

由于没有物理按钮,iPhone 永远改变了我们输入文本的方式。之前的手机上的固定键盘配置已经消失;取而代之的是适应不同应用的触摸屏键盘。此外,iOS 附带了一个全面的字体库和令人印象深刻的文本渲染能力,允许用户输入以清晰的细节显示。

在本章中,您将探索 Flash 对原生 iOS 虚拟键盘的支持,并学习如何处理文本。

在文本字段中使用设备字体

iOS 设备上安装了全面的字体列表,可以直接在您的 AIR for iOS 应用中使用。

这个菜谱将指导您完成创建使用设备字体的文本字段的步骤。

准备工作

从本书的配套代码包中,在 Flash Professional 中打开chapter7\recipe1\recipe.fla。FLA 的舞台是空的,但其 AIR for iOS 设置已经应用,这为您在构建和部署到设备时节省了时间和精力。

如何做到...

执行以下步骤以利用设备字体:

  1. 使用文本工具(T)在舞台上绘制一个文本字段。如何做到...

  2. 在文本字段中输入Flash iOS Apps Cookbook

  3. 属性面板中,确保从最上面的两个下拉框中选择经典文本动态文本

  4. 将文本字段定位在(21,52)。将其宽度和高度分别设置为 278 和 240。

  5. 在属性面板中展开字符部分。将家族下拉框设置为Trebuchet MS,将大小设置为60.0 pt,并将字体颜色更改为黑色。此外,选择使用设备字体作为抗锯齿字段,并确保直接下方的可选中图标未被选中。所有这些设置都在前面的屏幕截图中显示。

  6. 最后,展开段落部分。将格式字段选择为居中对齐,并将行为字段的下拉框选择为多行

  7. 保存您的 FLA。

  8. 发布 FLA 并在您的设备上安装 IPA。

它是如何工作的...

虽然 Flash 可以直接在您的 SWF 中嵌入字体,但 iOS 提供了自己的字体,可以替代使用。这些被称为设备字体,使用它们具有许多优点:

  • 您应用的最终大小将会减小,因为不再需要 Flash 将字体符号直接包含在您的 SWF 中。

  • 这将确保字体渲染与其他使用它的 iOS 应用完全相同

  • 设备字体比 Flash 嵌入的字体在屏幕上渲染得更快

设备字体也有一些缺点,这可能会决定您是否可以在项目中使用它们:

  • 无法直接将透明度应用于您的文本

  • 如果文本字段已旋转,则嵌入的字体将无法渲染

如果您选择设备上可用的字体,请确保从抗锯齿字段中选择使用设备字体。字体还必须安装到您的开发计算机上,否则您将无法从 Flash Professional 中选择它们。

Flash 无法阻止您选择未实际安装到设备上的字体——它无法判断。如果您选择的字体不可用,则所有需要使用该字体的文本字段将默认为_ 无衬线

设备字体可以与所有三种经典文本类型一起使用:静态、动态和输入文本。

还有更多...

为您的应用程序选择正确的字体很重要。首先,您需要知道哪些字体实际上是可用的。

iOS 上的设备字体

无法从 Flash Professional 的 IDE 中判断哪些字体实际上已嵌入到您的设备中可能会带来问题。幸运的是,有几个应用程序可以列出设备上安装的字体,并允许您以各种点大小预览它们。大多数应用程序还允许您输入并预览自己的文本。

值得一看的两个应用程序是Fast FontsFonts。两者都是免费的,可以从 iTunes 或 App Store 下载。

请注意,安装的字体数量在不同设备和 iOS 版本之间有所不同。例如,在 iOS 4.3 中,iPhone 上安装了 40 种字体家族,而 iPad 则有 57 种。在使用之前,请检查您希望针对的所有设备上字体的可用性。

以下是一些常用设备字体:

  • 宋体:Times New Roman, Georgia, 和 _ 宋体

  • 无衬线:Helvetica, Arial, Verdana, Trebuchet, Tahoma, 和 _ 无衬线

  • 等宽:Courier, Courier New, 和 _ 打字机

要获取 iOS 最新版本上支持的所有字体的完整列表,请查看iOS Fonts 网站

列举可用的设备字体

可以确定设备上安装的字体。以下是一个简单的代码示例:

var f:Font;
var fonts:Array = Font.enumerateFonts(true);
for(var i:int = 0; i < fonts.length; i++)
{
f = fonts[i];
trace(f.fontName + "," + f.fontStyle + "," + f.fontType);
}

通过将true传递给静态Font.enumerateFonts()方法,您可以检索一个表示设备嵌入字体的Font实例数组。只需查询实例的fontName, fontStyle, 和 fontType属性,就可以了解更多关于该字体代表的信息。

此外,您在使用Font类之前需要导入flash.text.Font。要了解更多关于每个属性的信息,请在 Adobe Community Help 中搜索Font类。

像素密度

您的 iOS 设备的像素密度可能比典型监视器要高。在 Flash Professional 中工作时看起来合适的字体大小,在实际设备上可能太小。这尤其适用于针对 iPhone 4/4S 的 Retina 显示屏。Fast Fonts 等应用程序可以帮助您直接从您的设备中选择合适的大小。尽量不使用小于 14 磅的点大小。

TLF 文本

Flash Professional CS5 引入了一个名为文本布局框架(TLF)的新文本引擎。虽然 TLF 与之前的经典文本引擎相比提供了更优越的文本布局功能,但由于框架的性能限制较重,不建议在针对 iOS 时使用它。本书不会涉及 TLF 文本。

参见

  • 在文本字段中使用嵌入的字体

在文本字段中使用嵌入的字体

您最终可能需要使用未安装在您的设备上的字体。在这种情况下,您可以嵌入字体,使其在您的应用中正确渲染。

让我们看看如何做到这一点。

准备工作

启动 Flash Professional,并从书籍配套代码包中打开chapter7\recipe2\recipe.fla。FLA 的舞台是空的,但其 AIR for iOS 设置已经应用,一旦您准备好,您可以轻松发布。

如何做到这一点...

iOS 设备上未安装 Impact 字体。让我们创建一个文本字段,通过直接在您的应用中嵌入字体来使用它。

  1. 选择文本工具(T)并在舞台上绘制一个文本字段。

  2. 在文本字段中输入Flash iOS Apps Cookbook

  3. 属性面板中,从最上面的两个下拉框中选择经典文本动态文本

  4. 将文本字段定位在(21,52)。将其宽度和高度分别设置为 278 和 240。

  5. 在属性面板中展开字符部分。将家族字段设置为Impact,将大小设置为60.0 pt,并将字体颜色更改为黑色。同时,确保未选中可选取图标。

  6. 字符部分中保持,将抗锯齿字段设置为可读性抗锯齿。可能会出现一个字体嵌入警告对话框,指出您需要选择要嵌入的字体和字符。如果是这样,请点击其嵌入按钮打开字体嵌入面板。如果不是,请简单地点击样式字段旁边的嵌入按钮打开面板,如图所示:如何做到这一点...

  7. 字体嵌入面板中,在字符范围列表中检查大写[A..Z]小写[a..z]复选框。点击确定按钮关闭面板。

  8. 现在在属性面板中展开段落部分。将格式字段选择为居中对齐,并将行为字段的下拉框选择为多行

  9. 保存您的 FLA 文件。

  10. 发布 FLA 并在您的设备上安装 IPA。

它是如何工作的...

您计算机上安装的任何字体都可以嵌入到您的 SWF 中。这将允许字体在您的应用程序中正确渲染,即使它无法直接从您的设备获取。

您可以从字体嵌入面板管理您想要嵌入的字体,该面板通过在属性面板上单击嵌入按钮启动。从这里,您还可以设置您希望包含的特定字体的字符范围。您只选择所需的字符非常重要,因为随着您添加的字形符号数量的增加,您的应用程序文件大小会增加。此外,您还可以从该面板导出用于 ActionScript 的字体。

嵌入的字体可以与所有经典文本字段类型一起使用。然而,当使用静态文本字段时,您无法控制嵌入到您的 SWF 中的字符范围。相反,Flash 只是包括字段中出现的字符。

当使用嵌入的字体时,请确保文本字段的抗锯齿选项设置为除使用设备字体之外的内容。将其设置为使用设备字体实际上不会嵌入字体,而是假设该字体已安装在与设备一起。

只有当字体在设备上不可用且没有合适的替代设备字体可以使用时,才嵌入字体。嵌入的字体会增加应用程序的大小,并且在大多数情况下不如设备字体渲染得快。

更多内容...

您应该仔细管理嵌入的字体,并尽量保持您的应用程序文件大小尽可能小。

大小考虑

当该字体无法直接从设备获取时,嵌入字体是有用的。然而,嵌入的字体可能会影响您应用程序的最终大小。

您可以从 Flash 生成大小报告,该报告提供了您 SWF 中所有资产的分析以及它们消耗的 SWF 文件大小。此报告还将包括每个嵌入字体的尺寸信息。只需转到发布设置面板并勾选生成大小报告复选框。Flash CS5 用户应首先在发布设置面板中的Flash选项卡上单击。

当您发布 FLA 时,将生成一个大小报告,并在输出面板中显示。在报告中有一个部分,您可以查看嵌入的字体及其字符集的列表。每个字体使用的字节数也会显示出来。

以下是从该食谱的 FLA 的大小报告中获取的结果:

Font Name Bytes Characters
--------- ---------- ----------
Impact 6606 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk lmnopqrstuvwxyz

如您所见,大约需要 7 KB 来存储这个字体的字符集。

返回字体嵌入面板,通过检查字符范围列表中的第一个复选框来包含所有字体的字形。

重新发布 FLA 并查看新的大小报告。现在字体几乎消耗了 47 KB!

注意

重要的是,您只需包含所需的字体,并且将每个字体的字符集保持到绝对最小。由于对嵌入字体的管理不善,您的应用程序最终文件大小可能会迅速增加。

相关内容

  • 在文本字段中使用设备字体

提供文本输入

所有 iOS 设备都放弃了物理键盘,转而使用虚拟触摸屏等效物。AIR 提供了虚拟键盘支持,使用户能够在输入文本字段中输入文本。

让我们看看这是如何操作的。

准备工作

已提供一个 FLA 文件作为此菜谱的起点。

从书籍的配套代码包中,在 Flash Professional 中打开chapter7\recipe3\recipe.fla

阶段上已经放置了三个静态文本字段,将作为标签使用。我们将在舞台上添加三个输入文本字段,将每个标签与一个字段关联。

如何操作...

执行以下步骤以创建三个输入文本字段:

  1. 通过选择插入 | 时间轴 | 图层在时间轴上创建一个新的图层。

  2. 从工具面板中选择文本工具(T)

  3. 在新创建的图层上,绘制一个文本字段,紧邻名字文本字段,如图所示:如何操作...

  4. 属性面板中,从最上面的两个下拉框中选择经典文本输入文本

  5. 扩展属性面板的字符部分。将家族下拉框设置为Trebuchet MS,将大小设置为20.0 pt,并将文本颜色设置为黑色。此外,将抗锯齿字段设置为使用设备字体,并选择显示文本周围的边框图标。

  6. 将文本字段定位在(114,33)处,并设置其大小为 193x28。

  7. 扩展段落部分。通过选择右对齐图标设置格式,并从行为下拉框中选择单行

  8. 创建一个与第一个类似的第二个输入文本字段。将其定位在姓氏标签旁边(114,83),并将格式字段设置为居中对齐

  9. 最后,在详情标签下方直接绘制第三个输入文本字段。将其定位在(11,174)处,并设置其大小为 298x154。在段落部分中,为格式字段选择左对齐图标,并从行为下拉框中选择多行

  10. 保存您的 FLA 文件。

  11. 发布 FLA 并在您的设备上安装 IPA。

  12. 运行应用程序并输入每个字段中的文本。

它是如何工作的...

当用户触摸任何输入文本字段时,虚拟键盘将自动出现。许多原生 iOS 应用程序提供的相同功能也直接来自您的输入文本字段,包括预测文本和清除字段的按钮。在 iOS 4 或更高版本上运行的应用程序也将受益于复制和粘贴支持。

前两个字段是单行的,如果已输入文本,将在右侧提供清除按钮。然而,如果文本字段太窄,则不会显示按钮。

当您完成在单行文本字段中输入文本后,您可以通过点击完成键或点击文本字段外部的任何地方来关闭虚拟键盘。

注意

如果您使用 Flash Professional CS5 构建了您的应用,那么您会注意到,当输入文本时,字段的对齐设置被忽略。当使用 AIR 2.0 SDK 时,iOS 中的输入文本字段仅支持左对齐。因此,当与 CS5 一起工作时,建议您不要选择其他对齐方式。

当编辑多行的详细信息字段时,虚拟键盘不提供完成键。取而代之的是,在其位置上有一个回车键,允许用户跳到下一行。要关闭编辑多行输入文本字段时的虚拟键盘,用户必须点击字段外的任何地方。不幸的是,这并不是 iOS 应用的常规做法,可能会让用户感到困惑。另外,请确保包含一个用户可以点击的区域。如果字段太大,那么用户可能无法关闭键盘。

输入文本字段的位置很重要。如果您要编辑的字段位于虚拟键盘使用的区域,那么 AIR 将在运行时调整舞台的位置。您可以通过尝试编辑详细信息输入文本字段来看到这一点。舞台将被平移,以确保字段不被遮挡。然而,输入字段却被推出了视图,为详细信息腾出空间。

小贴士

在设计您的应用程序时,请考虑键盘所占用的区域以及在此区域内编辑文本字段的影响。

您还应该确保您的多行文本字段的高度不超过虚拟键盘升起后剩余的高度,因为文本字段滚动不是直接提供的。

小贴士

为了提高性能和渲染质量,请在您的输入文本字段中使用设备字体而不是嵌入的字体。

更多内容...

虚拟键盘及其许多文本编辑功能的激活是免费的。但如果你想要更多的控制呢?

键盘类型

与使用 iOS SDK 开发原生应用的开发者可以配置显示的键盘类型不同,当与输入文本字段一起工作时,AIR 目前不提供此类控制。您只能限制为两种非常相似的布局——一个用于单行输入字段,另一个用于多行。

如果虚拟键盘不符合您的要求,那么请考虑使用 AIR 3.0 提供的原生 iOS 文本控件。这样做将为您提供访问更多键盘配置的权限。有关更多详细信息,请参阅本章末尾的使用原生 iOS 文本控件配方。

以编程方式启动虚拟键盘

当用户点击输入文本字段时,虚拟键盘会自动启动。但是,有时您可能需要使用 ActionScript 代码来程序化地启动键盘。

在 AIR 2.6 及以上版本中,您可以通过将文本字段的 needsSoftKeyboard 属性设置为 true 并调用其 requestSoftKeyboard() 方法来强制虚拟键盘出现。以下是一个示例代码,通过将焦点设置到实例名为 forename 的文本字段上来启动虚拟键盘。

forename.needsSoftKeyboard = true;
var success:Boolean = forename.requestSoftKeyboard();

requestSoftKeyboard() 方法返回一个布尔值,指示虚拟键盘是否成功弹出。

如果您正在使用 Flash Professional CS5 和 AIR 2.0,则可以通过使用 Stage 类的 focus 属性来强制虚拟键盘出现。以下是一个使用实例名为 forename: 的文本字段的示例代码:

stage.focus = forename;

记住,您可以从任何 DisplayObject(包括您的文档类)中检索到舞台的引用。DisplayObject 类提供了一个 stage 属性,您可以访问它。

相关内容

  • 捕获文本输入

  • 可配置的滚动与虚拟键盘激活

  • 使用原生 iOS 文本控件

捕获文本输入

您可以获取任何非静态文本字段中存储的文本。这对于输入文本字段尤其有用,因为应用程序可能希望立即响应用户的输入或收集信息以供以后使用。

本食谱将向您展示如何捕获用户输入。

准备工作

从书籍的配套代码包中,将 chapter7\recipe4\recipe.fla 打开到 Flash Professional 中。

一个名为 submit 的输入文本字段位于舞台上。在其下方是一个名为 echo 的动态文本字段。

我们将编写一些 ActionScript 代码来捕获用户在 submit 字段中输入的任何文本,并在 echo 字段中显示它。

如何操作...

执行以下步骤:

  1. 创建一个名为 Main 的文档类。

  2. 在类中监听 submit 输入字段发出的 FocusEvent.FOCUS_OUT 事件。您还需要添加对 FocusEvent 类的导入语句:

    package {
    import flash.display.MovieClip;
    import flash.events.FocusEvent;
    public class Main extends MovieClip {
    public function Main() {
    submit.addEventListener(FocusEvent.FOCUS_OUT,
    focusLost);
    }
    }
    }
    
    
  3. 现在,添加一个处理 FOCUS_OUT 事件的处理器:

    private function focusLost(e:FocusEvent):void {
    echo.text = e.target.text;
    }
    
    
  4. 保存类,并在提示时将文件命名为 Main.as

  5. 最后保存并编译 FLA 文件。在您的设备上测试应用程序。

您在输入文本字段中输入的任何文本都会被回显到下面的动态文本字段中。这将在您点击输入字段外部时发生。

它是如何工作的...

动态字段和输入字段都提供了一个 text 属性,可以用来获取或设置它们的当前文本。然而,在我们能够获取 submit 字段的文本之前,我们需要知道用户是否已经完成输入。我们可以通过监听 FOCUS_OUT 事件来判断,该事件是由输入文本字段在用户执行以下操作时触发的:

  • 用户在文本字段边界之外的屏幕上触摸

  • 用户点击虚拟键盘的 完成

在这个食谱的代码中,focusLost()处理程序响应submit字段的FOCUS_OUT事件。它将echo字段中的文本设置为submit字段的文本。以下又是处理程序的代码:

private function focusLost(e:FocusEvent):void {
echo.text = e.target.text;
}

submit字段实际上是通过FocusEvent参数的target属性访问的。我们可以这样做,因为FOCUS_OUT事件是从submit字段发出的,使其成为事件的目标。或者,我们也可以忽略实际的FocusEvent参数,直接使用以下代码片段直接访问submit字段:

private function focusLost(e:FocusEvent):void {
echo.text = submit.text;
}

如食谱所示,在字段中检索和设置文本的机制是微不足道的。然而,在捕获用户的文本输入时,您首先需要确保用户已经完成输入。

如需更多信息,请在 Adobe 社区帮助中搜索flash.text.TextFieldflash.events.FocusEvent

更多内容...

在我们继续之前,以下是一些额外的信息。

监听焦点

除了FocusEvent.FOCUS_OUT,您还可以监听FOCUS_IN事件,这会告诉您用户何时触摸输入文本字段。如果您需要在用户开始输入文本之前执行任何准备工作,这很理想。例如,您可能想在用户开始键入之前清除字段中的当前文本。让我们继续实现这一点。

在您的文档类的构造函数中,监听FOCUS_IN事件:

submit.addEventListener(FocusEvent.FOCUS_IN, clearField);

现在添加一个事件处理程序,它简单地清除文本字段:

private function clearField(e:FocusEvent):void {
e.target.text = "";
}

保存类并测试您设备上最新版本的 app。

参见

  • 提供文本输入

配置虚拟键盘激活时的平移

当用户触摸输入文本字段时,虚拟键盘会自动出现。如果文本字段位于键盘使用的区域中,则舞台将自动平移以防止文本字段被遮挡。然而,可以关闭此默认行为并自行修改布局以响应键盘的激活。

这里涵盖的步骤仅适用于使用 Flash Professional CS5.5 和 AIR 2.6 或更高版本的用户。

准备工作

已提供一个 FLA 作为起点。

从本书的配套代码包中,将chapter7\recipe5\recipe.fla打开到 Flash Professional 中。

舞台中心是一个名为field的输入文本字段。我们将编写一些 ActionScript 来在虚拟键盘激活时重新定位此文本字段。

如何操作...

首先,您需要从应用程序描述文件中关闭自动平移。

  1. 从 Flash Professional CS5.5 中选择文件 | 打开。从文件浏览器中,选择与 FLA 相同的文件夹中的recipe-app.xml

  2. 将以下行添加到描述文件的 XML 中:

    <initialWindow>
    <content>recipe.swf</content>
    <systemChrome>standard</systemChrome>
    <transparent>false</transparent>
    <visible>true</visible>
    <fullScreen>true</fullScreen>
    <aspectRatio>portrait</aspectRatio>
    <renderMode>gpu</renderMode>
    <autoOrients>false</autoOrients>
    <softKeyboardBehavior>none</softKeyboardBehavior>
    </initialWindow>
    
    
  3. 保存文件。

  4. 现在,为您的 FLA 创建一个文档类,并将其命名为Main

  5. 添加以下导入语句:

    import flash.display.MovieClip;
    import flash.events.SoftKeyboardEvent;
    import flash.geom.Rectangle;
    
    
  6. 在构造函数中,监听虚拟键盘的激活和关闭:

    public function Main() {
    stage.addEventListener(
    SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, activate);
    stage.addEventListener(
    SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, deactivate);
    }
    
    
  7. SOFT_KEYBOARD_ACTIVATE事件添加一个处理程序。当虚拟键盘被激活时,它将被调用,并将输入文本字段定位在键盘边界之外:

    private function activate(e:SoftKeyboardEvent):void {
    var keysRect:Rectangle = stage.softKeyboardRect;
    if(field.y + field.height > keysRect.top)
    {
    offset = field.y + field.height - keysRect.top;
    field.y -= offset;
    }
    else
    {
    offset = 0;
    }
    }
    
    
  8. activate()处理程序计算文本字段需要垂直移动多少像素才能定位在键盘边界区域外。这个值存储在一个名为offset的成员变量中。在你的类中声明offset成员变量:

    public class Main extends MovieClip {
    private var offset:Number;
    public function Main() {
    
    
  9. 最后,当键盘移除时,我们需要将文本字段放回其原始位置。SOFT_KEYBOARD_DEACTIVATE事件的处理程序将使用offset成员变量来处理这个问题:

    private function deactivate(e:SoftKeyboardEvent):void {
    field.y += offset;
    }
    
    
  10. 保存该类,并在提示时将文件命名为Main.as。也要保存您的 FLA 文件。

  11. 发布应用程序并在您的设备上测试它。

当您选择输入文本字段时,虚拟键盘将会显示,并且字段将被重新定位在它上方。在字段外轻触会将它放回键盘离开屏幕后的原始位置。

它是如何工作的...

通常,如果虚拟键盘遮挡了具有焦点的输入文本字段,舞台会自动平移。然而,我们通过将应用程序描述文件中的softKeyboardBehavior元素设置为none:来禁用了这种默认行为:

<softKeyboardBehavior>none</softKeyboardBehavior>

注意

软键盘这个术语指的是软件键盘,它是 AIR 对 iOS 使用的虚拟键盘的通用术语。

关闭自动平移后,我们可以在用户轻触输入文本字段时更改应用程序的布局,并在用户完成输入后将其改回。

为了做到这一点,我们监听了以下两个从舞台发出的事件:

  • SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE

  • SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE

当虚拟键盘出现在屏幕上时,会触发SOFT_KEYBOARD_ACTIVATE事件。正是响应这个事件,我们重新定位输入文本字段。当用户在输入文本字段外轻触或按下完成键时,虚拟键盘会被关闭,并发出SOFT_KEYBOARD_DEACTIVATE事件。当我们捕获这个事件时,我们将输入文本字段放回其原始位置。

虽然为这两个事件硬编码文本字段的定位是完全可以接受的,但我们的示例代码更进一步,在键盘关闭后动态地将文本字段移出键盘占据的区域,然后再将其移回。

它首先检查输入文本字段是否在键盘的边界区域内。如果是的话,它会通过计算需要偏移多少来将文本字段定位在键盘上方。以下又是代码:

private function activate(e:SoftKeyboardEvent):void {
var keysRect:Rectangle = stage.softKeyboardRect;
if(field.y + field.height > keysRect.top)
{
offset = field.y + field.height - keysRect.top;
field.y -= offset;
}
else
{
offset = 0;
}
}

虚拟键盘的边界区域是从 Stage.softKeyboardRect 获取的,它表示被虚拟键盘覆盖的舞台区域。使用此属性时要小心,因为它在键盘不可见时将返回零的大小。此外,请注意,偏移量存储在我们的 offset 成员变量中,如果文本字段不在键盘的边界内,它将被设置为零。

最后,当虚拟键盘关闭时,我们使用 offset 成员变量的值将文本字段移回:

private function deactivate(e:SoftKeyboardEvent):void {
field.y += offset;
}

更多信息,请在 Adobe Community Help 中搜索 flash.events.SoftKeyboardEventStage.softKeyboardRect

还有更多...

你可能会对以下信息感兴趣。

相关对象

SoftKeyboardEvent 类提供了 relatedObject 属性,它包含之前有焦点的 InteractiveObject。当你监听 SoftKeyboardEvent.DEACTIVATE 时,这很有用,因为你将能够确定用户最后编辑的是哪个输入文本字段。

更新动态文本字段

渲染文本很昂贵,可能会降低应用程序的整体性能。这在第一代和第二代 iPhone 和 iPod touch 等较老设备上尤为明显,因为每个 CPU 周期都很重要。尽量减少更新的文本数量和更新频率。

让我们看看如何实现这一点。

准备工作

在书籍的配套代码包中,提供了一个 FLA 文件,位于 chapter7\recipe6\recipe.fla

你会在舞台上找到两个文本字段。第一个是静态的,包含文本 已过时间:。第二个是动态的,包含一个零,并且有一个实例名称 timerField

我们将编写一些 ActionScript 代码,以持续更新 timerField,显示自应用程序启动以来已过的秒数。

如何实现...

让我们按照以下步骤进行操作:

  1. 创建一个文档类,并将其命名为 Main

  2. 我们将需要两个成员变量。一个用于存储应用程序启动时的时间,另一个用于存储已过秒数。让我们也在类的构造函数中初始化这两个变量:

    package {
    import flash.display.MovieClip;
    public class Main extends MovieClip {
     private var startTime:Date;
    private var elapsed:uint; 
    public function Main() {
     startTime = new Date();
    elapsed = 0; 
    }
    }
    }
    
    
  3. 我们将使用循环来计算已过的秒数,并使用该值更新 timerField。该循环将在每一帧重绘时被调用。

    首先,添加一个监听器 Event.ENTER_FRAME,并添加一个对 Event 类的导入语句:

    package {
    import flash.display.MovieClip;
    import flash.events.Event;
    public class Main extends MovieClip {
    private var startTime:Date;
    private var elapsed:uint;
    public function Main() {
    startTime = new Date();
    elapsed = 0;
    addEventListener(Event.ENTER_FRAME, update);
    }
    }
    }
    
    
  4. 现在,添加将作为更新循环的事件处理程序:

    private function update(e:Event):void {
    var currTime:Date = new Date();
    var prevElapsed:uint = elapsed;
    elapsed = (currTime.getTime()-startTime.getTime()) / 1000;
    if(elapsed != prevElapsed)
    {
    timerField.text = String(elapsed);
    }
    }
    
    
  5. 保存类,并在提示时将文件命名为 Main.as。保存 FLA 文件。

  6. 编译应用程序并将其部署到您的设备上。

当你测试应用程序时,你应该看到动态文本字段持续更新为已过秒数。

工作原理...

虽然在每次ENTER_FRAME事件上都会调用update()处理程序,但我们只在实际改变时在文本字段中设置经过的时间。一个常见的错误是反复将相同的字符串写入文本字段,这是不必要的,并且会降低性能。我们通过以下if语句来防止这种情况:

if(elapsed != prevElapsed)
{
timerField.text = String(elapsed);
}

基本上,只有当经过的秒数与上一次循环调用中使用的值不同时,文本字段才会更新。对于此配方来说,这意味着文本字段每秒只更新一次,而不是每秒 24 次(FLA 的帧率)。这是一个重大的节省。

除了减少文本字段更新的频率外,我们还可以通过仅设置需要更改的字符来提高性能。此配方中的两个文本字段可以很容易地用一个字段表示。如果我们采取这种方法,那么更新字段所需的代码将看起来像这样:

timerField.text = "Elapsed Time: " + elapsed;

当然,这是浪费的,因为经过时间字符串会每次都写入文本字段。仅在其自己的单独文本字段中显示和更新时间有助于进一步提高此配方应用的性能。

虽然这些建议可能看起来很明显,但习惯于针对 Flash 和 AIR 桌面运行时的开发者往往会忽略它们。在为 iOS 开发时,每一项节省都很重要,这对于文本同样适用,即使是少量文本也可能对性能产生重大影响。

还有更多...

以下可能有助于你获得更多的性能提升。

设备字体

此配方使用了嵌入式字体。然而,通过使用直接安装在 iOS 设备上的字体,可以进一步节省空间。这不仅会减小你的 SWF 文件大小,还会提高性能,因为设备字体渲染到屏幕上的速度比嵌入式字体快。此外,在嵌入字体之前,检查该字体是否在设备上可用。

追加文本

将字符串追加到文本字段末尾是另一个常见的任务,可能会很昂贵。这通常使用连接赋值运算符(+=)来完成,以下是一个简单的示例:

textField.text = "Hello ";
textField.text += "Christopher";

然而,TextField类提供了appendText()方法,它执行此操作的速度要快得多:

textField.text = "Hello ";
textField.appendText("Christopher");

如果你正在追加文本,那么请使用这种方法而不是连接赋值运算符。

用位图替换文本字段

在性能至关重要的地方,使用位图来表示文本。

例如,考虑一个用户得分不断更新的游戏。使用动态文本字段可能会损害性能。相反,编写一些 ActionScript 来显示和排列每个数字的位图表示。虽然这需要更多的编码工作,但通常使用位图会比使用由复杂矢量形状构成的字体表现更好。

缓存为位图

文本字段可以被缓存为位图,防止它在某些情况下被重新渲染,并提供性能提升。文本字段的缓存不能从 Flash IDE 中应用,而必须使用 ActionScript 来完成。使用cacheAsBitmapcacheAsBitmapMatrix属性,这些属性对TextField类可用。位图缓存不能直接应用于静态文本字段。

更多信息,请参阅第六章中的使用位图缓存使用位图缓存矩阵配方。

参见

  • 使用更新循环,第三章

  • 在文本字段中使用设备字体

  • 在文本字段中使用嵌入式字体

使用原生 iOS 文本控件

AIR 3.0 引入了StageText类,它提供了对 iOS 原生文本输入控件和自定义虚拟键盘的能力。

让我们看看如何创建一个原生文本输入字段并指定在执行文本输入时启动的虚拟键盘类型。

这里涵盖的步骤仅适用于使用 AIR 3.0 及以上版本的用户。如果你使用 Flash Professional CS5,那么你将无法尝试这个配方,因为它仅支持 AIR 2.0。

准备工作

已提供一个 FLA 作为起点。从本书的配套代码包中,将chapter7\recipe7\recipe.fla打开到 Flash Professional CS5.5 中。

阶段上有一个背景位图图像。我们将编写一些 ActionScript 来叠加一个原生文本输入字段,当点击时将启动一个配置为输入人名的虚拟键盘。

如何做到这一点...

我们将通过以下步骤大量使用flash.text包中找到的类:

  1. 创建一个文档类并将其命名为Main

  2. 将以下导入语句添加到类中:

    import flash.display.MovieClip;
     import flash.events.FocusEvent;
    import flash.geom.Rectangle;
    import flash.text.ReturnKeyLabel;
    import flash.text.SoftKeyboardType;
    import flash.text.StageText;
    import flash.text.TextFormatAlign;
    import flash.text.engine.FontWeight; 
    
    
  3. 声明一个StageText成员变量:

    private var nativeText:StageText;
    
    
  4. 现在在构造函数中创建并初始化一个原生文本输入字段。作为初始化的一部分,我们将确保它包含提示用户输入他们名字的文本:

    public function Main() {
    nativeText = new StageText();
    nativeText.stage = stage;
    nativeText.viewPort = new Rectangle(30, 28, 420, 116);
    nativeText.fontFamily = "ChalkboardSE-Bold";
    nativeText.fontSize = 50;
    nativeText.color = 0xB88858;
    nativeText.fontWeight = FontWeight.BOLD;
    nativeText.textAlign = TextFormatAlign.CENTER;
    nativeText.text = "enter name";
    nativeText.maxChars = 11;
    nativeText.softKeyboardType = SoftKeyboardType.CONTACT;
    nativeText.returnKeyLabel = ReturnKeyLabel.DONE;
    }
    
    
  5. 此外,通过添加以下高亮代码来监听用户触摸时文本字段获得焦点的事件:

    nativeText.returnKeyLabel = ReturnKeyLabel.DONE;
    nativeText.addEventListener(FocusEvent.FOCUS_IN, focusIn);
    }
    
    
  6. 当它获得焦点时,我们将移除字段的默认文本,使用户能够直接输入他们的名字,而无需先删除字符。以下代码片段是该事件处理程序:

    private function focusIn(e:FocusEvent):void {
    if(nativeText.text == "enter name")
    {
    nativeText.text = "";
    }
    }
    
    
  7. 保存类,并在提示时将文件命名为Main.as

  8. 返回到你的 FLA 并保存它。现在发布应用程序并在你的设备上测试它。

如何做到这一点...

点击输入名字文本字段并使用虚拟键盘输入文本。按完成键提交更改。

它是如何工作的...

StageText 类允许将原生 iOS 文本输入字段添加到应用程序中。与 Flash 的 Classic 和 TLF 文本字段类型不同,StageText 提供了在 iOS 上找到的相同用户交互行为,例如放大、文本选择、自动大写、自动更正和虚拟键盘自定义。

然而,尽管可以使用 IDE 的工具面板添加 Classic 和 TLF 文本字段,但每个 StageText 实例都必须通过编程方式添加、定位和调整大小。以下代码片段展示了这一点:

nativeText = new StageText();
nativeText.stage = stage;
nativeText.viewPort = new Rectangle(30, 28, 420, 116);

在此代码片段中,使用 stage 属性添加文本字段——StageText 对象不能添加到显示列表中,而必须直接附加到舞台。通过传递一个 Rectangle 对象到其 viewPort 属性来指定文本字段的位置和大小。此外,所有 StageText 实例都将出现在显示列表中的内容上方,并且它们的深度无法排序。因此,建议您避免重叠原生文本字段。

fontFamily 属性用于指定要使用的设备字体——不能使用嵌入的 Flash 字体。在指定设备字体时,请确保它在您希望针对的所有 iOS 设备上可用。

可以使用 text 属性设置原生文本字段中显示的当前文本,如果字段允许用户输入,则可以使用 maxChars 限制字符数。

最后,使用 softKeyboardType 属性设置输入文本时要使用的键盘类型。可以通过使用 returnKeyLabel 来进一步配置键盘,以指定其返回键的标签:

nativeText.softKeyboardType = SoftKeyboardType.CONTACT;
nativeText.returnKeyLabel = ReturnKeyLabel.DONE;

SoftKeyboardType 类提供的常量用于指定键盘类型,而 ReturnKeyLabel 类表示可用于返回键的各种不同标签。此代码指定了一个配置为姓名输入的键盘,其返回标签设置为完成

如果字段的 editable 属性设置为 true(默认情况下是如此),则当用户触摸它时将显示虚拟键盘。

如需更多信息,请在 Adobe Community Help 中搜索 flash.text.StageText

还有更多...

在我们离开这一章之前,这里有一些关于原生文本输入字段和虚拟键盘的附加细节。

虚拟键盘类型

支持的虚拟键盘类型在 flash.text.SoftKeyboardType 类中指定为公共常量,以下列出以供您方便参考:

  • CONTACT: 适用于输入人名或电话号码

  • DEFAULT: 默认键盘配置

  • EMAIL: 此配置适用于电子邮件地址的输入

  • NUMBER: 数字键盘

  • PUNCTUATION: 适用于包含标点的文本输入

  • URL: 优化用于 URL 输入

返回键标签类型

flash.text.ReturnKeyLabel 类提供了以下常量,可用于设置虚拟键盘的返回键:DEFAULT, DONE, GO, NEXTSEARCH

枚举设备字体

通过将 true 传递给 flash.text.Font.enumarateFonts() 静态方法,您可以枚举设备的可用字体。这将让您知道,在设置原生文本输入字段的 fontFamily 属性时,您可以从哪些字符串中进行选择。

事件

StageText 实例交互时,可能会触发以下事件:

  • FocusEvent.FOCUS_IN: 原生文本输入字段已获得焦点

  • FocusEvent:FOCUS_OUT: 原生文本输入字段已失去焦点

  • KeyboardEvent.KEY_DOWN: 一个虚拟键已被按下

  • KeyboardEvent.KEY_UP: 一个虚拟键已被释放

  • SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING: 虚拟键盘正在被激活,并且目前正在进入视图

  • SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE: 虚拟键盘已被激活,现在可以与 SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE 进行交互

  • SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE: 虚拟键盘已被停用

自动更正和自动大写

您可以通过将您的 StageText 对象的 autoCorrectautoCapitalize 属性设置为 true 来启用 iOS 的自动更正和自动大写功能。

参见

  • 在文本字段中使用设备字体

  • 配置虚拟键盘激活时的可滚动

第八章. 屏幕分辨率和方向变化

在本章中,我们将涵盖:

  • 针对设备

  • 针对 Retina 显示屏

  • 支持多个分辨率

  • 设置默认宽高比

  • 启用自动旋转

  • 监听方向变化

  • 响应方向变化

简介

加速度传感器的加入使得原始 iPhone 能够检测其物理方向的变化;根据用户的偏好重新排列其屏幕内容以适应纵向或横向观看。然而,提供这一点意味着应用程序必须为两种屏幕宽高比进行设计和编码——一种是纵向,另一种是横向。

随着 iOS 家族的壮大,必须支持的屏幕分辨率数量也在增加。随着 iPad 的推出和 Retina 显示屏设备的引入,现在有三个不同的分辨率。如果你还考虑了两种屏幕宽高比,那么你的应用程序的屏幕布局管理可能会变得令人望而生畏。

本章提供了将帮助你在任何 iOS 设备上正确渲染内容的菜谱,无论其屏幕分辨率和物理方向如何。

针对设备

iOS 家族包括三种设备:iPhone、iPod touch 和 iPad。在为 iOS 开发时,你必须声明你具体针对的设备。你的选择将决定你的应用程序如何由这三种设备运行。

这个菜谱将带你完成创建一个针对整个家族的应用程序所需的必要步骤。

准备工作

已提供了一个 FLA 作为本菜谱的起点。从书籍的配套代码包中打开chapter8\recipe1\recipe.fla

在舞台上有一个名为output的动态文本字段。我们将使用这个文本字段来报告应用程序当前正在运行的设备。

为了避免疑问,这个菜谱将不会利用 iPhone 4/4S 和第四代 iPod touch 的 Retina 显示屏分辨率。如果你想提供 Retina 支持,请参阅本章的针对 Retina 显示屏菜谱。

如何做到这一点...

我们将指定目标设备,然后编写一些 ActionScript 来报告应用程序当前正在运行的设备。

设置目标设备

让我们先设置目标设备:

  1. 通过从 Flash Professional 中选择文件 | AIR for iOS 设置来打开 AIR for iOS 设置面板。

  2. 确保已选择常规选项卡。

  3. 设备字段中选择iPhone 和 iPad

  4. 如果你正在使用 Flash Professional CS5.5,请将分辨率字段设置为标准

  5. 点击确定以关闭面板。

检测当前设备

现在,让我们继续添加这个菜谱所需的 ActionScript:

  1. 创建一个文档类;命名为Main

  2. 将以下三个导入语句添加到类中:

    import flash.display.MovieClip;
     import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.system.Capabilities;
    
    
  3. 在构造函数中,设置舞台的缩放模式和定位:

    public function Main() {
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = StageAlign.TOP_LEFT;
    }
    
    
  4. 使用 Capabilities 类,确定应用正在运行的设备:

    public function Main() {
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = StageAlign.TOP_LEFT;
     if(Capabilities.screenResolutionX == 320)
    {
    output.text = "iPhone / iPod touch";
    }
    else if(Capabilities.screenResolutionX == 768)
    {
    output.text = "iPad";
    } 
    }
    
    
  5. 将文档类保存在与您的 FLA 相同的文件夹中,并将其命名为 Main.as。同时保存 FLA。

  6. 在您的设备上发布和测试应用。如果您有多台设备,请安装到多台设备上。

当您在 iPhone 或 iPod touch 上运行它时,以下文本将输出到屏幕上:

iPhone / iPod touch

在 iPad 上测试的人将看到以下内容:

iPad

它是如何工作的...

您可以通过设置 AIR for iOS 设置面板中的 Device 字段来指定您希望针对的设备。以下有三个选项可供您选择:

  • iPhone

  • iPad

  • iPhone 和 iPad

iPod touch 没有列出,因为它被视为 iPhone——这两个设备具有相同的宽高比和分辨率。

选择 iPhone 将屏幕大小限制在 iPhone 和 iPod touch 的大小。您的应用仍然可以在 iPad 上运行,但它不会尝试利用 iPad 的更高分辨率。相反,iPad 将使用 iPhone 的标准 320x480 分辨率来运行应用。用户可以选择在正常大小下运行应用或使用像素加倍来覆盖几乎整个屏幕。

选择 iPad 可以利用 iPad 的整个 768x1024 分辨率,但将您的应用限制在该设备上。

如果您正在编写一个可以通过适应不同屏幕尺寸在所有三种设备上运行的 app,请选择 iPhone 和 iPad。这通常被称为通用应用,也是我们在本菜谱中选择的类型。

苹果承认编写针对多个设备和屏幕分辨率的难度。为了简化开发,当针对整个 iOS 系列时,他们提供了以下两个选项:

  • 编写两个单独的应用——一个用于 iPad,另一个用于 iPhone/iPod touch

  • 编写一个适应每个设备屏幕大小的通用应用

当然,您不必支持所有三种设备。例如,编写一个仅针对 iPad 的应用是完全可行的。

通过查询设备的屏幕分辨率,可以确定您的应用正在运行的设备。iPhone 和 iPod touch 的水平分辨率为 320 像素,而 iPad 的宽度为 768 像素。因此,我们只需要查询静态的 Capabilities.screenResolutionX 属性来确定设备类型,而无需也检查垂直分辨率 Capabilities.screenResolutionY

您可能会想使用 Stage.stageWidth,但请记住,由于舞台尺寸固定,此菜谱中所有设备类型都将返回相同的宽度。

您可以从 Adobe 社区帮助中获取有关 flash.system.Capabilities, flash.display.StageScaleModeflash.display.StageAlign 的更多信息。

更多信息...

在针对多个设备时,还应考虑以下信息。

应用程序启动图像

当针对多种设备类型时,请记住为每个支持的分辨率包含一个启动图像。如果您选择支持它们,也可以提供不同方向的备用启动图像。有关更多详细信息,请参阅第三章包含应用程序启动图像的菜谱[ch03.html "第三章。编写您的第一个应用程序"]。

包含图标

请记住包含每个设备类型所需的适当图标艺术品。有关更多详细信息,请参阅第三章包含图标的菜谱[ch03.html "第三章。编写您的第一个应用程序"]。

横屏宽高比

screenResolutionXscreenResolutionY 属性总是以设备竖直方向握持时返回。例如,一个默认横屏方向的 iPad 应用仍然会返回水平分辨率为 768 像素,垂直分辨率为 1024 像素的分辨率。

参见

  • AIR for iOS 通用设置,第二章

  • 针对 Retina 显示

  • 设置默认宽高比

针对 Retina 显示

iPhone 4 将 Retina 显示引入了世界。它将四倍的像素数压缩到与早期型号相同的屏幕中,提供了在移动设备上所见到的最清晰的图像。

使用 Flash Professional CS5.5 和至少 AIR 2.6 的用户可以使用 Retina 显示的 iPhone 和 iPod touch 提供的完整 640x960 分辨率。

准备中

从本书的配套代码示例中,将 chapter8\recipe2\recipe.fla 打开到 Flash Professional CS5.5 中。

这个 FLA 已作为起点提供,并在舞台上有一个名为 output 的动态文本字段。我们将使用这个文本字段来报告应用是否在 Retina 显示设备上运行。

虽然这个菜谱的示例应用可以在 iPad 上运行,但它不会针对其 768x1024 的屏幕分辨率。相反,它将模拟标准分辨率的 iPhone/iPod touch。

如何操作...

Retina 显示支持是在 AIR for iOS 设置面板中指定的。我们还将编写一个基本的文档类来确定应用实际上是否在 Retina 设备上运行。

设置 Retina 显示支持

让我们先启用对 Retina 显示屏幕分辨率的支持:

  1. 通过选择文件 | AIR for iOS 设置来打开 AIR for iOS 设置面板。

  2. 确保已选择常规选项卡。

  3. 分辨率字段设置为

  4. 此外,对于这个菜谱,确保设备字段设置为iPhone

  5. 点击确定按钮关闭面板。

检测 Retina 显示设备

在处理完 AIR for iOS 设置后,我们可以将注意力转向确定应用是否在 Retina 显示设备上运行的所需 ActionScript:

  1. 创建一个文档类,并将其命名为 Main

  2. 将以下三个导入语句添加到类中:

    import flash.display.MovieClip;
     import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.system.Capabilities; 
    
    
  3. 设置舞台的缩放模式和居中对齐属性:

    public function Main() {
     stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = StageAlign.TOP_LEFT; 
    }
    
    
  4. 查询设备的屏幕分辨率以确定它是否有视网膜显示屏:

    public function Main() {
    
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = StageAlign.TOP_LEFT;
     if(Capabilities.screenResolutionX == 320)
    {
    output.text = "Standard Resolution";
    }
    else if(Capabilities.screenResolutionX == 640)
    {
    output.text = "Retina Resolution";
    } 
    }
    
    
  5. 将类文件保存为Main.as在 FLA 相同的文件夹中。也要保存 FLA。

  6. 发布并部署 IPA 到你的设备。如果你有视网膜和标准显示屏设备可用,那么在两个设备上安装应用。

当你在视网膜显示屏的 iPhone 或 iPod touch 上运行应用时,以下文本将被输出到屏幕:

视网膜分辨率

对于标准显示屏设备,你会看到以下内容:

标准分辨率

它是如何工作的...

虽然已经保持了宽高比,但在为 iPhone 和 iPod touch 开发时,现在有两个屏幕分辨率可以针对:

  • 标准:320x480

  • 视网膜:640x960

视网膜显示屏的分辨率出现在第三代 iPhone 和 iPod touch 之后。所有之前的型号都使用标准显示屏分辨率。

如果你选择支持视网膜显示屏,那么你的应用也必须支持标准显示屏。苹果不允许你为每个支持的分辨率提交单独的 IPA。然而,你可以选择只支持标准显示屏,iOS 会将应用像素加倍以适应视网膜显示屏屏幕。

要指定你的应用将支持的分辨率,请在 AIR for iOS 设置面板中设置分辨率字段。以下有两个选项可用:

  • 标准

如果你同时为视网膜和标准显示屏提供支持,请选择。否则选择标准

当针对多个屏幕分辨率时,设置舞台的缩放模式和校准非常重要。

将缩放模式设置为NO_SCALE可以防止舞台内容缩放以适应视网膜屏幕的分辨率。相反,你的内容将保持其定义的大小。将舞台校准设置为TOP_LEFT将强制所有内容相对于左上角进行定位。

虽然缩放可能听起来很吸引人,但对于使用位图的应用程序来说,实际上并不建议这样做。位图在缩放时会出现像素化。相反,你应在你的应用中编写逻辑来在标准分辨率和视网膜分辨率的位图版本之间切换,并自行处理内容和布局的位置。

此外,你的 FLA 舞台大小应该与标准分辨率显示屏匹配——320x480 像素。当在视网膜显示屏设备上运行,并且将舞台的缩放模式设置为NO_SCALE时,舞台的尺寸将被报告为是你在 Flash Professional 中设置的尺寸的两倍。这将允许你利用更高的分辨率。

通过查询属于Capabilities类的静态screenResolutionXscreenResolutionY属性,可以确定你的应用正在使用的屏幕分辨率。对于这个菜谱,我们只是检查了screenResolutionX,因为这足以确定是否正在使用标准或视网膜屏幕分辨率。

您可以从 Adobe 社区帮助中获取有关 flash.system.Capabilitiesflash.display.StageScaleModeflash.display.StageAlign 的更多信息。

还有更多...

在使用 Retina 显示屏时,还有其他一些考虑因素。

Retina 主屏幕图标

当支持 Retina 显示屏时,您必须提供一个 114x114 像素的主屏幕图标。有关详细信息,请参阅第三章中的包含图标配方。

Retina 应用程序启动图像

您可以在 IPA 中包含一个额外的启动图像,该图像利用了 Retina 显示屏的高分辨率。有关更多详细信息,请参阅第三章中的包含应用程序启动图像配方。

仅矢量应用程序

如果您的应用程序仅使用矢量内容,则可以简单地让 AIR 为您处理缩放。这将允许您编写一个针对标准 320x480 像素显示屏的应用程序,这将同时利用更高分辨率的 Retina 显示屏。

要启用此功能,请将场景的缩放模式和定位设置为以下内容:

stage.scaleMode = StageScaleMode.SHOW_ALL;
stage.align = StageAlign.TOP_LEFT;

此外,请记住将 AIR for iOS 设置面板中的分辨率字段设置为

不要将此与 iOS 使用的像素加倍混淆。您的应用程序的矢量内容实际上会被缩放,而不是每个像素的大小加倍。本质上,在 Retina 设备上会有明显的图像保真度提升。

当然,您仍然可以使用位图,但与矢量内容不同,当它们放大时,像素化将非常明显。

iPad 显示屏

iPad 1 和 2 都支持 768x1024 像素的单一屏幕分辨率。当针对 iPad 或非 Retina 显示屏的 iPhone 和 iPod touch 时,将分辨率字段设置为标准

参见

  • AIR for iOS 通用设置,第二章

  • 针对设备

  • 支持多分辨率

支持多分辨率

iPad 的推出导致开发者必须支持两种不同的物理屏幕尺寸和分辨率。iPhone 和 iPod touch 引入 Retina 显示屏后,这种情况更加严重,因为同一设备类型的屏幕分辨率不再保证相同。

当针对多种设备和型号时,您的应用程序能够适应不同的屏幕分辨率非常重要。

让我们通过一个简单的示例来创建一个支持 iPhone、iPod touch 和 iPad 使用的各种纵向分辨率的通用应用程序。

准备工作

书籍附带的代码包中提供了一个包含图形的 FLA 文件,供您从中工作。

chapter8\recipe3\recipe.fla 打开到 Flash Professional 中。

在 FLA 的库中,你会找到三个 PNG 图像——每个屏幕分辨率一个。每个图像也已被链接以供 ActionScript 使用,允许它在运行时轻松添加到屏幕上。以下表格总结了这一点:

位图名称 AS 链接
标准显示 320x480 rocket-standard.png RocketStandardBitmapData
视网膜显示屏 640x960 rocket-retina.png RocketRetinaBitmapData
iPad 显示 768x1024 rocket-ipad.png RocketIPadBitmapData

当在标准显示的 iPhone 或 iPod touch 上运行时,屏幕上会显示 rocket-standard.png。对于视网膜显示屏,应用程序将使用 rocket-retina.png。最后,如果检测到 iPad 的屏幕分辨率,将显示 rocket-ipad.png

如果你使用 Flash Professional CS5 进行这个菜谱,那么你的应用程序将无法利用 Retina 显示设备提供的更高分辨率。Retina 显示支持仅从 AIR 2.6 开始可用。

如何操作...

我们将把这个菜谱分成两部分。首先,从 AIR for iOS 设置面板中,我们将声明支持所有设备分辨率。其次,我们将编写显示每个支持分辨率的正确位图的代码。

设置支持的设备和分辨率

让我们先针对所有可用的设备分辨率进行目标定位:

  1. 通过选择 文件 | AIR for iOS 设置 打开 AIR for iOS 设置面板。

  2. 确保选择了 常规 选项卡。

  3. 设备 字段设置为 iPhone 和 iPad

  4. 如果你使用的是 Flash Professional CS5.5,那么也将 分辨率 字段设置为

    如果你希望单个应用程序支持 iOS 家族中的所有设备并利用 Retina 显示设备提供的更高分辨率,则需要这些设置。

  5. 点击 确定 按钮关闭面板。

显示正确的位图

现在,我们将编写一些 ActionScript 代码以适应预期的每个屏幕分辨率:

  1. 创建一个文档类,并将其命名为 Main

  2. 为所需的类添加导入语句:

    import flash.display.MovieClip;
     import flash.display.Bitmap;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.system.Capabilities; 
    
    
  3. 在构造函数中,设置舞台的缩放模式和定位属性:

    public function Main() {
     stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = StageAlign.TOP_LEFT;
    }
    
    
  4. 在构造函数中,调用一个方法来为当前设备的屏幕分辨率创建正确的位图:

    public function Main() {
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = StageAlign.TOP_LEFT;
    var b:Bitmap = createRocketBitmap();
    addChild(b);
    }
    
    
  5. 现在,编写一个实例化和返回位图的函数:

    private function createRocketBitmap():Bitmap {
    var b:Bitmap;
    if(Capabilities.screenResolutionX == 320)
    {
    b = new Bitmap(new RocketStandardBitmapData());
    }
    else if(Capabilities.screenResolutionX == 640)
    {
    b = new Bitmap(new RocketRetinaBitmapData());
    }
    else if(Capabilities.screenResolutionX == 768)
    {
    b = new Bitmap(new RocketIPadBitmapData());
    }
    return b;
    }
    
    
  6. 将类文件保存为 Main.as。同时,回到你的 FLA 并保存它。

  7. 发布 FLA 并在一系列 iOS 设备上测试你的应用程序。

它是如何工作的...

这个菜谱的示例确定正在使用的屏幕分辨率,并显示为该分辨率准备的位图图像。

支持以下纵向分辨率:

  • iPad

    • 768x1024
  • iPhone 和 iPod touch

    • 320x480: 标准

    • 640x960: 视网膜

从 AIR for iOS 设置面板中,你必须明确声明你打算创建一个支持所有三种设备和它们屏幕分辨率的通用应用程序。这是通过将 设备 字段设置为 iPhone 和 iPad 以及将 分辨率 字段设置为 来完成的。

当针对多个屏幕分辨率时,设置舞台的缩放模式和校准非常重要。

将舞台的缩放模式设置为NO_SCALE确保你的内容在多个屏幕分辨率下保持其定义的大小。这让你完全控制内容的尺寸和布局。它还确保正在使用的位图在运行时不会被缩放,这将防止它们变得像素化。将舞台校准设置为TOP_LEFT强制所有内容相对于左上角定位,这使得定位更容易处理。

创建正确位图的实际代码只是简单地检查静态的Capabilities.screenResolutionX属性,以确定应用程序当前需要为哪三个预期的屏幕分辨率提供服务。一旦做出决定,正确的位图从库中实例化并添加到显示列表,其默认位置为(0,0)。

虽然舞台和时间轴仍然是内容布局的选项,但你可能会发现自己更依赖于 ActionScript 来处理更复杂的项目。

你可以从 Adobe 社区帮助中获取更多信息。搜索以下类:flash.system.Capabilities, flash.display.StageScaleMode, 和 flash.display.StageAlign

还有更多...

我们的例子有些简单。不幸的是,将实际应用适配到多个屏幕分辨率可能会很困难。

默认舞台大小

当其缩放模式设置为NO_SCALE时,舞台的默认大小对通用应用来说并不重要。例如,这个菜谱的 FLA 使用的是 320x480 的舞台大小,这显然远远低于 iPad 的 768x1024 分辨率。然而,这并不会限制应用程序的显示列表到舞台的默认尺寸——应用程序仍然能够针对其运行设备的全屏分辨率。

在进行跨多个分辨率的布局管理时,尽量不要依赖于默认的舞台大小。当确定你的应用程序当前运行在哪种设备上时,也是如此。相反,使用Capabilities.screenResolutionXCapabilities.screenResolutionY

模型-视图-控制器架构

尽管这超出了本书的范围,但你应该考虑使用模型-视图-控制器(MVC)设计模式来管理每个支持的屏幕分辨率的布局。

MVC 由三个元素组成:一个包含应用程序数据和状态管理逻辑的单个模型;至少一个视图,用于展示应用程序的屏幕状态;以及至少一个控制器,用于处理用户交互。

通常,一个视图会与一个控制器配对,你将为每个你希望支持的屏幕分辨率编写一个视图-控制器对。控制器在其视图和模型之间充当中间人。

有许多 ActionScript MVC 框架可用,例如 PureMVC 和 Robotlegs。你可以访问 PureMVC 的主页puremvc.org,而 Robotlegs 可以从www.robotlegs.org下载。

小贴士

苹果鼓励在为 iOS 编写应用时使用 MVC 模式。

动态尺寸和布局

当处理多个屏幕分辨率和像素密度时,你可能需要考虑开发你的应用以动态调整其内容的大小和布局。虽然这可能是一个复杂的方法,但它将为你的应用提供未来保障,使其能够适应未来可能出现的其他屏幕。然而,对于有限的屏幕数量,你可能发现 MVC 更可行。

更多详情,请查看 Adobe AIR 开发者中心的“编写多屏幕 AIR 应用”文章:www.adobe.com/devnet/air/flex/articles/writing_multiscreen_air_apps.html

单独支持 iPad

iPad 屏幕的宽高比与 iPhone 和 iPod touch 不同。这可能会使得开发一个适用于所有三个设备的单一应用变得尴尬,因为应用需要在运行时针对三种不同的分辨率调整其 UI。此外,对于位图密集型应用,存储三套图形将消耗大量内存。

为了减轻在一个应用中支持三个设备的复杂性,你可以单独编写你的 iPad 版本。App Store 将接受一个针对 iPad 的应用版本以及一个同时支持 iPhone 和 iPod touch 的应用版本。只需从 AIR for iOS 设置面板中指定你的目标设备。

相关内容

  • AIR for iOS 通用设置,第二章

  • 使用 ActionScript 访问位图,第六章

  • 调整位图大小,第四章

设置默认宽高比

像 iPhone 这样的设备可以在真实空间中自由旋转。这很方便,因为它提供了两种可以工作的宽高比——纵向和横向。

让我们看看如何选择默认宽高比。

准备工作

使用 Flash Professional,从书籍配套代码包中打开chapter8\recipe4\recipe.fla

该库包含一个为 480x320 像素横幅分辨率设计的消防车位图。

如何做到...

我们将首先将 FLA 锁定为横幅宽高比:

  1. 使用选择工具(V),在舞台上的任何位置点击。从属性面板中,将舞台的宽高比从纵向更改为横向。要做到这一点,只需将其宽度设置为480,高度设置为320

  2. 虽然舞台大小暗示了这一点,但 AIR for iOS 设置也需要更改以反映我们选择的宽高比。从下拉菜单中选择文件 | AIR for iOS 设置

  3. 确保已选中常规选项卡。

  4. 宽高比下拉框中选择横向

  5. 点击确定以关闭面板。

  6. 最后,将库中的位图图像拖动到舞台上,并将其放置在屏幕的左上角。

  7. 保存您的 FLA 文件并发布它。

  8. 在您的设备上安装应用程序并启动它。

为了正确查看消防车图像,您将不得不将设备侧放,使设备的物理方向与舞台的方向相匹配。

它是如何工作的...

您的应用程序可以从两种宽高比之一开始:纵向或横向。这是通过在 AIR for iOS 设置面板中的常规选项卡内从宽高比下拉框中进行选择来完成的。

此外,您还需要将舞台设置为与所选宽高比相匹配。这将允许您在设计应用程序时正确布局任何内容。

注意

当您创建一个新的 AIR for iOS 文档时,默认设置为纵向宽高比。

更多内容...

当从 Flash Professional CS5.5 设置默认宽高比时,还有一个额外的选项可用。

自动宽高比

从 AIR 2.6 开始,您的应用程序可以在启动时被指示选择与设备当前方向匹配的宽高比。为了适应这一点,从宽高比下拉框中提供了一个名为自动的第三个选项。

此功能只能与自动方向一起启用,这在下一道菜谱中有所介绍。

参见

  • AIR for iOS 常规设置,第二章

  • 启用自动方向

启用自动方向

用户可以在任何时刻在真实空间中更改设备的方向,并且可能会期望屏幕上的内容能够反映这一点。AIR for iOS 可以检测这些变化并自动旋转舞台以匹配设备的新物理方向。

本菜谱将向您展示如何启用自动方向。

准备工作

如果您已经完成了设置默认宽高比菜谱,那么您可以从其 FLA 继续工作。或者,从本书的配套源代码中,在 Flash Professional 中打开chapter8\recipe5\recipe.fla,然后从那里开始工作。

在任何情况下,您都会在舞台上看到一个消防车的位图图像。舞台本身的大小是为了适应横向宽高比,FLA 的 AIR for iOS 设置反映了这一点。

如何操作...

通过执行以下步骤启用自动方向:

  1. 通过选择文件 | AIR for iOS 设置来打开 AIR for iOS 设置面板。

  2. 确保已选中常规选项卡。

  3. 宽高比下拉框设置为纵向

  4. 选中自动方向复选框。

  5. 点击确定按钮以关闭面板。

  6. 保存您的 FLA 文件并发布它。

  7. 将应用程序部署到您的设备并启动它。

当设备的物理方向改变时,舞台将自动旋转以匹配这一变化。

它是如何工作的...

当自动旋转启用时,每次旋转时舞台都会尝试匹配设备的当前方向。iOS 支持四种方向:

  • 默认:iOS 设备的默认纵向方向

  • 向左旋转:顺时针旋转 90 度

  • 向右旋转:逆时针旋转 90 度

  • 颠倒:旋转 180 度

自动旋转很方便,因为它可以防止你不得不手动旋转显示列表中的对象。相反,这项任务将代表你完成。

在自动旋转期间,舞台的缩放模式和当前的对其设置将被遵守。

此外,如果你决定支持纵向和横向的宽高比,那么苹果建议你的应用以纵向模式启动。

更多...

很可能你希望对舞台上的内容在自动旋转时的处理方式有一定的控制。

检查方向支持

虽然 Flash 为所有 iOS 设备提供了对设备方向变化的支持,但在编写跨平台代码时,你可能想通过检查舞台的supportsOrientationChange属性返回true来确认支持。

通过编程设置自动旋转

除了使用 AIR for iOS 设置面板外,你还可以通过设置Stage.autoOrients属性来程序化地激活和停用自动旋转。该属性的初始值是从 AIR for iOS 设置面板中的自动旋转字段派生的。

以下 ActionScript 激活了自动旋转:

stage.autoOrients = true;

舞台缩放模式

你可以指定当设备的物理方向改变时舞台的缩放方式。这是通过将Stage.scaleMode属性设置为flash.display.StageScaleMode类提供的四个常量之一来实现的。

默认模式是StageScaleMode.SHOW_ALL,确保整个舞台在屏幕内可见,同时保持其宽高比。如果你不希望在方向变化时调整舞台内容的尺寸,则将缩放模式设置为NO_SCALE。这指定了舞台内容的大小将保持不变。

关于缩放模式的更多信息可以在 Adobe 社区帮助中找到。

舞台对齐

当设备的物理方向改变时,舞台内容对齐的方式也可以指定。只需将Stage.align属性设置为flash.display.StageAlign定义的常量之一即可。

舞台的内容默认将居中显示在屏幕上,然而,有八个常量可以用来将舞台的内容对齐到屏幕的边缘。例如,以下 ActionScript 将对舞台进行左上角对齐:

stage.align = StageAlign.TOP_LEFT;

关于舞台对齐的更多信息可以在 Adobe 社区帮助中找到。

相关内容

  • AIR for iOS 常规设置,第二章

  • 监听方向变化

监听方向变化

iOS 设备中存在的加速度计可以检测物理方向的变化。AIR 提供了 API 来检测这些变化并确定设备在真实空间中的实际方向。

让我们看看这是如何实现的。

准备工作

首先,从书籍附带代码包中打开chapter8\recipe6\recipe.fla

在舞台上可以找到一个名为output的动态文本字段。我们将使用此文本字段来报告设备经历的方向变化。

如何实现...

执行以下步骤以监听方向变化:

  1. 从 Flash Professional 的下拉菜单中选择文件 | AIR for iOS 设置

  2. 常规选项卡中,勾选自动旋转复选框;然后点击面板的确定按钮。

  3. 创建一个文档类,并将其命名为Main

  4. 添加以下导入语句:

    import flash.display.MovieClip;
     import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.StageOrientationEvent; 
    
    
  5. 在构造函数中,设置舞台,并监听正在分发的ORIENTATION_CHANGINGORIENTATION_CHANGE事件:

    public function Main() {
     stage.align = StageAlign.TOP_LEFT;
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.addEventListener(
    StageOrientationEvent.ORIENTATION_CHANGING,
    orientationChanging);
    stage.addEventListener(
    StageOrientationEvent.ORIENTATION_CHANGE,
    orientationChanged);
    output.text = "Rotate the device."; 
    }
    
    
  6. ORIENTATION_CHANGING事件编写一个处理器:

    private function orientationChanging(e:StageOrientationEvent):void {
    output.text = "Orientation Changing\n";
    output.appendText(
    "Current orientation: " + e.beforeOrientation + "\n");
    output.appendText(
    physical orientation changeslistening"Target orientation: " + e.afterOrientation + "\n\n");
    }
    
    
  7. 最后,添加对ORIENTATION_CHANGE事件的处理器:

    private function orientationChanged(e:StageOrientationEvent):void {
    output.appendText("Orientation Changed\n");
    output.appendText(
    "Previous orientation: " + e.beforeOrientation + "\n");
    output.appendText(
    "Current orientation: " + e.afterOrientation + "\n\n");
    }
    
    
  8. 当提示时,保存类并将其命名为Main.as。同时,保存您的 FLA 文件。

  9. 发布应用程序并在您的设备上测试它。

通过旋转设备进行实验。一旦检测到方向变化,它们将在屏幕上显示。

它是如何工作的...

可以通过监听舞台上的以下两个事件来检测方向变化:

  • StageOrientationEvent.ORIENTATION_CHANGING

  • StageOrientationEvent.ORIENTATION_CHANGE

当设备的加速度计检测到正在发生方向变化时,会分发生ORIENTATION_CHANGING事件,并在自动旋转的默认行为发生之前。ORIENTATION_CHANGE事件在所有默认行为发生后分发生。

只有当从 AIR for iOS 设置面板或通过 ActionScript 启用自动旋转时,您的应用程序才会接收到ORIENTATION_CHANGINGORIENTATION_CHANGE事件。

您可以通过查询事件对象的beforeOrientationafterOrientation属性来检索有关方向变化的信息。这两个属性是只读的,并将设置为flash.display.StageOrientation中的以下常量之一:

  • DEFAULT: iOS 设备的默认纵向方向。

  • ROTATED_LEFT: 顺时针旋转 90 度。

  • ROTATED_RIGHT: 逆时针旋转 90 度。

  • UPSIDE_DOWN: 旋转了 180 度。

当处理ORIENTATION_CHANGING事件时,beforeOrientation将保持设备的当前方向,而afterOrientation将指定设备旋转到的目标方向。

对于ORIENTATION_CHANGE事件,使用beforeOrientation来获取设备的前一个方向,并使用afterOrientation来确定当前方向。

您可以在我们的文档类的orientationChanging()orientationChanged()事件处理器中看到这两个属性的使用。它们的值被获取并写入output文本字段。

更多内容...

也可以在不使用事件监听器的情况下确定设备的方向。

确定设备方向

您还可以通过访问Stage类的deviceOrientation属性来确定设备的物理方向。此属性为只读,并将返回StageOrientation类中定义的其中一个常量。

除了我们已讨论的四个常量之外,deviceOrientation还可以返回StageOrientation.UNKNOWNdeviceOrientation属性不包含设备的起始方向,因此,在第一次发生物理方向变化之前,它被设置为UNKNOWN

参见

  • AIR for iOS 常规设置,第二章

  • 响应方向变化

  • 启用自动方向调整

响应方向变化

您可能希望更新应用程序的屏幕内容以反映设备物理方向的变化。虽然自动方向调整与舞台的默认对齐和缩放模式将代表您尝试这样做,但您可能希望自行处理布局。

本食谱将向您展示如何做到这一点。

准备工作

已提供一个 FLA 作为起点。从本书的配套代码包中,在 Flash Professional 中打开chapter8\recipe7\recipe.fla

您将在舞台上找到两个电影剪辑。第一个电影剪辑是一个向上指的箭头的图像,它已被创建以适应屏幕的尺寸,并使用纵向方向。第二个显示了相同的箭头,但这次图像的尺寸适合屏幕的横向方向。

两个电影剪辑都位于舞台的左上角,分别具有实例名称portraitlandscape

我们将编写一些代码,以确保无论用户将设备旋转到四个可能的物理方向中的哪一个,都能看到向上指的箭头。我们将通过显示适合当前设备方向的适当电影剪辑来实现这一点。

舞台尺寸设置为初始的纵向宽高比,这已在 AIR for iOS 设置中反映出来。

如何做到这一点...

在转向 ActionScript 之前,我们将快速更改 AIR for iOS 设置。

  1. 从 Flash Professional 的下拉菜单中选择文件 | AIR for iOS 设置

  2. 常规选项卡中,勾选自动方向调整复选框;然后单击面板的确定按钮。

  3. 创建一个文档类并命名为Main

  4. 将以下导入语句添加到类中:

    import flash.display.MovieClip;
     import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display.StageOrientation;
    import flash.events.StageOrientationEvent; 
    
    
  5. 在构造函数中设置舞台并监听ORIENTATION_CHANGING事件:

    public function Main() {
     stage.align = StageAlign.TOP_LEFT;
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.addEventListener(
    StageOrientationEvent.ORIENTATION_CHANGING,
    orientationChanging);
    landscape.visible = false; 
    }
    
    
  6. 最后,添加一个处理ORIENTATION_CHANGING事件的处理器:

    private function orientationChanging(e:StageOrientationEvent):void {
    if(
    e.afterOrientation == StageOrientation.DEFAULT || e.afterOrientation == StageOrientation.UPSIDE_DOWN
    )
    {
    portrait.visible = true;
    landscape.visible = false;
    }
    else if(
    e.afterOrientation == StageOrientation.ROTATED_LEFT || e.afterOrientation == StageOrientation.ROTATED_RIGHT
    )
    {
    portrait.visible = false;
    landscape.visible = true;
    }
    }
    
    
  7. 将类文件保存为Main.as。也移动到您的 FLA 并保存它。

  8. 发布 FLA 并将 IPA 部署到您的设备上。

  9. 通过旋转您的设备来测试应用程序。屏幕将更新以反映任何方向变化。

它是如何工作的...

我们不是让舞台当前屏幕内容在设备方向改变时自动调整大小,而是选择显示不同的视图。

实现这一点的第一步是设置舞台的缩放模式和定位。

将缩放模式设置为NO_SCALE可以防止您的内容缩放以适应舞台大小的任何变化。这确保了在方向改变期间,portraitlandscape电影剪辑保持其定义的大小。

将对齐方式设置为TOP_LEFT会强制所有内容相对于屏幕的左上角进行定位。本质上,我们位于舞台(0,0)位置的两个电影剪辑将始终从屏幕的左上角开始,无论设备处于何种方向。

下一步是在方向改变时使相应的电影剪辑可见。这是通过处理ORIENTATION_CHANGING事件并根据afterOrientation属性的值选择电影剪辑来实现的。

如果设备正在旋转到两种竖屏方向之一(DEFAULTUPSIDE_DOWN),则portrait电影剪辑将变为可见,而landscape将隐藏。对于两种横屏方向(ROTATED_LEFTROTATED_RIGHT),将显示landscape电影剪辑,而portrait将不可见。

您可能想知道为什么我们只有两个电影剪辑用于四种可能的屏幕方向。portraitlandscapeUPSIDE_DOWNROTATED_LEFT方向上不会颠倒吗?好吧,它们确实会短暂颠倒,但请记住,自动方向调整的一个好处是它会旋转您的屏幕内容,确保它以正确的方向显示。如果没有自动方向调整,您将不得不手动旋转显示列表上的所有项目。

还有更多...

这里有一些更多细节,可以帮助您完善对屏幕方向的知识。

舞台颜色

您选择的舞台颜色很重要,因为在自动方向调整期间,舞台尺寸之外的区域将是可见的。选择一种能够衬托您内容的舞台颜色。例如,这个菜谱使用了黑色,因为它与两个电影剪辑的背景颜色相匹配。

将舞台颜色改为白色,并将应用重新部署到您的设备上。在方向改变期间,您现在将能够看到实际上有多少区域是可见的。

舞台方向

尽管它们通常匹配,但设备在真实空间中的实际方向与屏幕上查看的内容是独立的。例如,用户可能手持设备处于横屏方向,而应用的内容仍在以竖屏方式渲染。

虽然Stage.deviceOrientation属性可用于确定设备的物理方向,但您可以使用Stage.orientation属性来检索舞台相对于设备当前的方向。

还可以独立于设备更改舞台的方向。这是通过调用Stage.setOrientation()并传递flash.display.StageOrientation类中定义的其中一个常量来实现的。您可以通过监听并响应ORIENTATION_CHANGINGORIENTATION_CHANGE事件来对此方向更改做出响应。

防止自动旋转

自动旋转发生在ORIENTATION_CHANGING事件之后,但在ORIENTATION_CHANGE事件分发之前。因此,可以通过在ORIENTATION_CHANGING事件的对象上调用preventDefault()来防止特定方向(或所有方向)的自动旋转。

例如,以下对orientationChanging()处理器的修改将防止设备旋转到两种横屏方向之一时舞台被定位:

private function orientationChanging(e:StageOrientationEvent):void {
 if(
e.afterOrientation == StageOrientation.ROTATED_LEFT ||
e.afterOrientation == StageOrientation.ROTATED_RIGHT
)
{
e.preventDefault();
} 
}

您还可以使用preventDefault()来阻止自动旋转,以便完全自行管理舞台内容的旋转和定位。

参见

  • AIR for iOS 通用设置,第二章

  • 监听方向更改

  • 启用自动旋转

第九章。地理位置和加速度计 API

在本章中,我们将介绍:

  • 确定当前位置

  • 确定速度和航向

  • 检查地理位置访问权限

  • 响应加速度计变化

  • 检测震动

简介

iOS 系列设备使用许多内置传感器,包括三轴加速度计、数字指南针、摄像头、麦克风和全球定位系统(GPS)。它们的加入为开发者创造了一个世界,并导致了一系列创新、创意和有趣的应用程序,这些应用程序为 App Store 的压倒性成功做出了贡献。

本章将重点介绍两种最流行的传感器——加速度计和 GPS;两者都由 AIR 为 iOS 提供支持。

加速度计测量重力加速度,能够检测物理方向、运动和振动。虽然最初被许多人视为一种花招,但随着平台的演变,其用途变得越来越复杂。从游戏到遥控器,从绘图软件到声音生成,加速度计已成为许多应用程序的首选输入方法。

像 iPhone 这样的设备也具有位置感知功能;其 GPS 接收器能够确定其在世界上的位置。可以跟踪运动,获取当前速度,甚至可以确定设备面向的方向。除了地图服务外,位置服务还在各种领域找到其应用,从摄影到消息客户端。

AIR 提供了 API,允许访问设备传感器收集的加速度计和位置数据。加速度计的支持由flash.sensors.Accelerometer类提供,而flash.sensors.Geolocation用于编写位置感知应用程序。

确定当前位置

iOS 系列设备具有位置感知功能,允许确定你的大致地理位置。这是如何实现的取决于设备中存在的硬件。例如,原始 iPhone、所有型号的 iPod touch 和仅 Wi-Fi 的 iPad 使用 Wi-Fi 网络三角测量法来提供位置信息。其余设备可以使用内置的 GPS 芯片或手机塔三角测量法更精确地计算其位置。

AIR SDK 提供了一层抽象,允许你以硬件无关的方式提取位置信息,这意味着你可以使用相同的代码在任何 iOS 设备上访问信息。

此配方将指导你完成确定当前位置所需的步骤。

准备工作

已提供 FLA 作为此配方的起点。

从 Flash Professional 中,打开书附带代码包中的chapter9\recipe1\recipe.fla

你将找到六个动态文本字段,它们位于舞台上。我们将用从设备获取的位置数据填充每个字段。

如何操作...

执行以下步骤以监听和显示地理位置数据:

  1. 创建一个文档类并将其命名为Main

  2. 导入以下类并添加一个类型为Geolocation的成员变量:

    package {
    import flash.display.MovieClip;
     import flash.events.GeolocationEvent;
    import flash.sensors.Geolocation; 
    public class Main extends MovieClip {
     private var geo:Geolocation; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在类的构造函数中,实例化一个Geolocation对象并监听它的更新:

    public function Main() {
    if(Geolocation.isSupported)
    {
    geo = new Geolocation();
    geo.setRequestedUpdateInterval(1000);
    geo.addEventListener(GeolocationEvent.UPDATE, geoUpdated);
    }
    }
    
    
  4. 现在,编写一个事件处理程序,它将获取更新的地理位置数据并将其填充到动态文本字段中:

    private function geoUpdated(e:GeolocationEvent):void {
    latitudeField.text = e.latitude.toString();
    longitudeField.text = e.longitude.toString();
    altitudeField.text = e.altitude.toString();
    hAccuracyField.text = e.horizontalAccuracy.toString();
    vAccuracyField.text = e.verticalAccuracy.toString();
    timestampField.text = e.timestamp.toString();
    }
    
    
  5. 将类文件保存为Main.as,位于与 FLA 相同的文件夹中。返回到 FLA 并保存它。

  6. 在您的设备上发布和测试应用。

  7. 首次启动时,将出现一个带有以下提示的原生 iOS 对话框:

    "c9 r1" 希望使用您的当前位置

    点击确定按钮以授予您的应用访问设备位置数据的权限。

小贴士

运行 iOS 4 或更高版本的设备将记住您的选择,而运行较旧版本 iOS 的设备将在每次应用启动时提示您。

位置数据将在屏幕上显示并定期更新。带着您的设备移动,您将看到数据随地理位置变化而变化。

它是如何工作的...

AIR 在flash.sensors包中提供了Geolocation类,允许从您的设备检索位置数据。要访问数据,创建一个Geolocation实例并监听它派发的GeolocationEvent.UPDATE事件。

我们在文档类的构造函数中这样做,使用geo成员变量来保存对对象的引用:

geo = new Geolocation();
geo.setRequestedUpdateInterval(1000);
geo.addEventListener(GeolocationEvent.UPDATE, geoUpdated);

可以通过调用Geolocation.setRequestedUpdateInterval()方法来设置获取位置数据的频率。您可以在之前的代码中看到这一点,我们请求了 1000 毫秒的更新间隔。这仅作为对设备的提示,意味着实际更新之间的时间可能大于或小于您的请求。省略此调用将导致设备使用默认的更新间隔。默认间隔可以是毫秒到秒之间的任何值,具体取决于设备的硬件能力。

每个UPDATE事件都会派发一个GeolocationEvent对象,该对象包含描述您当前位置的属性。我们的geoUpdated()方法通过将几个属性输出到舞台上的动态文本字段来处理此事件:

private function geoUpdated(e:GeolocationEvent):void {
latitudeField.text = e.latitude.toString();
longitudeField.text = e.longitude.toString();
altitudeField.text = e.altitude.toString();
hAccuracyField.text = e.horizontalAccuracy.toString();
vAccuracyField.text = e.verticalAccuracy.toString();
timestampField.text = e.timestamp.toString();
}

输出了以下信息:

  • 经纬度

  • 海拔

  • 水平和垂直精度

  • 时间戳

经纬度位置用于识别您的地理位置。您的海拔也会被获取,并以米为单位进行测量。随着您使用设备移动,这些值将更新以反映您的新位置。

位置数据的精度也会显示,并取决于设备的硬件能力。水平和垂直精度都以米为单位进行测量。

最后,每个派发的GeolocationEvent对象都会关联一个时间戳,这允许您确定每个事件之间的实际时间间隔。时间戳指定了自应用启动以来经过的毫秒数。

一些不包含 GPS 单元的较旧设备只会偶尔分发 UPDATE 事件。最初,会分发一个或两个 UPDATE 事件,只有在位置信息明显变化时才会分发额外的事件。

还请注意在构造函数中使用的静态 Geolocation.isSupported 属性。尽管目前所有 iOS 设备都将返回 true,但未来设备不能保证。在编写跨平台代码时,检查地理位置支持也是建议的。

如需更多信息,请在 Adobe 社区帮助中搜索 flash.sensors.Geolocationflash.events.GeolocationEvent

更多内容...

可用信息和信息的准确性取决于设备的性能。

准确度

位置数据的准确性取决于设备计算您位置所采用的方法。通常,带有内置 GPS 芯片的 iOS 设备将比依赖 Wi-Fi 三角测量的设备有优势。

例如,在包含 GPS 单元的 iPhone 4 上运行此配方应用程序,其水平精度约为 10 米。在依赖 Wi-Fi 网络的第三代 iPod touch 上运行相同的应用程序,报告的水平精度约为 100 米。差别相当大!

高度支持

当前高度只能从带有 GPS 功能的设备中获取。在没有 GPS 单元的设备上,GeolocationEvent.verticalAccuracy 属性将返回 -1,而 GeolocationEvent.altitude 将返回 0。垂直精度为 -1 表示无法检测到高度。

在开发提供基于位置服务的应用程序时,您应该注意并针对这些限制进行编码。不要对设备的性能做出假设。

如果您的应用程序依赖于 GPS 硬件的存在,那么您可以在应用程序描述文件中声明这一点。这样做将防止没有必要硬件的用户从 App Store 下载您的应用程序。

如需更多信息,请查看第十三章中的 声明设备性能 章节配方。

映射您的位置

获取地理位置数据的最明显用途是映射。通常,应用程序将获取地理位置并显示其周边地区的地图。有几种实现方式,但启动并将位置数据传递给设备的原生地图应用程序可能是最简单的方法。查看第十三章中的 启动地图应用程序(Chapter 13)以了解如何实现。

如果您更喜欢 ActionScript 解决方案,那么有 UMap ActionScript 3.0 API,它可以与包括必应、谷歌和雅虎在内的广泛地图数据提供商的地图数据集成。您可以在www.umapper.com上注册并下载 API。同时,在www.afcomponents.com/tutorials/umap_as3上也有教程可用。

计算地理位置之间的距离

当两个不同位置的地理坐标已知时,可以确定它们之间的距离。AIR 不提供相应的 API,但在 Adobe 开发者连接网站上可以找到一个 AS3 解决方案:cookbooks.adobe.com/index.cfm?event=showdetails&postId=5701

UMap ActionScript 3.0 API 也可以用来计算距离。请参阅www.umapper.com

地理编码

地图服务提供商,如谷歌和雅虎,提供地理编码和反向地理编码的 Web 服务。地理编码是将地址转换为经纬度的过程,而反向地理编码则是将经纬度对转换为可读的地址。

您可以从您的 AIR for iOS 应用程序向这些服务中的任何一个发送 HTTP 请求。例如,查看雅虎 PlaceFinder Web 服务developer.yahoo.com/geo/placefinder

或者,UMap ActionScript 3.0 API 可以与许多这些服务集成,直接在您的 Flash 项目中提供地理编码功能。请参阅 uMapper 网站。

陀螺仪支持

另一个流行的传感器是陀螺仪,它出现在较新的 iOS 设备中。虽然 AIR SDK 不直接支持陀螺仪访问,但 Adobe 为 AIR 3.0 提供了一种原生扩展,它提供了一个Gyroscope ActionScript 类。

您可以在 Adobe 开发者连接网站上找到下载链接和使用示例,网址为www.adobe.com/devnet/air/native-extensions-for-air/extensions/gyroscope.html

参见

  • 确定您的速度和航向

  • 启动地图应用程序,第十三章

确定您的速度和航向

由于内置了 GPS 单元,因此可以确定您的速度和航向。在本食谱中,我们将编写一个简单的应用程序,使用Geolocation类获取和使用这些信息。此外,我们将通过利用用户的当前航向来添加指南针功能。

准备工作

您需要一个带有 GPS 功能的 iOS 设备。自 3G 发布以来,iPhone 就内置了 GPS 单元。所有支持蜂窝网络功能的 iPad 也配备了 GPS 硬件。

从 Flash Professional 中,打开书籍附带代码包中的chapter9\recipe2\recipe.fla

舞台上坐着三个动态文本字段。前两个(speed1Fieldspeed2Field)将分别用于显示以米/秒和英里/小时为单位的当前速度。我们将把设备的当前航向写入第三个—headingField

此外,一个名为compass的电影剪辑被放置在舞台底部附近,它代表了一个带有北、南、东和西清晰标记的指南针。我们将根据航向变化更新这个剪辑的旋转,以确保它始终指向真正的北方。

如何做到这一点...

要获取设备的速度和航向,执行以下步骤:

  1. 创建一个文档类并命名为Main

  2. 添加必要的导入语句、一个常量和类型为Geolocation的成员变量:

    package {
    import flash.display.MovieClip;
     import flash.events.GeolocationEvent;
    import flash.sensors.Geolocation; 
    public class Main extends MovieClip {
     private const CONVERSION_FACTOR:Number = 2.237;
    private var geo:Geolocation; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在构造函数中,实例化一个Geolocation对象并监听更新:

    public function Main() {
     if(Geolocation.isSupported)
    {
    geo = new Geolocation();
    geo.setRequestedUpdateInterval(50);
    geo.addEventListener(GeolocationEvent.UPDATE, geoUpdated);
    } 
    }
    
    
  4. 我们需要一个事件监听器来监听Geolocation对象的UPDATE事件。这是我们获取和显示当前速度和航向的地方,并更新compass电影剪辑以确保它指向真正的北方。添加以下方法:

    private function geoUpdated(e:GeolocationEvent):void {
    var metersPerSecond:Number = e.speed;
    var milesPerHour:uint = getMilesPerHour(metersPerSecond);
    speed1Field.text = String(metersPerSecond);
    speed2Field.text = String(milesPerHour);
    var heading:Number = e.heading;
    compass.rotation = 360 - heading;
    headingField.text = String(heading);
    }
    
    
  5. 最后,添加这个支持方法将米/秒转换为英里/小时:

    private function getMilesPerHour(metersPerSecond:Number):uint
    {
    return metersPerSecond * CONVERSION_FACTOR;
    }
    
    
  6. 将类文件保存为Main.as。回到 FLA 并保存它。

  7. 编译 FLA 并将 IPA 部署到您的设备上。

  8. 启动应用程序。当提示时,授予您的应用程序访问 GPS 单元的权限。

将设备放在您面前并开始原地转动。航向(度)字段将更新以显示您面对的方向。compass电影剪辑也将更新,显示相对于您当前航向的真正北方在哪里。

将您的设备拿到户外,开始行走,或者更好的是,开始跑步。平均每 50 毫秒,您将看到顶部两个文本字段更新并显示您的当前速度,以每秒米和每小时英里为单位进行测量。

它是如何工作的...

在这个菜谱中,我们创建了一个Geolocation对象并监听它派发UPDATE事件。我们指定了 50 毫秒的更新间隔,试图频繁地接收速度和航向信息。

速度和航向信息都是从GeolocationEvent对象中获得的,该对象在每个UPDATE事件上派发。事件被捕获并由我们的geoUpdated()处理程序处理,该处理程序显示来自加速度计的速度和航向信息。

当前速度以米/秒为单位进行测量,通过查询GeolocationEvent.speed属性获得。我们的处理程序还在显示每个值之前将速度转换为英里/小时。以下代码执行此操作:

var metersPerSecond:Number = e.speed;
var milesPerHour:uint = getMilesPerHour(metersPerSecond);
speed1Field.text = String(metersPerSecond);
speed2Field.text = String(milesPerHour);

航向,表示相对于真正北方的运动方向(以度为单位),从GeolocationEvent.heading属性中检索。该值用于设置compass电影剪辑的rotation属性,并也写入headingField文本字段:

var heading:Number = e.heading;
compass.rotation = 360 - heading;
headingField.text = String(heading);

剩余的方法是getMilesPerHour(),它用于geoUpdated()中,将当前速度从米每秒转换为每小时英里。注意使用了在您的文档类中声明的CONVERSION_FACTOR常量:

private function getMilesPerHour(metersPerSecond:Number):uint
{
return metersPerSecond * CONVERSION_FACTOR;
}

尽管从 GPS 单元获取的速度和航向对于大多数应用来说已经足够,但不同设备之间的精度可能会有所不同。你的周围环境也可能产生影响;在高层建筑街道或树下移动可能会影响读数。

你可以在 Adobe Community Help 中找到有关flash.sensors.Geolocationflash.events.GeolocationEvent的更多信息。

还有更多...

以下信息提供了一些额外的细节。

确定支持

你的当前速度和航向只能由拥有 GPS 接收器的设备确定。

尽管你可以将此配方的应用安装在任何 iOS 设备上,但你不会从任何型号的 iPod touch、原始 iPhone 或仅 Wi-Fi 的 iPad 上收到有效的读数。相反,GeolocationEvent.speed属性将返回-1,而GeolocationEvent.heading将返回NaN

如果你的应用依赖于 GPS 硬件的存在,那么你可以在应用描述符文件中声明这一点。这样做将防止没有必要硬件的用户从 App Store 下载你的应用。

更多信息,请参阅第十三章中的声明设备能力配方 Chapter 13。

模拟 GPS 接收器

在开发周期中,在实时环境中不断测试你的应用是不切实际的。相反,你可能希望从你的设备中记录实时数据,并在测试期间重新使用它。有各种应用程序可以记录设备上的传感器数据。

其中一个这样的应用是 xSensor,可以从 iTunes 或 App Store 下载,并且是免费的。其数据传感器日志限制为 5KB,但可以通过购买 xSensor Pro 来解除此限制。

防止屏幕空闲

本章中的许多应用不需要你经常触摸屏幕。因此,在测试它们时,你可能会遇到背光变暗或屏幕锁定的情况。这可能会很麻烦,可以通过禁用屏幕锁定来防止这种情况。更多详情,请参阅第三章中的防止屏幕空闲配方 Chapter 3。

参见

  • 确定你的当前位置

  • 检查地理位置访问

检查地理位置访问

使用设备位置数据的应用程序必须获得用户的许可。当应用首次尝试访问位置数据时,会提示用户。运行 iOS 4 或更高版本的设备将记住这个选择,而较旧版本的 iOS 每次启动应用时都会请求访问权限。此外,访问权限可以在任何时候从设备的设置中更改。

重要的是您的应用程序能够检测地理位置数据的可用性,并且能够在运行时响应权限更改。让我们看看这是如何完成的。

准备中

已提供一个 FLA 文件作为起点。

从本书的配套代码包中,将chapter9\recipe3\recipe.fla文件打开到 Flash Professional 中。

已在舞台上添加一个名为output的动态文本字段。

我们将编写一个应用程序,监听地理位置数据的可用性,并将任何更改报告到output文本字段。

如何操作...

执行以下步骤:

  1. 创建一个名为Main的文档类。

  2. 添加以下导入语句和一个类型为Geolocation的成员变量:

    package {
    import flash.display.MovieClip;
     import flash.events.GeolocationEvent;
    import flash.events.StatusEvent;
    import flash.sensors.Geolocation; 
    public class Main extends MovieClip {
    private var geo:Geolocation; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在构造函数中,创建一个Geolocation对象并监听它发出GeolocationEvent.UPDATEStatusEvent.STATUS

    public function Main() {
     output.text = "Obtaining location...";
    if(Geolocation.isSupported)
    {
    geo = new Geolocation();
    geo.setRequestedUpdateInterval(1000);
    geo.addEventListener(GeolocationEvent.UPDATE, geoUpdated);
    geo.addEventListener(StatusEvent.STATUS, statusUpdated);
    }
    else
    {
    output.text = "Geolocation is not supported.";
    } 
    }
    
    
  4. 最后,为每个事件添加处理程序:

    private function geoUpdated(e:GeolocationEvent):void {
    output.text = "Location received.";
    }
    private function statusUpdated(e:StatusEvent):void {
    if(e.code == "Geolocation.Muted")
    {
    output.text = "Geolocation access denied.";
    }
    }
    
    
  5. 将类文件保存为Main.as

  6. 保存 FLA 文件并发布它。安装 IPA 文件并在您的设备上启动它。

    将出现一个带有以下提示的原生 iOS 对话框:

    "c9 r3" 希望使用您的当前位置

  7. 点击不允许按钮以拒绝应用程序访问设备的地理位置数据。

    屏幕上会出现以下文本:

    获取位置...

    它将很快被替换为:

    地理位置访问被拒绝。

  8. 现在重新启动应用程序。如果您使用 iOS 4 或更高版本,您的先前设置将被记住,并且对地理位置数据的访问将再次被拒绝。如果您使用的是 iOS 的早期版本,那么每次都会提示您授权访问。

    小贴士

    要在 iOS 4 或更高版本中重新启动应用程序,您首先需要使用快速应用程序切换器将其终止。有关如何操作的详细信息,请参阅第三章中的优雅地退出应用程序菜谱。

    • 在运行 iOS 4 或更高版本的设备上,可以从设备的设置中更改应用程序的访问权限。让我们为我们的应用程序做这件事。
  9. 通过按主按钮退出应用程序。从设备的设置中,转到位置服务。您将看到一个列表,其中包含尝试访问位置数据的应用程序。向下滚动,直到找到c9 r3。点击旁边的按钮以允许访问它。如何操作...

  10. 现在返回主屏幕并再次启动此菜谱的应用程序。

    这次您将看到以下文本:

    获取位置...

    它将很快被替换为:

    位置已接收。

它是如何工作的...

当用户阻止 AIR for iOS 应用程序访问位置数据时,GeolocationEvent.UPDATE事件将停止,并且从Geolocation对象发出StatusEvent.STATUS。因此,只需监听STATUS事件即可确定何时撤销对位置数据的访问:

geo = new Geolocation();
geo.setRequestedUpdateInterval(1000);
geo.addEventListener(GeolocationEvent.UPDATE, geoUpdated);
geo.addEventListener(StatusEvent.STATUS, statusUpdated);

statusUpdated()处理程序中执行最终检查:

private function statusUpdated(e:StatusEvent):void {
if(e.code == "Geolocation.Muted")
{
output.text = "Geolocation access denied.";
}
}

在这个方法中,我们查询StatusEvent对象的code属性。如果它的字符串值为Geolocation.Muted,那么我们知道不再可以访问地理位置数据。

最后,尽管这个示例中没有使用,但你也可以访问Geolocation.muted属性以确定地理位置数据是否可用。当一个新安装的应用程序首次启动时,muted将被设置为true,直到用户从原生 iOS 对话框中授予权限。

关于flash.events.StatusEvent的更多信息可以在 Adobe 社区帮助中找到。

参见

  • 确定你的当前位置

响应加速度计变化

加速度计提供了访问表示设备在三维轴上位置或移动的数据。当检测到运动时,它作为数据返回,可以通过 ActionScript 访问。

这个食谱将向你展示如何利用 iOS 设备中发现的加速度计。

准备工作

已提供一个 FLA 文件作为起点。

将书附带代码包中的chapter9\recipe4\recipe.fla文件打开到 Flash Professional 中。

你将在舞台上找到五个动态文本字段,它们下方是一个实例名为arrow的电影剪辑。我们将用从设备加速度计检索到的数据填充每个文本字段,并将电影剪辑旋转以反映设备方向的物理变化。

此外,请注意舞台的尺寸设置为 480x320。对于这个食谱,将使用横屏方向。

如何操作...

执行以下步骤以监听和响应加速度计变化:

  1. 创建一个文档类并将其命名为Main

  2. 添加以下两个导入语句和一个类型为Accelerometer的成员变量:

    package {
    import flash.display.MovieClip;
     import flash.events.AccelerometerEvent;
    import flash.sensors.Accelerometer; 
    public class Main extends MovieClip {
    private var acc:Accelerometer; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在构造函数中,实例化一个Accelerometer对象并监听它的更新:

    public function Main() {
     if(Accelerometer.isSupported)
    {
    acc = new Accelerometer();
    acc.setRequestedUpdateInterval(50);
    acc.addEventListener(AccelerometerEvent.UPDATE, accUpdated);
    } 
    }
    
    
  4. 最后,编写一个事件处理程序以获取和使用更新的加速度计数据:

    private function accUpdated(e:AccelerometerEvent):void {
    var radians:Number = Math.atan2(e.accelerationY, e.accelerationX);
    var degrees:Number = (radians * (180 / Math.PI)) - 90;
    arrow.rotation = -degrees;
    accXField.text = e.accelerationX.toString();
    accYField.text = e.accelerationY.toString();
    accZField.text = e.accelerationZ.toString();
    timeField.text = e.timestamp.toString();
    rotField.text = degrees.toString();
    }
    
    
  5. 将类文件保存为Main.as

  6. 此外,保存你的 FLA 文件,然后发布它。将应用安装到你的设备上并启动它。

当设备的运动传感器检测到活动时,文本字段将更新。将设备放在自己面前并顺时针和逆时针倾斜将更新arrow电影剪辑的旋转,确保它始终向上指。

它是如何工作的...

我们通过创建Accelerometer类的实例并监听它分发AccelerometerEvent.UPDATE事件来访问加速度计的数据:

acc = new Accelerometer();
acc.setRequestedUpdateInterval(50);
acc.addEventListener(AccelerometerEvent.UPDATE, accUpdated);

接收UPDATE事件的频率可以通过调用Accelerometer.setRequestedUpdateInterval()方法来设置。您可以在之前的代码中看到这一点,我们请求每 50 毫秒更新一次。这仅作为对设备的提示,意味着实际更新之间的时间可能大于或小于您的请求。省略此调用将导致设备使用默认的更新间隔。默认间隔可以是毫秒到秒之间的任何值,具体取决于设备的硬件能力。

UPDATE事件是一个AccelerometerEvent对象,并提供访问以下属性:

  • accelerationX —沿 x 轴的加速度。当设备直立时,x 轴从左到右运行。如果设备向右移动,加速度为正。

  • accelerationY—沿 y 轴的加速度。当设备直立时,y 轴从底部到顶部运行。如果设备向上移动,加速度为正。

  • accelerationZ—沿 z 轴的加速度。如果设备移动到使其面向上方的位置,加速度为正。如果设备面向地面,加速度为负。

  • timestamp —自应用程序启动以来经过的毫秒数。

提示

加速度以“g”为单位进行测量,其中 1g 是标准重力加速度,大约为每秒 9.8 米。

我们在accUpdated()处理程序中获取这些属性,并将它们写入我们的动态文本字段:

accXField.text = e.accelerationX.toString();
accYField.text = e.accelerationY.toString();
accZField.text = e.accelerationZ.toString();
timeField.text = e.timestamp.toString();

此外,accelerometerXaccelerometerY属性用于计算设备被持有的角度(屏幕朝向您)。这用于更新arrow电影剪辑的旋转。以下是执行此操作的代码:

var radians:Number = Math.atan2(e.accelerationY, e.accelerationX);
var degrees:Number = (radians * (180 / Math.PI)) - 90;
arrow.rotation = -degrees;

知道设备倾斜的角度对于许多应用很有用。特别是游戏,其中倾斜设备可能用于在平台上移动角色或模拟方向盘的运动。

最后,在构造函数中,注意使用静态只读属性Accelerometer.isSupported来检查加速度计的可用性。加速度计在所有现有的 iOS 设备上都受支持,但未来设备不一定保证。因此,检查支持是一个好习惯,并且在编写跨平台代码时也有益。

还有更多...

以下是一些有关加速度计及其数据处理的更多信息。

方向和加速度计轴

加速度计轴的重新定向与设备的显示方向而不是设备的物理方向一致。换句话说,当自动方向检测处于活动状态时,y 轴将垂直,当在正常直立位置查看显示内容时。这对默认为纵向宽高比的应用程序和默认为横向宽高比的应用程序都适用。然而,如果自动方向检测未激活,则当设备旋转时,加速度计轴不会重新定向。

确定设备方向

加速度计的数据受重力影响,可用于确定设备的当前方向。以下是需要检查的值:

  • accelerationX > 0.5—逆时针旋转 90 度

  • accelerationX < -0.5—顺时针旋转 90 度

  • accelerationY > 0.5—正常直立位置

  • accelerationY < -0.5—颠倒

  • accelerationZ > 0.5—向上面对

  • accelerationZ < -0.5—向下面对

这为通过监听从舞台派发的 StageOrientationEvent 对象来确定方向提供了另一种方法。此外,使用加速度数据使得确定设备屏幕显示是向上还是朝向地面成为可能。

应用低通滤波器

加速度计的数据受重力和运动突然变化的影响。如果您使用这些数据来检测设备的方向,那么您应该通过应用低通滤波器从数据中隔离重力分量。

这可以通过随时间平滑数据来实现。为此,首先创建一个滤波因子和三个成员变量来存储每个轴的先前值:

private const FACTOR:Number = 0.1;
private var accX:Number = 0;
private var accY:Number = 0;
private var accZ:Number = 0;

现在针对每个 AccelerometerEvent.UPDATE 事件,应用低通滤波器以保留每个轴的仅重力分量:

accX = (e.accelerationX * FACTOR) + (accX * (1 - FACTOR));
accY = (e.accelerationY * FACTOR) + (accY * (1 - FACTOR));
accZ = (e.accelerationZ * FACTOR) + (accZ * (1 - FACTOR));

本质上,此代码为每个轴生成一个值,该值使用其当前数据的 10%和先前过滤数据的 90%。这将确保数据对突然和短暂的运动变化响应缓慢。

应用高通滤波器

许多类型的应用程序使用加速度计数据来检测运动的突然变化。高通滤波器可以用来隔离由运动突然变化引起的数据部分。

与低通滤波器的实现类似,使用一个滤波因子和三个成员变量来存储每个轴的先前值。然后在每个 AccelerometerEvent.UPDATE 事件响应中应用过滤器:

accX = e.accelerationX - ((e.accelerationX * FACTOR) + (accX * (1 - FACTOR)));
accY = e.accelerationY - ((e.accelerationY * FACTOR) + (accY * (1 - FACTOR)));
accZ = e.accelerationZ - ((e.accelerationZ * FACTOR) + (accZ * (1 - FACTOR)));

在此示例中,为每个轴计算一个低通滤波器值,并将其从当前值中减去。这样做可以保留运动的突然变化,同时移除重力分量。

“muted”属性

Accelerometer 类有一个名为 muted 的静态只读属性。它用于确定用户是否已授予应用程序访问加速度计数据的权限。在 iOS 中,此属性不是必需的,因为目前没有方法拒绝应用程序访问加速度计。

参见

  • 设置默认纵横比,第八章

  • 启用自动方向,第八章

  • 响应方向变化,第八章

检测摇晃

加速度计的常见用途是检测摇晃,这已成为游戏和应用程序中的一种流行交互方法。例如,许多随 iOS 提供的应用程序允许用户通过摇晃设备来执行撤销操作。

此配方将向您展示如何通过检查来自加速度计的数据来确定用户是否在摇晃设备。

准备工作

从本书的配套代码包中,将 chapter9\recipe5\recipe.fla 打开到 Flash Professional 中。

您将在舞台中心找到一个名为 shake 的电影剪辑。其时间轴由两个关键帧组成。

我们将编写一些 ActionScript 代码,以响应设备三个轴上的变化来移动剪辑。当运动明显时,我们将通过跳转到电影剪辑的第二帧来向用户指示已检测到摇晃。

本配方中舞台使用的是横向纵横比。

如何实现...

执行以下步骤来检测摇晃:

  1. 创建一个文档类并命名为 Main.

  2. 导入与加速度计一起工作的类,并添加以下成员变量:

    package {
    import flash.display.MovieClip;
     import flash.events.AccelerometerEvent;
    import flash.sensors.Accelerometer; 
    public class Main extends MovieClip {
     private const THRESHOLD:Number = 0.8;
    private var acc:Accelerometer;
    private var prevX:Number;
    private var prevY:Number;
    private var prevZ:Number;
    private var startX:Number;
    private var startY:Number; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 初始化成员变量和 shake 电影剪辑。同时,实例化一个 Accelerometer 对象并监听它派发的 UPDATE 事件:

    public function Main() {
     prevX = prevY = prevZ = 0;
    shake.gotoAndStop(1);
    startX = shake.x;
    startY = shake.y;
    if(Accelerometer.isSupported)
    {
    acc = new Accelerometer();
    acc.setRequestedUpdateInterval(50);
    acc.addEventListener(AccelerometerEvent.UPDATE, accUpdated);
    } 
    }
    
    
  4. 添加 UPDATE 事件的处理器:

    private function accUpdated(e:AccelerometerEvent):void {
    var changeX:Number = prevX - e.accelerationX;
    var changeY:Number = prevY - e.accelerationY;
    var changeZ:Number = prevZ - e.accelerationZ;
    prevX = e.accelerationX;
    prevY = e.accelerationY;
    prevZ = e.accelerationZ;
    shake.x = startX + (changeX * 100);
    shake.y = startY + (changeY * 100);
    shake.z = (changeZ * 100);
    if(Math.abs(changeX) > THRESHOLD || Math.abs(changeY) > THRESHOLD || Math.abs(changeZ) > THRESHOLD)
    {
    shake.gotoAndStop(2);
    }
    else
    {
    shake.gotoAndStop(1);
    }
    }
    
    
  5. 保存类文件,并在提示时将其命名为 Main.as

  6. 现在保存 FLA 文件并发布它。在您的设备上测试应用程序。

轻轻摇晃设备会将电影剪辑从屏幕中心移开。更剧烈的动作也会改变其外观,表明检测到了足够大的摇晃。

它是如何工作的...

此示例将当前加速度数据与之前的数据进行比较,以查看是否发生了足够大的变化。

前一个加速度数据存储在 prevX, prevYprevZ 成员变量中,并与当前数据比较以确定每个轴的变化:

var changeX:Number = prevX - e.accelerationX;
var changeY:Number = prevY - e.accelerationY;
var changeZ:Number = prevZ - e.accelerationZ;
prevX = e.accelerationX;
prevY = e.accelerationY;
prevZ = e.accelerationZ;

如果三个轴中的任何一个轴的变化足够大,那么可以安全地假设设备正在被摇晃。通过将 shake 电影剪辑移动到第二帧,将此信息反馈给用户。以下是实现此功能的代码:

if(Math.abs(changeX) > THRESHOLD || Math.abs(changeY) > THRESHOLD || Math.abs(changeZ) > THRESHOLD)
{
shake.gotoAndStop(2);
}
else
{
shake.gotoAndStop(1);
}

THRESHOLD 常量简单地规定了任何轴上需要发生的变化量,以便将运动视为摇晃。降低此值将减少用户触发摇晃所需的努力,而增加它将使其更难。

为了提供更大的视觉反馈,我们还根据加速度计的变化更新了shake电影剪辑的x, yz位置。摇晃动作越剧烈,剪辑与其原始起始位置的距离就越大:

shake.x = startX + (changeX * 100);
shake.y = startY + (changeY * 100);
shake.z = (changeZ * 100);

在构造函数中初始化并设置为shake电影剪辑原始位置的startXstartY成员变量。

在本例中,大部分工作是在accUpdated()事件处理程序中完成的,该处理程序在每次从Accelerometer对象发出AccelerometerEvent.UPDATE时被调用。为了确保应用响应,会调用setRequestedUpdateInterval()方法请求频繁更新。

更多内容...

让我们看看一些选项,以进一步改进这个示例的配方。

检查多个轴

在决定用户正在摇晃设备之前,我们只检查了一个轴的足够大的变化。另一种方法是等待三个轴中的两个轴有显著变化。这个代码看起来如下:

var changeX:Number = Math.abs(e.accelerationX);
var changeY:Number = Math.abs(e.accelerationY);
var changeZ:Number = Math.abs(e.accelerationZ);
if((changeX > THRESHOLD && changeY > THRESHOLD) || (changeX > THRESHOLD && changeZ > THRESHOLD) || (changeY > THRESHOLD && changeZ > THRESHOLD))
{
// Shake detected.
}

对于多个轴,你可能需要稍微降低THRESHOLD值,以补偿用户必须做出更夸张的动作才能启动摇晃的事实。

平滑加速度计数据

你可能已经注意到,即使手持设备不动,shake电影剪辑也会轻微颤抖。加速度计并不完全准确,返回的数据将包含一些噪声。

这种噪声可以通过在数据上应用高通滤波器随时间减少,这在响应加速度计变化配方中有详细说明。尝试调整滤波因子和阈值常数,直到找到让你满意的结果。

参见

  • 响应加速度计变化

第十章。相机和麦克风支持

在本章中,我们将介绍:

  • 保存到相机胶卷

  • 从相机胶卷读取

  • 使用默认相机应用进行捕获

  • 使用内置相机

  • 录制麦克风音频

  • 播放录制的音频

简介

相机和麦克风可能是 iOS 设备中内置的最受欢迎的两个传感器。实际上,iPhone 用户在打电话时每天都会依赖麦克风。使用 Apple 的 FaceTime 的人依赖于麦克风和相机来保持联系。当然,每个人都会时不时地拍照或拍摄视频。

开发者正在发现越来越复杂的传感器用途,这些用途远远超出了 Apple 预装应用程序的功能。图像和语音识别、增强现实、语言翻译和语音扭曲只是其中的一小部分。

Adobe 在 AIR 2.6 中引入了对相机和麦克风的支持,允许 Flash 开发者在其应用程序中利用这两个传感器。虽然您可以使用 Flash Professional CS5.5 完成本章的所有食谱,但使用 Flash Professional CS5 的用户将仅限于第一个食谱,保存到相机胶卷

保存到相机胶卷

许多 iOS 应用程序允许用户将图像保存到相机胶卷。绘图工具和头像创建者是流行的例子,用户可以轻松地从设备的原生照片库中向朋友和家人展示他们的创作。

这个食谱将向您展示如何将舞台的快照保存到设备的相机胶卷。

准备工作

从本书的配套代码包中,将 chapter10\recipe1\recipe.fla 打开到 Flash Professional 中。

您将在舞台上找到两个位图和一个动画剪辑。这些位图已被合成为背景图像,我们将将其保存到相机胶卷。动画剪辑代表一个按钮,当按下时将启动保存操作。

按钮动画剪辑的实例名称为 saveBtn,其库符号链接到一个名为 Button 的类。这个类是在 第四章 的 处理用户交互 食谱中引入的。

好的,让我们编写一些代码。

如何操作...

我们将使用 AIR 的 CameraRoll 类来完成这个食谱。

  1. 创建一个文档类并命名为 Main

  2. 添加以下导入语句和一个类型为 CameraRoll: 的成员变量:

    package {
    import flash.display.BitmapData; 
    import flash.display.MovieClip;
     import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.media.CameraRoll; 
    public class Main extends MovieClip {
    private var cameraRoll:CameraRoll; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在构造函数中,创建一个 CameraRoll 对象并监听它分发 Event.COMPLETE。同时监听从 saveBtn 动画剪辑分发的 MouseEvent.MOUSE_UP

    public function Main() {
     cameraRoll = new CameraRoll();
    cameraRoll.addEventListener(Event.COMPLETE, saved);
    saveBtn.addEventListener(MouseEvent.MOUSE_UP, pressed); 
    }
    
    
  4. 当按下保存按钮时,我们将把舞台的位图图像添加到相机胶卷。为了防止按钮出现在捕获的位图图像中,我们首先将其隐藏。添加一个 pressed() 事件处理程序:

    private function pressed(e:MouseEvent):void {
    saveBtn.visible = false;
    var bitmapData:BitmapData = new BitmapData(
    stage.stageWidth, stage.stageHeight, false);
    bitmapData.draw(stage);
    if(CameraRoll.supportsAddBitmapData)
    {
    cameraRoll.addBitmapData(bitmapData);
    }
    }
    
    
  5. 一旦位图成功添加到相机胶卷,我们将再次使按钮可见。为此编写一个 saved() 事件处理程序:

    private function saved(e:Event):void {
    saveBtn.visible = true;
    }
    
    
  6. 保存类,并在提示时将文件命名为 Main.as

  7. 返回到您的 FLA。

  8. 发布应用并将其部署到您的设备上。

  9. 启动应用并按保存按钮。转到照片应用,您将看到您的图片已保存到相册中,如下面的截图所示:

如何操作...

它是如何工作的...

CameraRoll 类允许访问设备的照片库,属于 flash.media 包。

调用 CameraRoll.addBitmapData() 方法会将指定的位图保存到设备上。在保存成功后,会分发 Event.COMPLETE 事件。

对于这个菜谱,我们创建并传递了一个 BitmapData 对象到 addBitmapData() 方法。BitmapData 对象包含了一个由调用 BitmapData.draw() 方法并传递 stage 属性给它创建的舞台位图表示。

静态属性 CameraRoll.supportsAddBitmapData 也被使用了。它决定了是否支持将位图数据保存到目标平台的设备相册中。尽管这个属性对所有 iOS 设备都返回 true,但在编写跨平台代码时进行检查是明智的。

还有更多...

在保存到相册时,以下信息将对您有所帮助。

处理保存失败

不要假设位图总是会成功保存到相册中。例如,设备可能没有足够的存储空间。

当无法添加位图时,CameraRoll 对象将分发 ErrorEvent.ERROR。查询 ErrorEvent 对象的 text 属性可以检索与错误相关的消息。

您的代码应该监听此事件并处理任何添加位图数据失败的尝试。在 Adobe Community Help 中搜索 flash.media.CameraRoll 以获取可能的错误列表。

保存特定显示对象

尽管我们在这个菜谱中抓取了整个舞台,但您也可以创建任何显示对象的位图图像并将其添加到相册中。只需创建一个 BitmapData 对象并调用它的 draw() 方法,将您的目标显示对象作为参数传递。BitmapData 对象的尺寸应与您的显示对象相匹配。

视频和相册

目前,AIR SDK 不提供将视频内容添加到相册的支持。

参见

  • 从相册读取

从相册读取

根据您使用的 AIR SDK 版本,您可能可以从设备的相册中加载图片。AIR for iOS 通过启动原生照片应用并允许用户选择图片来简化这一过程。然后,图片可以被加载并添加到您的显示列表中。

让我们看看如何编写一个简单的应用程序,该程序可以加载从相册中选择的图片。

这里介绍的方法仅适用于使用 Flash Professional CS5.5 的用户。Flash Professional CS5 使用的 AIR 2.0 SDK 没有提供从相册加载图片的 API。

准备工作

已提供一个 FLA 作为此菜谱的起点。从本书的配套代码包中,打开 chapter10\recipe2\recipe.fla 到 Flash Professional CS5.5。

在舞台上可以找到一个实例名为 browseBtn 的动画剪辑。该剪辑的库符号链接到一个名为 Button 的类,该类在第四章的 处理用户交互 菜谱中介绍。

准备中

让我们编写一些代码,以便在按下 browseBtn 动画剪辑后让用户浏览并从相册中加载图片。

如何操作...

我们将使用几个类,包括 CameraRoll, LoaderMediaPromise

  1. 创建一个文档类,并将其命名为 Main

  2. 导入所需的类并添加两个成员变量——一个为 CameraRoll 类型,另一个为 Loader 类型:

    package {
     import flash.display.Loader; 
    import flash.display.MovieClip;
     import flash.events.Event;
    import flash.events.MediaEvent;
    import flash.events.MouseEvent;
    import flash.media.CameraRoll;
    import flash.media.MediaPromise; 
    public class Main extends MovieClip {
     private var cameraRoll:CameraRoll;
    private var loader:Loader; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 实例化一个 CameraRoll 对象,并监听它分发 MediaEvent.SELECTEvent.CANCEL 事件。同时,监听 browseBtn 动画剪辑被按下:

    public function Main() {
     cameraRoll = new CameraRoll();
    cameraRoll.addEventListener(MediaEvent.SELECT,
    photoSelected);
    cameraRoll.addEventListener(Event.CANCEL, cancelled);
    browseBtn.addEventListener(MouseEvent.MOUSE_UP,
    buttonPressed); 
    }
    
    
  4. 当按下 browseBtn 动画剪辑时,我们将将其从视图中隐藏,并启动原生的照片应用。添加以下方法来处理此操作:

    private function buttonPressed(e:MouseEvent):void {
    browseBtn.visible = false;
    if(CameraRoll.supportsBrowseForImage)
    {
    cameraRoll.browseForImage();
    }
    }
    
    
  5. 如果用户从照片应用中取消,我们将再次使 browseBtn 动画剪辑可见:

    private function cancelled(e:Event):void {
    browseBtn.visible = true;
    }
    
    
  6. 如果用户做出选择,则我们将创建一个 Loader 对象并开始加载照片。添加 photoSelected() 方法来处理此操作:

    private function photoSelected(e:MediaEvent):void {
    var photoPromise:MediaPromise = e.data;
    loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE,
    photoLoaded);
    loader.loadFilePromise(photoPromise);
    }
    
    
  7. 最后,编写 photoLoaded() 事件处理程序,当照片的图像成功加载时将被调用。此方法将在将图像添加到显示列表之前调整图像大小和方向:

    private function photoLoaded(e:Event):void {
    var mc:Loader = e.currentTarget.loader as Loader;
    var scale:Number;
    if(mc.width > mc.height)
    {
    scale = stage.stageHeight / mc.width;
    mc.scaleX = scale;
    mc.scaleY = scale;
    mc.x = stage.stageWidth;
    mc.rotation = 90;
    addChild(mc);
    }
    else
    {
    scale = stage.stageWidth / mc.width;
    mc.scaleX = scale;
    mc.scaleY = scale;
    addChild(mc);
    }
    }
    
    
  8. 保存类并在提示时将文件命名为 Main.as

  9. 然后,返回到您的 FLA 并保存它。

  10. 发布 FLA 并将生成的 .ipa 文件部署到您的设备。

  11. 启动应用程序,点击 BROWSE 按钮,然后从相册中选择一张图片。您的应用程序将加载并显示该图片。

它是如何工作的...

flash.media.CameraRoll 类允许访问设备的照片库。

它的 browseForImage() 方法打开原生的照片应用,允许用户从设备的相册中选择一张图片。在此点,您的应用程序将失去焦点并在后台等待。

当用户做出选择时,您的应用程序将重新获得焦点,并且 CameraRoll 对象将分发 MediaEvent.SELECT 事件。然而,如果用户从照片应用中取消,则将分发 Event.CANCEL 事件。

在此菜谱中,当用户按下 BROWSE 按钮时调用 browseForImage() 方法。然而,在调用之前,将检查静态 CameraRoll.supportsBrowseForImage 属性。这决定了目标平台是否支持浏览图片。尽管该属性对所有 iOS 设备返回 true,但在针对多个平台时很有用。

一旦用户选择了图像,photoSelected() 事件处理器就会被调用,并将一个 MediaEvent 对象传递给它。从 MediaEvent 对象中,我们通过查询其 data 属性来检索有关所选图像的信息。这返回一个 MediaPromise 对象,我们将其传递给 Loader 对象的 loadFilePromise() 方法以实际加载图像。一旦完成,Loader 对象将派发 Event.COMPLETE 事件。

photoLoaded() 处理器捕获 Loader 对象的 COMPLETE 事件并在屏幕上显示实际图像。保存到相册的图像分辨率可能远高于舞台尺寸,可以是纵向或横向。photoLoaded() 方法将图像缩放到适合舞台大小,如果它具有横向宽高比,则将其旋转 90 度。

小贴士

MediaPromise 类还提供了一个 file 属性,可以用来获取所选相册图像的 URL。虽然这个属性在某些平台(如 Android)上是有效的,但在 iOS 上它始终返回 null。在编写跨平台代码时,使用 Loader.loadFilePromise() 而不是尝试获取并传递 URL 到 Loader.load()

你可以从 Adobe 社区帮助中获取有关 flash.media.CameraRollflash.media.MediaPromise 的更多信息。

更多信息...

当将照片保存到设备时,iOS 会将额外的元数据嵌入到图片中。根据你正在编写的应用程序,以下信息可能有用。

解析 Exif 数据

在 iOS 设备上拍摄的照片遵循 可交换图像文件 (Exif) 格式,并可以包含缩略图数据和附加信息的标签。这些标签可以描述从与图像关联的 GPS 坐标到其方向等任何内容。

虽然 AIR SDK 并不直接提供对这些标签的支持,但有一些第三方解析器可用。请参阅 code.shichiseki.jp/as3/ExifInfowww.mxml.it/index.php/2010/01/04/reading-exif-data-with-actionscript-30。此外,Exif 规范可以在 www.exif.org/exif2-2.pdf 找到。

相关内容

  • 保存到相册

使用默认相机应用捕获

大多数 iOS 设备都内置了相机。较新的型号有两个——一个安装在后面,另一个安装在前面。用户可以使用预装的相机应用拍摄照片和录制视频。第三方应用程序也可以使用相机,许多应用程序只是简单地启动默认的相机应用来完成这个目的。一旦用户完成相机操作,第三方应用就能访问所拍摄的照片或视频。

AIR 2.6 及以上版本提供了CameraUI类,使其能够启动并使用默认的相机应用。本教程将向您展示如何从 Flash Professional CS5.5 中完成此操作。AIR 2.0 和 Flash CS5 不提供相机支持。

准备工作

您需要一个具有相机的设备。第四代 iPod touch、iPad 2 以及所有型号的 iPhone 都配备了相机。

从本书的配套代码包中,将chapter10\recipe3\recipe.fla文件打开到 Flash Professional CS5.5 中。

您将在舞台上找到一个名为captureBtn的电影剪辑和一个名为output的动态文本字段。按钮剪辑的库符号链接到一个名为Button的类,该类在第四章的处理用户交互教程中介绍过。第四章。

我们将创建一个简单的应用,当按钮被按下时启动默认的相机应用,允许用户捕获照片。

如何操作...

让我们编写完成此操作的 ActionScript 代码。

  1. 创建一个名为Main的文档类。

  2. 导入此教程所需的各个类,并创建一个类型为CameraUI的成员变量:

    package {
    import flash.display.MovieClip;
     import flash.events.Event;
    import flash.events.MediaEvent;
    import flash.events.MouseEvent;
    import flash.media.CameraUI;
    import flash.media.MediaPromise;
    import flash.media.MediaType; 
    public class Main extends MovieClip {
    private var camera:CameraUI;
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在构造函数中,实例化一个CameraUI对象,并监听它触发MediaEvent.COMPLETEEvent.CANCEL事件。同时,监听用户按下captureBtn电影剪辑:

    public function Main() {
     camera = new CameraUI();
    camera.addEventListener(MediaEvent.COMPLETE, captured);
    camera.addEventListener(Event.CANCEL, cancelled);
    captureBtn.addEventListener(MouseEvent.MOUSE_UP, pressed);
    } 
    
    
  4. 当按钮被按下时,我们将启动相机应用,允许用户拍照。为此添加一个pressed()事件处理程序:

    private function pressed(e:MouseEvent):void {
    if(CameraUI.isSupported)
    {
    camera.launch(MediaType.IMAGE);
    }
    }
    
    
  5. 当用户从相机应用返回时,我们将检查照片是否成功获取,并将确认信息写入output文本字段。通过在您的类中添加一个captured()方法来处理此操作:

    private function captured(e:MediaEvent):void {
    var mediaPromise:MediaPromise = e.data;
    if(mediaPromise != null)
    {
    output.text = "Photo captured.";
    }
    }
    
    
  6. 用户可以从默认的相机应用中取消操作,丢弃他们可能已经拍摄的照片。为此添加一个事件处理程序,在output文本字段中说明操作已取消:

    private function cancelled(e:Event):void {
    output.text = "Cancelled.";
    }
    
    
  7. 保存类并在提示时将文件命名为Main.as

  8. 返回到您的 FLA 文件并保存它。

  9. 将 IPA 部署到您的设备后,发布应用并启动它。

  10. 点击CAPTURE按钮以启动默认的相机应用。拍照后,点击Use按钮。将显示一条消息,确认照片已成功捕获,现在可以通过您的应用访问。

工作原理...

flash.media.CameraUI类允许访问默认的相机应用。调用其launch()方法将打开相机应用,并允许用户捕获图片或视频。在此阶段,您的应用将失去焦点并等待在后台。一旦用户完成,您的应用将重新获得焦点,CameraUI对象将触发MediaEvent.COMPLETE事件。如果用户取消相机应用,则将触发Event.CANCEL事件。

在调用launch()时,您必须传递由flash.media.MediaType定义的常量,指定您是想拍照还是拍摄视频。在本教程中,我们传递了MediaType.IMAGE

通过COMPLETE事件的MediaEvent对象的data属性访问捕获的媒体。该属性是MediaPromise类的一个实例,可以用来加载图像甚至访问其数据。

注意在pressed()事件处理程序中使用静态isSupported属性。它确定当前运行您的应用程序的设备是否支持访问默认相机应用程序。

您可以从 Adobe 社区帮助中获取有关flash.media.CameraUIflash.media.MediaPromise的更多信息。

还有更多...

以下信息将有助于完善您的理解。

处理错误

如果默认相机应用程序已经在使用中,CameraUI对象将派发一个错误。您可以通过监听flash.events.ErrorEvent.ERROR来捕获此事件。查询ErrorEvent对象的errorIDtext属性以了解更多关于错误的信息。

显示捕获的图像

我们并没有走那么远,实际上加载并显示使用默认相机应用程序拍摄的照片。这可以通过创建一个Loader对象并将照片的MediaPromise对象传递给加载器的loadFilePromise()方法来实现。有关更多详细信息,请参阅前面的配方,从相机胶卷读取

将捕获的图像保存到相机胶卷

与一些其他移动操作系统不同,iOS 实际上并不在相机胶卷中存储捕获的照片。如果您想让照片出现在相机胶卷中,您需要手动添加它。这可以通过使用Loader对象来加载您的MediaPromise对象的二进制数据,然后使用CameraRoll实例将其位图数据写入相机胶卷来实现。

请参阅本章前面部分的从相机胶卷读取保存到相机胶卷配方。

捕获视频

虽然我们使用默认相机应用程序捕获了一张照片,但只需简单的代码更改就可以拍摄视频。您可以在以下代码片段中看到这一点,其中MediaType.VIDEO被传递到CameraUI对象的launch()方法中:

camera.launch(MediaType.VIDEO);

在使用从 AIR 启动的默认相机应用程序时,用户无法在照片和相机模式之间切换。您只能在任何时候使用相机应用程序捕获单一媒体类型。

查看第十二章的播放本地 H.264 视频配方,了解如何播放您捕获的视频。第十二章。

读取捕获的数据

也可以直接访问代表从相机捕获的图像或视频的二进制数据。这对于可能需要直接将媒体写入设备文件系统、上传数据到服务器或以某种方式解析或修改数据的应用程序非常有用。MediaPromise对象提供了一个open()方法,可以用来访问数据。然后你可以将其读入一个ByteArray对象中。

要在这个配方示例中实现这一点,请添加以下成员变量:

private var dataSource:IDataInput;
private var eventSource:IEventDispatcher;

captured()事件处理器的末尾添加以下代码片段:

dataSource = mediaPromise.open();
eventSource = dataSource as IEventDispatcher;
eventSource.addEventListener(Event.COMPLETE, dataCaptured);

现在编写一个事件处理程序,将数据复制到ByteArray对象中:

private function dataCaptured(e:Event):void {
var mediaBytes:ByteArray = new ByteArray();
dataSource.readBytes(mediaBytes);
}

还需包含以下导入语句:

import flash.events.IEventDispatcher;
import flash.utils.ByteArray;
import flash.utils.IDataInput;

您现在可以在dataCaptured()方法中访问媒体的二进制数据。

参见

  • 保存到相册

  • 从相册读取

  • 使用内置摄像头

使用内置摄像头

虽然启动和使用默认的摄像头应用为用户提供了一个他们熟悉的原生摄像头体验,但这可能不适合所有类型的应用。除了CameraUI之外,AIR 还提供了Camera类,该类接收设备内置摄像头捕获的视频数据,允许您直接在您的应用中显示。

在这个配方中,您将学习如何使用 Flash Professional CS5.5 从摄像头接收视频流并在您的应用中显示它。Camera类在 Flash CS5 和 AIR 2.0 for iOS 中不受支持。

准备工作

您需要一个带有摄像头的设备。第四代 iPod touch、iPad 2 以及所有型号的 iPhone 都配备了摄像头。

从书籍的配套代码包中,将chapter10\recipe4\recipe.fla文件打开到 Flash Professional CS5.5 中。

阶段已设置了一个景观宽高比,并且这一设置也反映在 FLA 的 iOS 设置中。

如何做到这一点...

按照以下步骤从摄像头接收视频并在舞台上显示:

  1. 创建一个文档类并命名为Main

  2. 声明两个成员变量——一个类型为Camera,另一个类型为Video

    package {
    import flash.display.MovieClip;
     import flash.media.Camera;
    import flash.media.Video; 
    public class Main extends MovieClip {
    private var camera:Camera; 
    private var video:Video; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在构造函数中,获取设备默认摄像头的引用并将其附加到一个Video对象上。同时,将Video对象添加到舞台上,以便用户可以查看视频数据:

    public function Main() {
     if(Camera.names.length > 0)
    {
    camera = Camera.getCamera();
    camera.setMode(stage.stageWidth, stage.stageHeight,
    stage.frameRate);
    video = new Video(camera.width, camera.height);
    video.attachCamera(camera);
    addChild(video);
    } 
    }
    
    
  4. 将类保存为Main.as。然后返回到您的 FLA 并保存它。

  5. 发布 FLA 并在您的设备上测试它。

  6. 将设备保持为横屏方向。后置摄像头的视频将被渲染到屏幕上。

它是如何工作的...

flash.media.Camera类是一个单例,这意味着只能存在一个实例。为了保证这一点,该类没有公共构造函数。相反,通过调用Camera类的getCamera()静态方法来获取对摄像头的访问,该方法为您返回一个可以与之工作的Camera实例。

一旦获取到Camera实例,就可以指定摄像头要使用的捕获模式。这是通过调用setMode()方法并传递一个宽度、高度和目标帧率来完成的。对于这个配方,我们传递了舞台的尺寸和帧率。如果摄像头无法满足指定的要求,它将使用最接近的模式。

为了显示从摄像头流出的实时视频,它必须附加到一个Video对象上。flash.media.Video类继承自DisplayObject,允许任何Video对象被添加到显示列表中。首先创建一个Video对象,并将宽度高度传递给其构造函数——我们将其尺寸设置为与摄像头使用的尺寸相匹配。然后调用attachCamera(),为Video对象提供访问Camera对象视频流的权限。最后,通过调用addChild()Video对象添加到显示列表中。

在尝试连接到摄像头之前,你应该首先检查是否有一个摄像头可用。Camera.names静态属性返回一个可用摄像头的数组。我们在文档类构造函数的开始处检查了数组的长度是否大于0,然后才继续。或者,你可以检查Camera.getCamera()返回的是否为null

关于摄像头支持的更多信息,请在 Adobe Community Help 中搜索flash.media.Cameraflash.media.Video

更多内容...

让我们看看从摄像头捕获实时视频时的一些附加选项。

肖像模式

在 iOS 上,Camera对象以横向模式捕获视频。如果你的应用程序使用的是纵向宽高比,那么你需要交换摄像头的捕获尺寸,并且旋转和重新定位Video对象。为此,你需要对以下构造函数进行以下更改:

camera = Camera.getCamera();
 camera.setMode(stage.stageHeight, stage.stageWidth,
stage.frameRate); 
video = new Video(camera.width, camera.height);
video.attachCamera(camera);
video.rotation = 90;
video.x += stage.stageWidth; 

记得更改舞台的尺寸并更新 AIR for iOS 设置以使用纵向宽高比。由于对Video对象应用了旋转,捕获纵向视频时会有性能损失。尽可能使用横向模式来处理使用摄像头的应用程序。

选择摄像头

Camera.getCamera()静态方法默认连接到后置摄像头。对于支持多个摄像头的设备,你可以通过传递一个字符串来指定摄像头,该字符串表示Camera.names指定的数组中的零基于索引位置。例如,以下代码使用了 iPhone 4/4S 的前置摄像头:

camera = Camera.getCamera("1");

在进行此调用时,传递字符串而不是整数是很重要的。

在 iOS 上,任何时刻只能有一个摄像头处于活动状态。如果你连接到第二个摄像头,则之前摄像头的连接将被断开。

获取位图图像

从摄像头的实时视频流中捕获位图图像是可能的。以下代码从视频的当前帧中提取位图数据,并将其存储在Bitmap对象中:

var bd:BitmapData = new BitmapData(video.width, video.height,
false);
bd.draw(video);
var b:Bitmap = new Bitmap(bd);

如你所见,BitmapData对象的尺寸被设置为与视频相匹配。然后当前帧被绘制到BitmapData对象中,该对象用于创建实际的位图。

实时流

对于这个食谱,我们只是在本地上使用了相机的视频流。然而,通过使用 NetConnectionNetStream 类,可以将视频流传输到 Flash 媒体服务器,在那里它可以被广播到其他客户端。这对于实时视频聊天应用或其他协作项目来说非常理想。

这两个类都属于 flash.net 包。更多详细信息可在 Adobe 社区帮助中找到。

使用舞台

使用 Flash IDE 而不是 ActionScript 也可以在舞台上放置和调整 视频 对象的大小。只需在 面板中右键单击,然后从上下文菜单中选择 新建视频。在出现的 视频属性 面板中,点击 视频(ActionScript 控制) 单选按钮,然后点击 确定。视频剪辑将出现在库中,您可以将其拖动到舞台上,并为其指定一个实例名称。

相关内容

  • 保存到相机胶卷

  • 使用默认相机应用捕获

录制麦克风音频

AIR 提供了一个 API,允许应用程序连接到内置麦克风。可以获取麦克风的原始数据,将其记录以供以后使用,在接收时进行处理,或者将其路由到设备的扬声器。

本食谱将向您展示如何使用 MicrophoneByteArray 类来捕获和录制音频。您需要 Flash Professional CS5.5,因为 CS5 和 AIR 2.0 不支持 iOS 的麦克风访问。

准备工作

虽然 iOS 家族的所有最新型号都内置了麦克风,但旧一代的 iPod touch 没有。然而,第二代和第三代设备确实提供了对外部麦克风的兼容性,这可以用于本食谱。

从本书的配套代码包中,将 chapter10\recipe5\recipe.fla 打开到 Flash Professional CS5.5。

在舞台上,您将找到一个名为 output 的动态文本字段和三个电影剪辑。其中两个电影剪辑代表按钮,分别命名为 recordBtnstopBtnstopBtn 剪辑位于 recordBtn 剪辑的直接后方,但位于自己的时间轴层上,以便于访问。第三个电影剪辑名为 micStatus,覆盖了整个背景。它用于指示何时正在录音。

recordBtnstopBtn 的库符号链接到一个名为 Button 的基类。这个类是在第四章(第四章. 将 Flash 项目移植到 iOS)的 处理用户交互 食谱中引入的。

当用户点击 recordBtn 电影剪辑时,我们将添加 ActionScript 以开始从麦克风录制数据。当按下 stopBtn 时,音频捕获将结束。为了向用户提供正在录制的反馈,我们将 micStatus 电影剪辑的 播放头 移动到帧 2。文本字段将用于输出音频成功录制的确认信息。

此配方将专注于麦克风音频的录制。我们将在下一个配方中介绍音频的播放。

如何做到这一点...

现在让我们编写这个 ActionScript。按照以下步骤操作:

  1. 创建一个文档类并将其命名为Main

  2. 导入此配方所需的各个类,并创建两个成员变量——一个用于引用设备的麦克风,另一个用于存储从它捕获的数据:

    package {
    import flash.display.MovieClip;
     import flash.events.MouseEvent;
    import flash.events.SampleDataEvent;
    import flash.media.Microphone;
    import flash.utils.ByteArray; 
    public class Main extends MovieClip {
    private var mic:Microphone;
    private var soundData:ByteArray; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在构造函数中,设置电影剪辑并创建与设备麦克风的连接:

    public function Main() {
     micStatus.gotoAndStop(1);
    recordBtn.visible = true;
    stopBtn.visible = false;
    recordBtn.addEventListener(MouseEvent.MOUSE_UP,
    pressedRecordBtn);
    stopBtn.addEventListener(MouseEvent.MOUSE_UP,
    pressedStopBtn);
    mic = Microphone.getMicrophone();
    if(!Microphone.isSupported || mic == null)
    {
    recordBtn.visible = false;
    } 
    }
    
    
  4. 为每个被按下的按钮添加一个处理程序:

    private function pressedRecordBtn(e:MouseEvent):void {
    startRecording();
    }
    microphone audiorecordingprivate function pressedStopBtn(e:MouseEvent):void {
    stopRecording();
    }
    
    
  5. 接下来添加一个设置麦克风并开始监听实时音频数据的方法。我们还将实例化一个名为soundDataByteArray对象,它将用于存储捕获的数据:

    private function startRecording():void {
    micStatus.gotoAndStop(2);
    recordBtn.visible = false;
    stopBtn.visible = true;
    soundData = new ByteArray();
    mic.gain = 100;
    mic.rate = 44;
    mic.addEventListener(SampleDataEvent.SAMPLE_DATA,
    sampleData);
    }
    
    
  6. 添加一个事件处理程序,每当从麦克风获取音频数据时都会被调用。我们将最多写入 2 MB 的音频数据到我们的ByteArray对象中,以供以后使用:

    private function sampleData(e:SampleDataEvent):void {
    while(e.data.bytesAvailable)
    {
    var sample:Number = e.data.readFloat();
    soundData.writeFloat(sample);
    }
    if(soundData.length > 2097152)
    {
    stopRecording();
    }
    }
    
    
  7. 最后添加一个方法,用于停止监听来自麦克风的实时音频数据。记录的总字节数将写入output文本字段:

    private function stopRecording():void {
    micStatus.gotoAndStop(1);
    stopBtn.visible = false;
    mic.removeEventListener(SampleDataEvent.SAMPLE_DATA,
    sampleData);
    output.text = (soundData.length + " bytes recorded");
    }
    
    
  8. 保存类并将其文件命名为Main.as

  9. 返回到你的 FLA 文件并保存它。

  10. 发布 FLA 文件并将生成的.ipa文件部署到你的设备上。

  11. 启动应用,点击RECORD按钮并开始对着麦克风说话。当你完成时,点击STOP按钮。

记录的音频数据量(以字节为单位)将写入屏幕。

它是如何工作的...

flash.media.Microphone类提供了麦克风支持。要连接到设备的麦克风,调用静态Microphone.getMicrophone()方法,它将返回一个新的Microphone实例。如果找不到麦克风,则返回null

以下代码片段是我们文档类构造函数中进行的调用:

mic = Microphone.getMicrophone();

一旦你有一个Microphone对象,你可以调整将要接收的音频数据。我们通过在startRecording()方法中设置Microphone对象的增益和采样率来完成此操作。

增益用于增强麦克风的信号,并使用gain属性设置。使用100的值以最大化其响度。

采样率决定了捕获的音频质量,由rate属性指定。较高的采样率产生更清晰的音频,但需要 CPU 更多的处理,并需要更多的空间来存储。我们将rate属性设置为44,指定实际的采样频率为 44 kHz。换句话说,我们将每秒从麦克风捕获 44,100 次声音!这是允许的最高采样率,并记录最清晰的声音。

要实际开始从麦克风捕获音频,请向 Microphone 对象添加一个 SampleDataEvent.SAMPLE_DATA 监听器。随着麦克风音频缓冲区的填充,SAMPLE_DATA 事件会持续派发。我们在设置增益和采样率后立即在 startRecording() 方法中添加了 SAMPLE_DATA 事件监听器:

mic.gain = 100;
mic.rate = 44;
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, sampleData);

每个 SampleDataEvent 对象都有一个 data 属性,它是一个包含从麦克风当前采样的音频的 ByteArray。录制音频就是一个简单地将这个临时数据复制到一个更持久的 ByteArray 对象的过程。您可以在 SampleData() 事件处理程序中看到此代码,其中使用循环提取采样数据并将其写入 soundData 成员变量:

while(e.data.bytesAvailable)
{
var sample:Number = e.data.readFloat();
soundData.writeFloat(sample);
}

每个样本都由一个浮点值表示。因此,循环从音频缓冲区中读取一个浮点数并将其写入 soundData 成员变量。这个过程会一直持续到 SampleDataEvent 对象中的数据为空。

为了防止应用完全耗尽设备的内存,sampleData() 处理程序会检查 soundData 成员变量的大小。如果它的大小超过 2 MB(2,097,152 字节),则停止录制并将录制的字节数写入 output 文本字段。

通过从 Microphone 对象中移除 SAMPLE_DATA 事件监听器来停止音频捕获。查看 stopRecording() 方法以了解这一点。

关于音频捕获的更多信息,请在 Adobe Community Help 中搜索 flash.media.Microphoneflash.events.SampleDataEventflash.utils.ByteArray

还有更多...

在从麦克风录制时,您还有以下一些额外的选项。

麦克风活动

您可以通过查询 Microphone 对象的 activityLevel 属性来确定麦克风检测到的声音量。这将返回一个从 0100 的值,当没有检测到声音时返回 0

使用 setSilenceLevel() 方法也可以指定一个活动水平阈值,在音频被麦克风接受之前必须达到这个阈值。传递给参数的活动水平越高,音频源必须越响亮才能被检测到。此方法还接受一个可选的第二个参数,该参数指定在认为声音停止之前必须经过的毫秒数的不活动时间。

例如,将以下内容添加到您的 startRecording() 方法中:

mic.setSilenceLevel(50, 2000);
mic.addEventListener(ActivityEvent.ACTIVITY, activityChanged);

现在添加以下事件处理程序:

private function activityChanged(e:ActivityEvent):void {
output.text = "activating: " + e.activating + ", " +
"activity level: " + mic.activityLevel;
if(e.activating == false)
{
stopRecording();
}
}

最后,添加以下导入语句:

import flash.events.ActivityEvent;

在您的设备上测试这些更改。您的应用将不会派发 SAMPLE_DATA 事件,直到麦克风的静音水平被超过。此外,一旦激活,如果静音持续超过两秒钟,麦克风将再次停用。

实时流

在本配方中,麦克风音频数据仅被本地使用。但是,使用NetConnectionNetStream类,可以将数据传输到 Flash Media Server 以广播给其他客户端。有关详细信息,请访问 Adobe 社区帮助,搜索这两个类,它们属于flash.net包。

参见

  • 播放录制的音频

播放录制的音频

在捕获麦克风的原始音频数据后,您需要一种播放它的方法。本配方将向您展示如何将数据发送到您的设备扬声器。

准备工作

如果您已经完成了录音麦克风音频配方,那么您可以从中编写的代码开始工作。或者,从本书的配套代码包中打开chapter10\recipe6\recipe.fla,并将其作为起点使用。

目前,FLA 将从麦克风录制音频并将其存储在名为soundData的成员变量中,该变量是ByteArray类型。我们将添加代码,在用户完成录音后播放音频。

如何操作...

需要以下更改来读取和播放录制的音频:

  1. 打开Main.as

  2. 导入以下三个类:

    import flash.display.MovieClip;
    import flash.events.Event; 
    import flash.events.MouseEvent;
    import flash.events.SampleDataEvent;
    import flash.media.Microphone;
    import flash.media.Sound;
    import flash.media.SoundChannel; 
    import flash.utils.ByteArray;
    
    
  3. 还需添加一个SoundSoundChannel成员变量:

    private var mic:Microphone;
    private var soundData:ByteArray;
    private var sound:Sound;
    private var channel:SoundChannel; 
    
    
  4. stopRecording()方法需要调用以启动录制的音频播放。在方法末尾添加以下行:

    private function stopRecording():void {
    micStatus.gotoAndStop(1);
    stopBtn.visible = false;
    mic.removeEventListener(SampleDataEvent.SAMPLE_DATA,
    sampleData);
    playRecording(); 
    }
    
    
  5. 现在编写playRecording()方法,它将启动音频播放:

    private function playRecording():void {
    soundData.position = 0;
    sound = new Sound();
    sound.addEventListener(SampleDataEvent.SAMPLE_DATA,
    playSampleData);
    channel = sound.play();
    channel.addEventListener(Event.SOUND_COMPLETE,
    playbackComplete);
    
    
  6. 添加一个方法,该方法定期从soundData对象中提取数据以进行播放:

    private function playSampleData(e:SampleDataEvent):void {
    for(var i:int=0; i<8192 && soundData.bytesAvailable>0; i++)
    {
    var sample:Number = soundData.readFloat();
    e.data.writeFloat(sample);
    e.data.writeFloat(sample);
    }
    }
    
    
  7. 最后,在音频播放完成后重置按钮电影剪辑:

    private function playbackComplete(e:Event):void {
    recordBtn.visible = true;
    stopBtn.visible = false;
    }
    
    
  8. 保存对类的更改。

  9. 发布 FLA 并在您的设备上测试它。

  10. 开始录制一些音频,完成后,轻触停止按钮。

录制的音频将通过您的设备扬声器播放。如果您什么也听不到,请增加扬声器的音量并再次尝试。

它是如何工作的...

SoundSoundChannel类都用于音频播放。

我们创建一个Sound对象,并向它添加一个SAMPLE_DATA事件监听器。当Sound对象没有更多音频数据可播放时,将触发此事件:

sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA,
playSampleData);

还调用了对象的play()方法,该方法返回一个SoundChannel实例,允许监控播放。我们监听SoundChannel对象触发SOUND_COMPLETE以确定音频播放何时结束:

channel = sound.play();
channel.addEventListener(Event.SOUND_COMPLETE,
playbackComplete);

初始时,Sound对象不包含任何音频数据。整个录音的数据由soundData成员变量持有,该变量是ByteArray类型。由于Sound对象没有音频数据可播放,它立即触发一个SAMPLE_DATA事件,该事件由playSampleData()处理程序捕获。

playSampleData()中,我们从soundData成员变量中提取一些音频数据并将其馈送到Sound对象。这为Sound对象提供了足够的数据以开始播放音频。每次其缓冲区变低时,它将派发另一个SAMPLE_DATA事件,我们将提供更多数据。这个过程会一直持续到整个录音播放完毕。

以下是从playSampleData()处理程序中提取的代码,该处理程序负责将数据写入Sound对象的缓冲区:

for(var i:int=0; i<8192 && soundData.bytesAvailable>0; i++)
{
var sample:Number = soundData.readFloat();
e.data.writeFloat(sample);
e.data.writeFloat(sample);
}

Sound对象的缓冲区通过SampleDataEvent参数的data属性来访问。因此,我们从soundData成员变量中取一个样本并将其写入data属性的ByteArray。使用readFloat()方法从soundData中读取样本,而使用writeFloat()将相同的样本写入Sound对象的缓冲区——每个样本由一个浮点值表示。

然而,我们不仅仅是将单个样本写入缓冲区——它很快就会再次清空。相反,我们抓住机会写入 8192 个立体声样本,为对象提供 64 KB 的音频数据。通常,你一次可以写入 2048 到 8192 个立体声样本。然而,如果你尝试写入超过 64 KB 的数据到缓冲区,将会抛出一个运行时异常。

要创建立体声样本,我们将每个记录的样本写入Sound对象两次:

e.data.writeFloat(sample);
e.data.writeFloat(sample);

当麦克风记录单声道数据时,你的设备能够进行立体声输出。因此,当将音频数据写入Sound对象时,你需要将样本写入左右两个通道。writeFloat()的第一个调用将样本发送到左通道,而第二个调用将样本发送到右通道。

更多信息,请在 Adobe 社区帮助中搜索flash.media.Soundflash.media.SoundChannel

还有更多...

与麦克风音频播放相关的一些最终信息。

处理较低的采样率

Sound类使用 44 kHz 的采样率。如果麦克风捕获的音频来自不同的频率,那么在将其馈送到Sound对象之前,你需要将其从较低的速率提升到 44 kHz。

例如,如果Microphone对象的rate属性在录制时被设置为 22 kHz 的频率,那么你需要在playSampleData()中的播放循环中进行调整,如下所示:

for(var i:int=0; i<4096 && soundData.bytesAvailable>0; i++)
{
var sample:Number = soundData.readFloat();
e.data.writeFloat(sample);
e.data.writeFloat(sample);
e.data.writeFloat(sample);
e.data.writeFloat(sample);
}

实际上,相同的样本被写入每个通道两次,这会将 22 kHz 的录音提升到 44 kHz。请注意,与之前的 8192 次迭代相比,这里执行了 4096 次循环迭代。这是为了确保写入到Sound对象缓冲区的音频数据不超过 64 KB,这是它的上限。

这里提供的示例相对简单,不推荐用于大多数采样率。更彻底的方法是通过插值现有样本来生成缺失的数据。在大多数情况下,您可能希望避免在实时中重新采样音频,因为这可能会很耗费计算资源。

关于采样率转换的更多详细信息可以在维基百科上找到:en.wikipedia.org/wiki/Sample_rate_conversion。此外,还可以查看 SoundTouch AS3 库,它允许使用 ActionScript 3.0 进行实时音频处理:github.com/also/soundtouch-as3.

保存捕获的数据

这和之前的配方只是简单地将记录的音频数据保存在内存中。然而,您的应用程序可能需要记录持久化。使用 flash.filesystem 包中提供的类,您可以将二进制数据写入您的设备,并在以后读取它。

以下代码片段将我们的录音保存到设备上:

var stream:FileStream = new FileStream();
var file:File = File.documentsDirectory.resolvePath("audio.dat");
stream.open(file, FileMode.WRITE);
stream.writeBytes(soundData);
stream.close();

获取数据同样简单:

soundData = new ByteArray();
var stream:FileStream = new FileStream();
var file:File = File.documentsDirectory.resolvePath("audio.dat");
stream.open(file, FileMode.READ);
stream.readBytes(soundData);

写入文件系统的数据只能由放置它的应用程序访问。当应用程序被卸载时,任何属于它的数据都将被删除。

导出为 WAV 或 MP3

对于这个和之前的配方,我们只是处理从麦克风捕获的原始 PCM 数据。然而,您可能希望将数据保存为常见的音频格式,如 MP3 和 WAV。不幸的是,AIR 不提供导出这些格式的 API。相反,您将需要依赖第三方库。

WAV 编码由 WAVWriter 类提供,该类可在以下位置找到:code.google.com/p/ghostcat/source/browse/trunk/ghostcatfp10/src/ghostcat/media/WAVWriter.as?spec=svn424&r=424.

使用 Shine 库可以实现 MP3 编码:github.com/kikko/Shine-MP3-Encoder-on-AS3-Alchemy.

参见

  • 录制麦克风音频

  • 控制音频播放,第十二章

  • 引用应用程序的常用目录,第十三章

  • 写入文件,第十三章

第十一章。渲染网页

在本章中,我们将涵盖:

  • 在 Safari 中打开网页

  • 在应用内渲染网页

  • 导航浏览历史记录

  • 渲染本地网页

  • 动态生成本地网页

  • 捕获网页快照

简介

互联网已经成为我们生活中不可或缺的一部分,以至于 iOS 应用也经常使用网络浏览器技术来执行某些任务。本章将探讨 AIR for iOS 的 HTML 功能;从简单地通过 Safari 启动网页,到更集成的体验,其中网页内容直接在应用本身中渲染。

我们将主要关注在 AIR 2.6 中引入的 StageWebView 类。然而,那些使用 Flash Professional CS5 和 AIR 2.0 的人会发现 在 Safari 中打开网页 的配方很有用。

在 Safari 中打开网页

AIR for iOS 使得向用户显示网页成为可能。对于许多情况,最简单的解决方案是从您的应用中启动 Safari(设备的原生网络浏览器)。许多应用程序采用这种方法,一旦用户完成页面,他们可以使用应用切换器回到他们的应用。

让我们看看如何从 AIR for iOS 应用中加载网页到 Safari。

准备工作

从本书的配套代码包中,将 chapter11\recipe1\recipe.fla 打开到 Flash Professional 中,并将其作为起点使用。

阶段上有一个名为 twitterBtn 的动画剪辑。动画剪辑的库符号链接到一个名为 Button 的类,该类是在第四章 处理用户交互 的配方中引入的 Chapter 4。

让我们编写一些 ActionScript 代码,在按钮被按下时将 www.twitter.com 加载到 Safari 中。

如何做到...

我们将利用包级 navigateToURL() 函数来启动 Safari。执行以下步骤:

  1. 创建一个新的文档类并将其命名为 Main

  2. 将以下三个导入语句添加到类中:

    import flash.events.MouseEvent;
    import flash.net.navigateToURL;
    import flash.net.URLRequest;
    
    
  3. 在构造函数中,监听 twitterBtn 动画剪辑被按下:

    public function Main() {
    twitterBtn.addEventListener(MouseEvent.MOUSE_UP, pressed); 
    }
    
    
  4. 现在添加一个事件监听器,它将启动 Safari 并将其加载到 Twitter 的网站中:

    private function pressed(e:MouseEvent):void {
    var url:URLRequest = new URLRequest(
    "http://www.twitter.com");
    navigateToURL(url);
    }
    
    
  5. 保存类并按提示将文件命名为 Main.as

  6. 返回 FLA 并也保存它。

  7. 发布 FLA 并在您的设备上测试它。点击 twitter 按钮将在 Safari 中启动并加载 www.twitter.com。如果您使用的是 iOS 4 或更高版本,请使用应用切换器查找并回到您的应用。

它是如何工作的...

flash.net 包含一个名为 navigateToURL() 的包级函数,可以用于在 Safari 浏览器中直接打开网站。

它接受一个参数,即表示要加载的 URL 的 URLRequest

var url:URLRequest = new URLRequest("http://www.twitter.com");

一旦创建了请求,就可以启动 Safari 并加载请求的 URL:

navigateToURL(url);

请求 URL 中的 http URI 方案很重要。navigateToURL() 函数可以用来启动许多外部 iOS 应用程序,Safari 只是其中之一。通过在 URL 前缀添加 http://,AIR 知道要启动 Safari。

此外,作为包级函数,navigateToURL() 必须明确添加到您类的导入语句列表中:

import flash.net.navigateToURL;

当从运行 iOS 4 或更高版本的设备上启动 Safari 时,您的应用程序将被挂起并移动到后台。当用户完成网页后,他们需要从主屏幕或应用程序切换器中选择您的应用程序以恢复它。然而,从 iOS 3 设备启动 Safari 将关闭您的应用程序而不是挂起它——多任务处理直到 iOS 4 才被引入。如果您计划支持 iOS 3,则在启动 Safari 之前保存应用程序的状态。

如需更多信息,请在 Adobe Community Help 中搜索 flash.net.navigateToURLflash.net.URLRequest

参考信息

  • 在应用程序内渲染网页

  • 处理多任务,第三章

  • 优雅地退出应用程序,第三章

  • 保存应用程序状态,第四章

  • 启动系统应用程序,第十三章

在应用程序内渲染网页

自从 AIR 2.6 以来,已经在 AIR for iOS 应用程序中直接加载和显示 HTML 内容成为可能。这很方便,因为它可以防止用户离开应用程序来查看网页。它还提供了其他好处,例如更紧密的 OAuth(开放授权)集成,以及包含 HTML 横幅广告的能力。

此配方将向您展示如何直接将远程网页加载到您的应用程序中。

准备工作

这里介绍的方法仅适用于使用 Flash Professional CS5.5 和 AIR 2.6 或更高版本的用户。AIR 2.0 SDK 不提供在应用程序中加载 HTML 的 API。

从本书的配套代码包中,将 chapter11\recipe2\recipe.fla 打开到 Flash Professional CS5.5 中。FLA 的舞台是空的,但其 AIR for iOS 设置已经应用,这为您发布时节省了精力。

如何操作...

我们将利用 StageWebView 类来渲染网页。

  1. 创建一个文档类并命名为 Main

  2. 添加以下两个导入语句:

    import flash.geom.Rectangle;
    import flash.media.StageWebView;
    
    
  3. 声明一个 StageWebView 成员变量:

    private var webView:StageWebView;
    
    
  4. 在构造函数中,使用 StageWebView 实例来加载网页:

    public function Main() {
     webView = new StageWebView();
    webView.stage = stage;
    webView.viewPort = new Rectangle(
    0, 0, stage.stageWidth, stage.stageHeight);
    webView.loadURL("http://www.yeahbutisitflash.com"); 
    }
    
    
  5. 保存类并将文件命名为 Main.as

  6. 现在发布 FLA 并将 .ipa 文件部署到您的设备上。

  7. 当启动时,www.yeahbutisitflash.com 网站将被加载并在您的应用程序中显示。您还可以与页面进行交互。试试看!

工作原理...

StageWebView 类允许在您的应用中使用 iOS 的原生 WebKit 渲染引擎显示本地和远程的 HTML 内容。

StageWebView 实际上不是一个正常的显示对象,因此不能添加到 Flash 的显示列表中。相反,它是一个绘制在您的应用程序之上的窗口,下面的项目被隐藏。不幸的是,这意味着您不能在 StageWebView 对象使用的区域上放置显示对象。

在创建 StageWebView 对象时,您必须直接将其附加到舞台,并指定一个视口以在其中渲染其 HTML 内容。为此,分别设置其 stageviewPort 属性。使用 Rectangle 对象来定义视口的大小和位置。

一旦 StageWebView 对象被实例化并设置好,您可以通过传递一个 URL 给其 loadURL() 方法来加载一个网页。使用一个字符串来定义 URL,并在其前加上相关的 URI 方案,对于大多数情况将是 http://。省略 URI 方案将阻止页面加载。

您可以通过将 stage 属性设置为 null 来隐藏 StageWebView 对象。当您完成使用 StageWebView 对象时,调用其 dispose() 方法。这样做将帮助垃圾回收器更快地回收内存。

更多信息,请在 Adobe Community Help 中搜索 flash.media.StageWebView

更多...

以下信息提供了更多详细信息。

页面加载事件

您可以通过监听来自 StageWebView 对象的以下两个事件来确定页面加载请求的成功或失败:

  • Event.COMPLETE: 请求的页面及其内容已加载

  • ErrorEvent.ERROR: 在尝试加载页面时发生错误

由于多种原因可能会发生加载错误,其中之一是省略了 URL 中的 URI 方案。有关加载错误的详细信息可以从 ErrorEvent 对象的 errorIDtext 属性中获取。

多个实例

可以同时创建并使用多个 StageWebView 对象;然而,您对它们的深度排序控制有限。虽然无法动态更改深度,但最近实例化的对象将位于其他 StageWebView 实例之上。但是,Adobe 建议您避免重叠实例。

检查支持情况

静态的 StageWebView.isSupported 属性可以用来确定 StageWebView 类是否受支持。尽管这个属性对所有 iOS 设备都返回 true,但在编写跨平台代码时您应该查询它。

在标准屏幕分辨率内的 Retina 网页页面

在 Retina 显示设备上,即使 AIR for iOS 应用本身设置为使用标准的非 Retina 分辨率,StageWebView 对象也会利用设备的更高分辨率。

包含横幅广告

许多开发者直接在他们的应用中包含 HTML 横幅广告。这允许开发者免费向用户分发应用,并通过应用内显示的广告来生成收入。

StageWebView类使得显示由 AdMob 等服务提供的横幅广告成为可能。有关更多信息,请访问 AdMob 网站:www.admob.com

OAuth 支持

第三方如 Twitter 和 Google 允许开发者访问其服务器端 API。然而,许多这些 API 提供对受保护数据的访问,并需要使用用户名和密码。许多第三方现在使用 OAuth 协议,该协议使用户能够访问数据,同时保护其账户凭证。

例如,如果您打算创建一个允许用户登录 Twitter 的应用,那么 OAuth 将是必需的。为了使过程尽可能安全,用户实际上将从 Twitter 托管的一个网页上登录,这意味着您需要将StageWebView对象作为客户端实现的一部分来使用。

Adobe 开发者传教士 Piotr Walczyszyn 在 Adobe TV 上提供了一个两部分的视频教程,演示了如何在 Adobe AIR 应用中使用 OAuth:tv.adobe.com/watch/adc-presents/introduction-to-oauth-for-secure-user-and-application-authorization。有关使用StageWebView的更具体的移动示例,请查看 Adobe 平台传教士 Mark Doherty 的视频:www.flashmobileblog.com/2010/07/17/air2-5-stagewebview-demo-oauth-support

OAuth ActionScript 3.0 库可在以下地址找到:code.google.com/p/oauth-as3.

参见

  • 浏览历史记录导航

  • 动态生成本地网页

  • 在 Safari 中打开网页

  • 捕获网页快照

浏览历史记录导航

当用户浏览时,访问过的页面会存储在浏览历史记录堆栈中。StageWebView类使得浏览历史记录的导航和检测位置变化成为可能。

本食谱将指导您完成创建一个简单应用的必要步骤,该应用允许用户在浏览时导航其页面历史记录。

准备工作

您需要 Flash Professional CS5.5 来完成此食谱。

已提供 FLA 作为起点。从本书的配套代码包中,将chapter11\recipe3\recipe.fla打开到 Flash Professional CS5.5 中。

阶段上放置了两个代表导航按钮的电影剪辑。我们将使用这些按钮在用户的历史记录堆栈中前后移动。第一个的实例名称为backBtn,而第二个命名为forwardBtn

这两个电影剪辑都链接到一个名为 Button 的基类。这个类是在第四章 处理用户交互 的配方中引入的 第四章。

如何实现...

让我们通过以下步骤使用与 StageWebView 类相关的各种方法和事件:

  1. 创建一个文档类,并将其命名为 Main

  2. 添加以下导入语句:

    import flash.events.MouseEvent;
    import flash.events.LocationChangeEvent;
    import flash.geom.Rectangle;
    import flash.media.StageWebView;
    
    
  3. 声明一个 StageWebView 成员变量:

    private var webView:StageWebView;
    
    
  4. 在构造函数中,设置按钮电影剪辑和 StageWebView 对象:

    public function Main() {
     backBtn.addEventListener(MouseEvent.MOUSE_UP, prevPage);
    forwardBtn.addEventListener(MouseEvent.MOUSE_UP, nextPage);
    backBtn.visible = false;
    forwardBtn.visible = false;
    webView = new StageWebView();
    webView.stage = stage;
    webView.viewPort = new Rectangle(
    0, 62, stage.stageWidth, stage.stageHeight-62);
    webView.addEventListener(
    LocationChangeEvent.LOCATION_CHANGE, locationChanged);
    webView.loadURL("http://www.yeahbutisitflash.com"); 
    }
    
    
  5. StageWebView 对象的视口已定位在按钮下方,并添加了对 URL 变化的监听器。由于用户的浏览历史堆栈最初为空,导航按钮已被设置为不可见。

  6. 现在添加一个 locationChanged() 方法来处理 StageWebView 对象 URL 的变化:

    private function locationChanged(e:LocationChangeEvent):void {
    backBtn.visible = webView.isHistoryBackEnabled;
    forwardBtn.visible = webView.isHistoryForwardEnabled;
    }
    
    
  7. 此方法根据用户在历史记录堆栈中的位置设置每个按钮的可见性。如果他们无法进一步后退,则 backBtn 将被隐藏。如果他们无法前进,则 forwardBtn 将被隐藏。

  8. 最后添加处理每个按钮被按下的方法:

    private function prevPage(e:MouseEvent):void {
    webView.historyBack();
    backBtn.visible = webView.isHistoryBackEnabled;
    }
    private function nextPage(e:MouseEvent):void {
    webView.historyForward();
    forwardBtn.visible = webView.isHistoryForwardEnabled;
    }
    
    
  9. 这两个方法根据按下的按钮将用户移动到浏览历史记录中的前一页或后一页。类似于 locationChanged() 方法,每个按钮的可见性也由其相应的处理程序管理。

  10. 保存类并将其命名为 Main.as

  11. 现在发布 FLA 并将应用部署到您的设备上。

  12. 启动应用并选择网站内的任意超链接。访问几页后,通过按导航按钮在历史记录中导航。

它是如何工作的...

在浏览过程中,访问的页面将被存储在浏览历史记录堆栈中。这包括通过超链接导航到的页面或使用 loadURL() 程序性加载的页面。

StageWebView 类提供了导航浏览历史记录的方法。调用 historyBack() 方法可跳转到之前访问的页面,或调用 historyForward() 跳转到堆栈中的下一页。在调用这些方法之前,您需要确定实际上是否有可以移动到的网页。isHistoryBackEnabled 属性返回 true 表示您能够后退,而 isHistoryForwardEnabled 返回 true 表示您能够前进。

当用户按下导航按钮时,historyBack()historyForward() 都被调用来响应。

我们还监听了 LocationChangeEvent.LOCATION_CHANGE 事件,该事件由 StageWebView 对象在 URL 发生变化时触发。在此事件的处理程序中,查询了 isHistoryBackEnabledisHistoryForwardEnabled,每个值都用于设置 backBtnforwardBtn 的可见性。

关于管理浏览历史记录的更多信息,请在 Adobe Community Help 中搜索 flash.media.StageWebViewflash.events.LocationChangeEvent

还有更多...

现在让我们谈谈处理浏览历史记录时的一些其他选项。

获取当前位置

你可以通过查询StageWebView对象的只读location属性来确定当前页面的 URL。URL 将以字符串的形式返回。

停止和重新加载页面

StageWebView类在页面加载方面提供了有限的控制。提供了一个stop()方法来停止当前页面的加载,而可以通过调用reload()来重新加载页面。

检测 URL 即将更改时

除了LOCATION_CHANGE,还有一个LOCATION_CHANGING事件,表示页面的 URL 即将更改。当选择超链接或页面内运行的脚本更改 URL 时,会触发LOCATION_CHANGING事件。这个事件很方便,因为你可以通过调用LocationChangeEvent对象的preventDefault()方法来阻止新 URL 的加载。

要看到这个动作,首先在你的构造函数中添加以下事件监听器:

webView.addEventListener(
LocationChangeEvent.LOCATION_CHANGING, locationChanging);

现在为该事件添加一个处理程序:

private function locationChanging(e:LocationChangeEvent):void
{
e.preventDefault();
}

发布并测试应用。你的代码更改将有效地阻止你选择的任何超链接。

在调用loadURL()loadString()historyBack()historyForward()reload()之后,LOCATION_CHANGING事件不会触发。

参见

  • 在应用内渲染网页

渲染本地网页

除了远程网页,还可以使用StageWebView类加载和显示本地 HTML 文件。

让我们将网页与应用程序捆绑在一起,并在运行时加载。

准备工作

这个菜谱需要 Flash Professional CS5.5 和 AIR 2.6 或更高版本。

从书籍的配套代码包中打开chapter11\recipe4\recipe.fla,并将其作为起点。

与 FLA 相同的目录下有一个名为html的文件夹,其中包含你的应用必须加载的 HTML 页面。使用 Windows 资源管理器或 Finder,查看文件夹的内容。在index.html文件中,你还会找到一个 PNG 图像和一个样式表,这两个都是 HTML 所使用的。

如何做到这一点...

我们将把这个菜谱分成两部分。首先,我们将使用 AIR for iOS 设置面板将本地 HTML 与应用程序捆绑在一起。然后,我们将编写加载和渲染所需的 ActionScript。

捆绑 HTML

让我们从将 HTML 内容与 FLA 捆绑在一起开始。

  1. 通过选择 Flash 的下拉菜单中的文件 | AIR for iOS 设置来移动到 AIR for iOS 设置面板。

  2. 如果它尚未选中,请点击面板的常规选项卡。

  3. 在面板底部是包含文件列表。点击列表上方的文件夹图标;浏览到并选择chapter11\recipe4\html。现在你将在包含文件列表中看到html

  4. 现在点击确定以关闭AIR for iOS 设置面板。

加载捆绑的 HTML

现在 HTML 已经包含在你的 FLA 中,我们可以专注于编写 ActionScript。

  1. 创建一个新的文档类,并将其命名为Main

  2. 向类中添加以下三个额外的导入语句:

    import flash.geom.Rectangle;
    import flash.media.StageWebView;
    import flash.filesystem.File;
    
    
  3. 声明一个 StageWebView 成员变量:

    private var webView:StageWebView;
    
    
  4. 最后,在构造函数中,设置并加载本地网页:

    public function Main() {
     var url:String = File.applicationDirectory.resolvePath(
    "html/index.html").nativePath;
    webView = new StageWebView();
    webView.stage = stage;
    webView.viewPort = new Rectangle(
    0, 0, stage.stageWidth, stage.stageHeight);
    webView.loadURL(url); 
    }
    
    
  5. 保存类并在提示时,将文件命名为 Main.as

  6. 返回到你的 FLA 并保存它。

  7. 现在发布 FLA 并在你的设备上测试它。HTML 页面将从你的设备文件系统加载。

它是如何工作的...

在你的设备上加载存储的网页与加载远程页面并没有太大区别。唯一需要额外的一步是首先获取你想要加载的本地 HTML 文件的本地路径。将相对路径传递给 StageWebView.loadURL() 将导致 ErrorEvent.ERROR 被分发。

所有 iOS 应用都存储在其自己的主目录中,应用本身可以读取和写入存在于其中的各种子文件夹。其中一个这样的子文件夹是应用程序目录,用于存储应用程序及其捆绑的任何文件。这就是你将找到 index.html 及其相关文件的地方。

AIR SDK 提供了 flash.filesystem.File 类,它允许你引用包括应用程序目录在内的常用目录。然后可以使用 File 类的 resolvePath() 方法来细化路径。以下代码行获取了存储在应用程序目录中的 index.html 文件的引用:

File.applicationDirectory.resolvePath("html/index.html")

resolvePath() 方法返回一个 File 对象。通过调用其 nativePath 属性,我们可以获得一个可以传递给 StageWebView 对象的 loadURL() 方法的字符串。以下是一行完整的代码:

var url:String = File.applicationDirectory.resolvePath(
"html/index.html").nativePath;

与你希望与应用捆绑的任何本地内容一样,确保你包含的任何文件都位于 FLA 的根文件夹中。

如需更多信息,请在 Adobe Community Help 中搜索 flash.filesystem.Fileflash.media.StageWebView

更多内容...

StageWebView 实例内渲染的网页不必与你的应用完全隔离。

双向 ActionScript/JavaScript 通信

虽然有限,但可以使用 StageWebView 类执行双向 ActionScript/JavaScript 通信。这样做允许在应用和 StageWebView 实例内渲染的 HTML 页面之间传递数据。

可以在 Adobe 开发者 Sean Voisen 的个人博客上找到概述该过程的文档:sean.voisen.org/blog/2010/10/making-the-most-of-stagewebview

参考以下内容

  • 在应用内渲染网页

  • 动态生成本地网页

  • 引用应用的常用目录,第十三章

动态生成本地网页

我们已经介绍了如何使用StageWebView类显示远程和本地网页。还可以在 iOS 应用程序中动态生成 HTML 并直接渲染它。

让我们通过动态创建一个使用 PNG 图像和样式表的网页来看看这是如何完成的。

准备工作

这里介绍的操作仅适用于使用 Flash Professional CS5.5 和至少 AIR SDK 2.6 版本的用户。AIR 2.0 不支持StageWebView类。

我们将需要使用as3corelib API。这是一个包含各种不可多得的 ActionScript 3.0 类和工具的库,包括散列、图像编码和字符串操作。在这个菜谱中,我们将使用库的 PNG 编码器。

as3corelib API 可在 GitHub 上获取:github.com/mikechambers/as3corelib。单击页面上的下载链接,从下载包部分选择as3corelib-.93.zip。将.zip文件解压缩到您的文档文件夹:packt\flash-ios-cookbook\

注意

如果您使用的是 Windows,则您的文档文件夹的位置取决于您运行的 Windows 版本。对于 Windows Vista 和 Windows 7,它可以在以下位置找到:C:\Users\<username>\Documents\。如果您使用的是 Windows XP,则它位于:C:\Documents and Settings\<username>\My Documents\

现在从书籍的配套代码包中打开chapter11\recipe5\recipe.fla到 Flash Professional CS5.5 中。在库面板中有一个被分配了Image链接名称的 PNG 图像。我们将在这个网页中包含这个图像。在接下来的这个菜谱中,我们将从这个 FLA 开始工作。

如何操作...

这个菜谱分为两个主要步骤。我们将首先将 as3corelib API 链接到我们的 FLA。一旦完成,我们将使用 API 编写生成页面的 ActionScript。

链接到 as3corelib API

as3corelib API 以.swc文件的形式提供,必须将其静态链接到您的 FLA。

  1. 从 Flash Professional 的下拉菜单中选择文件 | ActionScript 设置。这将打开高级 ActionScript 3.0 设置面板,您可以在其中添加 SWC。链接到 as3corelib API

  2. 选择库路径选项卡,然后单击表示为+符号的添加新路径图标。

  3. 现在点击浏览 SWC 文件图标,从您的文档文件夹中选择以下文件:packt\flash-ios-cookbook\as3corelib-.93\as3corelib-.93\lib\as3corelib.swc。它将被添加到要随应用程序发布的 SWC 文件列表中。通过单击其路径左侧的图标展开其条目,并确保其链接类型设置为合并到代码

  4. 通过单击底部的确定按钮关闭高级 ActionScript 3.0 设置面板。

生成 HTML

将 SWC 链接到你的 FLA 后,你现在可以使用它提供的 API。让我们写一些 ActionScript 来生成一个 HTML 文件并显示它。

  1. 首先创建一个文档类,并将其命名为Main

  2. 添加以下导入语句,包括 as3corelib 的 PNG 编码器类:

    import flash.display.BitmapData;
    import flash.filesystem.File;
    import flash.filesystem.FileStream;
    import flash.filesystem.FileMode;
    import flash.geom.Rectangle;
    import flash.media.StageWebView;
    import flash.utils.ByteArray;
    import com.adobe.images.PNGEncoder;
    
    
  3. 声明一个StageWebView成员变量:

    private var webView:StageWebView;
    
    
  4. 在类的构造函数中,调用创建 HTML 页面并将其加载到StageWebView对象中的方法:

    public function Main() {
     createHtml();
    loadHtml(); 
    }
    
    
  5. 现在添加创建 HTML 页面的方法,包括它所使用的样式表和 PNG 图像:

    private function createHtml():void {
    var cssString:String = "body" +
    "{ padding:0px; border:0px; margin:0px; " +
    "background-color:#cdc0af }";
    var htmlString:String = "<!DOCTYPE HTML>" +
    "<html>" +
    "<head>" +
    "<link rel='stylesheet' type='text/css' " +
    "href='styles.css' />" +
    "<meta name='viewport' " +
    "content='width=device-width; " +
    "height=device-height; initial-scale=1.0; " +
    "maximum-scale=1.0; user-scalable=0;' />" +
    "</head>" +
    "<body>" +
    "<img src='image.png' />" +
    "</body>" +
    "</html>";
    var image:BitmapData = new Image();
    writeFile(htmlString, "index.html");
    writeFile(cssString, "styles.css");
    writePng(image, "image.png");
    }
    
    
  6. createHtml()方法调用两个支持方法——writeFile()writePng()。将这两个方法都添加到类中:

    private function writeFile(text:String, name:String):void {
    var file:File = File.documentsDirectory.resolvePath(name);
    var stream:FileStream = new FileStream();
    stream.open(file, FileMode.WRITE);
    stream.writeUTFBytes(text);
    stream.close();
    }
    private function writePng(bd:BitmapData, name:String):void {
    var pngBytes:ByteArray = PNGEncoder.encode(bd);
    var file:File = File.documentsDirectory.resolvePath(name);
    var stream:FileStream = new FileStream();
    stream.open(file, FileMode.WRITE);
    stream.writeBytes(pngBytes);
    stream.close();
    }
    
    
  7. 最后,添加加载和显示生成的 HTML 页面的方法:

    private function loadHtml():void {
    var url:String = File.documentsDirectory.resolvePath(
    "index.html").nativePath;
    webView = new StageWebView();
    webView.stage = stage;
    webView.viewPort = new Rectangle(
    0, 0, stage.stageWidth, stage.stageHeight);
    webView.loadURL(url);
    }
    
    
  8. 保存这个类,并在提示时将其文件命名为Main.as

  9. 返回到你的 FLA 并保存它。

  10. 现在发布 FLA 并在你的设备上测试它。应用将动态生成 HTML 页面并在屏幕上显示。

它是如何工作的...

这个配方大量使用了 Flash 的FileFileStream类。在动态创建 HTML 页面时,生成的 HTML 必须首先写入设备的文件系统,然后才能被StageWebView实例加载。HTML 使用的任何本地资源,如样式表和图像,也必须写入文件系统,并且与 HTML 使用的相对路径相匹配。

createHtml()方法中,我们声明并初始化了一个包含我们 HTML 的字符串。以下是由它生成的 HTML:

<html>
<head>
<link rel='stylesheet' type='text/css' href='styles.css' />
<meta name='viewport' content='width=device-width;
height=device-height; initial-scale=1.0;
maximum-scale=1.0; user-scalable=0;' />
</head>
<body>
<img src='image.png' />
</body>
</html>

注意它引用了一个名为styles.css的本地样式表和一个名为image.png的图像。这个图像是 FLA 库中的 PNG,而表示样式表的字符串也是在createHtml()方法中生成的。

HTML 字符串、样式表字符串和 PNG 都写到了设备的文件系统中的同一目录。这是通过我们的writeFile()writePng()方法完成的。

当 iOS 应用安装时,在应用的主目录中创建了一些常见的目录。其中一个这样的目录是 Documents 目录,可以用来存储应用程序特定的数据和临时文件。可以通过flash.filesystem.File类的静态documentsDirectory属性来获取对这个目录的引用。这就是我们写入本地网页的地方。

writeFile()方法在 Documents 目录中创建一个指定的文件,并将数据字符串写入其中。我们调用这个方法两次。首先写入 HTML 文件,然后再次写入样式表。文件是通过使用File对象声明其位置来创建的,然后该对象被传递给FileStream对象的open()方法:

var file:File = File.documentsDirectory.resolvePath(name);
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);

一旦FileStream对象被打开,实际的文件是通过调用writeUTFBytes()并将字符串传递给它来写入的。然后通过调用close()来结束这个过程:

stream.writeUTFBytes(htmlString);
stream.close();

使用 writePng() 方法将 PNG 文件写入 Documents 目录,这与 writeHtml() 类似。首先使用 as3corelib 库的 PNGEncoder 类将 Image 对象的位图数据编码为 PNG 格式:

var pngBytes:ByteArray = PNGEncoder.encode(bd);

然后使用 FileStream 对象将 PNG 写入文件系统。HTML 和样式表都由字符串表示。PNG 的数据存储在一个 ByteArray 对象中。因此,而不是使用 writeUTFBytes(),我们调用 FileStream 对象的 writeBytes() 方法。

最后一步是创建一个 StageWebView 对象,并将 Documents 目录中的 index.html 加载到其中。这由 loadHtml() 方法处理。

关于 flash.filesystem.File, flash.filesystem.FileStreamflash.utils.ByteArray 的更多信息,可以从 Adobe 社区帮助中获取。

还有更多...

在动态生成 HTML 内容时,以下是一些额外的考虑因素。

清理

如果你正在使用应用的 Documents 文件夹来存储临时文件,那么请记住在完成后删除它们。这可以通过 File 类的 deleteFile()deleteFileAsync() 方法完成。

使用 loadString()

StageWebView 类有一个 loadString() 方法,允许显示指定的 HTML 字符串。虽然这种方法可能比本食谱中概述的步骤更容易,但使用 loadString() 显示的 HTML 内容无法加载本地资源,如图像文件或样式表。

参见

  • 在应用内渲染网页

  • 在应用内渲染本地网页

捕获网页快照

可以将 StageWebView 对象视口的内 容复制到位图中。

在本食谱中,我们将捕获网页快照并在页面视口下方显示位图的缩略图。

准备工作

本食谱中涵盖的步骤仅适用于使用 Flash Professional CS5.5 和 AIR 2.6 或更高版本的用户。Flash Professional CS5 和 AIR 2.0 不支持 StageWebView 类。

从本书的配套代码包中,将 chapter11\recipe6\recipe.fla 打开到 Flash Professional CS5.5 中。FLA 的舞台是空的,但其 AIR for iOS 设置已经应用。

如何操作...

除了 StageWebView,我们还将使用 BitmapBitmapData 类来存储和显示快照。

  1. 创建一个新的文档类,并将其命名为 Main

  2. 添加以下导入语句并声明一个 StageWebView 成员变量:

    package {
     import flash.display.Bitmap;
    import flash.display.BitmapData; 
    import flash.display.MovieClip;
     import flash.events.Event;
    import flash.geom.Rectangle;
    import flash.media.StageWebView; 
    public class Main extends MovieClip {
    private var webView:StageWebView; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在构造函数中,设置 StageWebView 对象并监听其网页成功加载:

    public function Main() {
     webView = new StageWebView();
    webView.stage = stage;
    webView.viewPort = new Rectangle(
    0, 0, stage.stageWidth, stage.stageWidth);
    webView.addEventListener(Event.COMPLETE, loaded);
    webView.loadURL("http://www.yeahbutisitflash.com"); 
    }
    
    
  4. 最后,添加一个事件处理器,捕获加载页面的位图并显示其缩略图:

    private function loaded(e:Event):void {
    var bd:BitmapData = new BitmapData(
    webView.viewPort.width, webView.viewPort.height);
    webView.drawViewPortToBitmapData(bd);
    var b:Bitmap = new Bitmap(bd);
    b.x = 0;
    b.y = 320;
    b.width = 160;
    b.height = 160;
    addChild(b);
    }
    
    
  5. 当提示保存类时,将其文件命名为 Main.as

  6. 返回到 FLA 并保存它。

  7. 现在发布 FLA 并在你的设备上测试它。一旦网页加载完成,它的快照将被捕获并显示在屏幕左下角的缩略图位置。

它是如何工作的...

StageWebView类提供了drawViewPortToBitmapData()方法,该方法将StageWebView对象视口中的像素数据写入BitmapData对象。

首先,需要实例化一个BitmapData对象:

var bd:BitmapData = new BitmapData(
webView.viewPort.width, webView.viewPort.height);

然后,可以通过调用drawViewPortToBitmapData():将视口的可见部分绘制到BitmapData对象上。

webView.drawViewPortToBitmapData(bd);

必须注意确保BitmapData对象的尺寸与视口的尺寸相匹配。如果不匹配,则drawViewPortToBitmapData()将抛出ArgumentError异常。StageWebView.viewPort属性返回一个Rectangle,您可以使用它来确定视口的宽度和高度。

关于flash.display.Bitmapflash.display.BitmapData类的更多信息,请参阅 Adobe 社区帮助。

还有更多...

以下是一个捕捉网页快照的实际用途。

铺设显示对象

虽然StageWebView对象在 Flash 的显示列表之上渲染,但在不需要与 HTML 进行用户交互的情况下,可以在 HTML 内容之上放置显示对象。这是通过捕获StageWebView的位图图像并将其替换为位图来实现的。然后,您可以在位图表示之上添加按钮、面板和菜单等显示对象。要隐藏一个StageWebView对象,请将其stage属性设置为null

参见

  • 在应用内渲染网页

第十二章. 处理视频和音频

在本章中,我们将涵盖:

  • 播放本地 FLV 视频

  • 播放本地 H.264 视频

  • 控制视频

  • 嵌入音频

  • 播放嵌入音频

  • 流式音频

  • 控制音频播放

简介

随着载体能够支持更大的下载,iOS 硬件不断向前发展,开发者能够构建更大的应用程序。苹果公司本身也承认了这一点,将其空中下载限制翻倍,使得包括更多带宽密集型内容(如视频和高质量音频)成为可能。

在互联网上,Flash 平台多年来一直是视频和音频播放的领导者。Adobe AIR 将这些功能带到了 iOS,使得开发者能够创建能够吸引、启发和沉浸用户的 app。

本章将探讨处理视频和声音的许多选项。它将首先指导您完成包括和播放视频所需的步骤,然后转向处理嵌入和流式音频。

播放本地 FLV 视频

多年来,Flash 平台成功的关键是其 FLV 文件格式,它提供本地和互联网上的 Sorenson Spark 或 ON2 VP6 编码视频。

在这个菜谱中,我们将看到如何加载与 AIR for iOS 应用程序捆绑在一起的 FLV 视频。

准备工作

使用书中附带代码包中的chapter12\recipe1\recipe.fla作为起点。

此外,还有一个 FLV 视频可以从chapter12\resources\video.flv获取,并且在继续之前应该复制到chapter12\recipe1\

视频旨在在横向放置的设备上观看。为了满足这一要求,FLA 的舞台大小已被设置为 480x320 像素,而不是默认的纵向模式 320x480。

如何做到这一点...

这个菜谱分为两个主要步骤。首先我们将 FLV 视频与应用程序捆绑在一起,然后我们将编写一些 ActionScript 来播放它。

捆绑 FLV 视频

执行以下步骤将视频与应用程序捆绑在一起:

  1. 通过从 Flash 的下拉菜单中选择文件 | AIR for iOS 设置来打开 AIR for iOS 设置面板。

  2. 如果尚未选中,请点击面板的常规选项卡。

  3. 渲染字段设置为CPU

  4. 在面板底部是包含文件列表。点击列表上方的+符号,并选择chapter12\recipe1\video.flv。当 FLA 发布时,视频现在将与您的 IPA 文件捆绑在一起。

  5. 点击确定关闭 AIR for iOS 设置面板。

播放 FLV 视频

现在 FLV 已经包含在您的 FLA 中,我们可以将注意力转向播放它所需的 ActionScript。

  1. 创建一个文档类并命名为Main

  2. 将以下导入语句添加到类中:

    import flash.desktop.NativeApplication;
    
    import flash.desktop.SystemIdleMode; 
    import flash.display.MovieClip;
     import flash.media.Video;
    import flash.net.NetConnection;
    import flash.net.NetStream; 
    
    
  3. 声明一个常量来存储 FLV 视频的名称:

    static private const VIDEO_URL:String = "video.flv";
    
    
  4. 创建三个播放视频所需的成员变量:

    private var netConnection:NetConnection;
    private var netStream:NetStream;
    private var video:Video;
    
    
  5. 在构造函数中,加载并播放 FLV 视频:

    public function Main() {
     NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
    netConnection = new NetConnection();
    netConnection.connect(null);
    netStream = new NetStream(netConnection);
    netStream.client = this;
    netStream.play(VIDEO_URL);
    video = new Video();
    video.attachNetStream(netStream);
    video.width = 480;
    video.height = 320;
    addChildAt(video, 0); 
    }
    
    
  6. 您还需要提供回调方法来捕获 FLV 播放时的元数据和提示点事件。将以下两个空方法添加到您的文档类中:

    public function onMetaData(dataObj:Object):void {
    ; // Do nothing.
    }
    public function onXMPData(dataObj:Object):void {
    ; // Do nothing.
    }
    
    
  7. 保存类文件和 FLA 文件。

  8. 发布 FLA 并将 IPA 部署到您的设备上。

当应用程序启动时,它将从文件系统加载并播放 FLV 文件。

它是如何工作的...

我们的代码从设备本地加载 video.flv 文件,并将其播放给用户。应用程序捆绑的所有文件在安装期间都会复制到其应用程序目录中。这是应用程序本身所在的文件夹,也是 FLV 视频存储的位置。

加载和播放视频是一个涉及 NetConnectionNetStreamVideo 类的三阶段过程。

首先创建一个 NetConnection 对象,并将 null 传递给其 connect() 方法。这表示我们不会连接到 Flash 媒体服务器,而是打算连接到存储在设备文件系统中的文件或托管在 Web 服务器上的文件。对于这个示例,我们使用了与应用程序捆绑的本地 FLV 文件:

netConnection = new NetConnection();
netConnection.connect(null);

接下来创建一个 NetStream 对象,并用于播放实际的视频。将 NetConnection 对象传递给 NetStream 对象的构造函数,使其能够从设备流式传输本地视频:

netStream = new NetStream(netConnection);
netStream.client = this;
netStream.play(VIDEO_URL);

最后,将 NetStream 对象附加到 Video 对象上,允许视频显示给用户:

video = new Video();
video.attachNetStream(netStream);
video.width = 480;
video.height = 320;
addChildAt(video, 0);

Video 类继承自 flash.display.DisplayObject,这意味着它可以被添加到显示列表中,并以与其他所有显示对象相同的方式进行操作。我们使用的两个 DisplayObject 属性是 widthheight,用于设置屏幕上视频的大小。为了最大化播放性能,确保尺寸与 FLV 完全匹配。缩放 FLV 视频会降低性能。

注意,在这个示例中选择了 CPU 渲染。虽然可以使用 GPU,但硬件视频解码器无法解码任意分辨率,这有时会导致您的 Video 对象尺寸不正确。此外,如果您正在使用 Flash Professional CS5 和 AIR 2.0,则应完全避免视频的 GPU 渲染。

如需更多信息,请在 Adobe Community Help 中搜索 flash.net.NetConnectionflash.net.NetStreamflash.media.Video

还有更多...

现在,让我们回到元数据和提示点的话题。在继续之前,我们还将涉及一些其他考虑因素。

元数据和提示点事件

当视频播放时,可以使用其 NetStream 对象来捕获和处理提示点和各种元数据事件,包括 onMetaDataonXMPData

虽然这个示例不需要这些事件,但我们仍然必须为每个事件编写空回调处理程序。如果不这样做,当事件被触发时,将抛出一个运行时异常。

要处理这些事件,将NetStream对象的client属性设置为包含每个事件的回调方法的对象。方法名称必须与事件名称完全匹配。对于这个菜谱,我们简单地设置client属性为this,并将处理程序添加到文档类中。

有关如何实际使用提示点和元数据事件的数据的详细信息,请参阅help.adobe.com/en_US/as3/dev/WSD30FA424-950E-43ba-96C8-99B926943FE7.html

播放远程 FLV 视频

除了本地播放外,FLV 视频还可以从远程位置通过 HTTP 进行渐进式流式传输。只需将视频的 URL 传递给NetStream.play()方法即可开始播放。你还可以通过监听NetStream对象内部回放缓冲区的状态来确定NetStream对象的状态,方法是监听它分发NetStatusEvent.NET_STATUS

你可以在help.adobe.com/en_US/as3/dev/WS901d38e593cd1bac-3d11a09612fffaf8447-8000.html找到有关可用NetStream事件的更多信息。

屏幕锁定

当观看视频时,如果用户在一段时间内没有活动,屏幕将会变暗。在这个菜谱的构造函数中,我们通过将NativeApplication.systemIdleMode设置为SystemIdleMode.KEEP_AWAKE来防止这种情况发生。

虽然无限期地防止屏幕锁定在演示目的上是可接受的,但可能不适合实际应用。更好的做法是在视频播放期间禁用屏幕锁定,然后在视频暂停或停止时重新启用。

最大化播放性能

为了最大化性能,最小化你的显示列表,并在播放期间尽量避免在视频上方叠加其他图形元素。还尝试限制在播放期间执行的 ActionScript 的数量。这对于较老的第一代和第二代硬件尤其如此,因为 FLV 的性能可能会遇到困难。

如果你使用的是 AIR 3.0 SDK 或更高版本,那么考虑使用硬件加速的 H.264 视频,因为它的回放性能和视频质量显著更好。

捆绑多个视频

可以单独将文件添加到包含文件列表中,或者你可以指定一个包含文件夹。当你编写具有多个视频的应用程序时,这很方便,因为你可以在单个位置简单地分组文件。文件夹中的每个文件都将与你的 IPA 捆绑在一起。

参见

  • 播放本地 H.264 视频

  • 控制视频

  • 防止屏幕空闲,第三章

  • 理解 GPU 混合模式,第六章

播放本地 H.264 视频

AIR for iOS 现在支持高质量的、低比特率的 H.264 视频格式,通过StageVideo类实现最佳级别的高清播放。通过利用硬件加速,H.264 视频比 FLV 等类似格式减少了 CPU 使用率,并消耗更少的内存。

在本食谱中,我们将播放已与应用程序本地捆绑的 H.264 视频。

准备工作

这里所述的步骤仅适用于使用 AIR 3.0 及以上版本的用户。如果您使用的是 Flash Professional CS5,那么您将无法尝试此食谱。

从章节的配套代码包中,以chapter12\recipe2\recipe.fla作为起始点。

chapter12\resources\video.mp4提供的 H.264 编码视频,在继续之前应将其复制到chapter12\recipe2\

该视频旨在在横向持握的设备上观看。为了满足这一要求,FLA 的舞台大小已设置为 480x320 像素,而不是默认的纵向方向 320x480。

如何操作...

此食谱分为两个主要步骤。首先,我们将捆绑 H.264 视频与应用程序,然后编写一些 ActionScript 来播放它。

打包 H.264 视频

执行以下步骤以将视频与应用程序捆绑:

  1. 通过从 Flash 的下拉菜单中选择文件 | AIR for iOS 设置来打开 AIR for iOS 设置面板。

  2. 如果该选项尚未选中,请点击面板的常规选项卡。

  3. 渲染字段设置为GPU

  4. 在面板底部是包含的文件列表。点击列表上方的+符号,并选择chapter12\recipe2\video.mp4。当 FLA 发布时,该文件将捆绑到您的 IPA 文件中。

  5. 点击确定以关闭 AIR for iOS 设置面板。

播放 H.264 视频

现在视频已包含在您的 FLA 中,我们可以将注意力转向播放视频所需的 ActionScript。

  1. 创建一个文档类,并将其命名为Main

  2. 将以下导入语句添加到类中:

    import flash.desktop.NativeApplication;
    import flash.desktop.SystemIdleMode; 
    import flash.display.MovieClip;
    import flash.geom.Rectangle;
    import flash.media.StageVideo;
    import flash.net.NetConnection;
    import flash.net.NetStream; 
    
    
  3. 声明一个常量以存储视频的名称:

    static private const VIDEO_URL:String = "video.mp4";
    
    
  4. 创建三个用于播放视频的成员变量:

    private var netConnection:NetConnection;
    private var netStream:NetStream;
    private var video:StageVideo;
    
    
  5. 在构造函数中设置并播放视频:

    public function Main() {
     NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
    netConnection = new NetConnection();
    netConnection.connect(null);
    netStream = new NetStream(netConnection);
    netStream.client = this;
    video = stage.stageVideos[0];
    video.attachNetStream(netStream);
    video.viewPort = new Rectangle(0, 25, 480, 270);
    netStream.play(VIDEO_URL); 
    }
    
    
  6. 您还需要提供一个回调方法,以捕获视频播放时的元数据事件。将以下空方法添加到您的文档类中:

    public function onMetaData(dataObj:Object):void {
    ; // Do nothing.
    }
    
    
  7. 保存类文件和您的 FLA。

    注意

    AIR 调试启动器(ADL)目前不支持 H.264 视频播放。如果您尝试使用 ADL 测试此食谱,则将收到运行时错误。

  8. 发布 FLA 并将 IPA 部署到您的设备上。

当启动时,应用程序将从文件系统加载并播放 H.264 视频。

它是如何工作的...

我们的代码从设备本地加载video.mp4并播放给用户。应用程序捆绑的所有文件在安装期间都会复制到其应用程序目录中。这是应用程序本身所在的文件夹,也是 H.264 视频存储的位置。

加载和播放视频是一个涉及 NetConnection, NetStreamStageVideo 类的四步过程。

首先创建一个 NetConnection 对象,并将 null 传递给其 connect() 方法。这表示我们不会连接到 Flash 媒体服务器,而是打算连接到设备文件系统上存储的文件或托管在 Web 服务器上的文件。对于这个配方,我们使用了与应用程序捆绑的本地 FLV 文件:

netConnection = new NetConnection();
netConnection.connect(null);

接下来创建一个 NetStream 对象,并将用于播放实际视频。将 NetConnection 对象传递给 NetStream 对象的构造函数,允许它从设备流式传输本地视频:

netStream = new NetStream(netConnection);
netStream.client = this;

为了将视频显示给用户,NetStream 对象需要附加到 StageVideo 对象上。然而,你不需要自己显式创建一个。相反,可以从 Stage 对象的 stageVideos 属性提供的向量数组中获取一个 StageVideo 对象。在 iOS 设备上,这个向量将包含一个能够渲染视频的 StageVideo 实例:

video = stage.stageVideos[0];
video.attachNetStream(netStream);

最后一步是为视频创建一个视口并开始播放。由 StageVideo 类渲染的视频是硬件加速的,并且不是显示列表的一部分。相反,StageVideo 实例在显示列表后面的一个矩形区域内渲染,该区域指定了视频的绝对位置和大小。一旦定义了视口,就调用 NetStream 对象的 play() 方法:

video.viewPort = new Rectangle(0, 25, 480, 270);
netStream.play(VIDEO_URL);

用于此配方的视频大小为 400x224 像素,但你可能已经注意到,在上面的代码中,视口已被分配了一个 480x270 的矩形区域。这会将视频缩放到覆盖屏幕的整个水平宽度,同时仍然保持视频的宽高比。此外,视口向下移动了 25 像素,以确保它在屏幕上垂直居中。

对于这个配方,选择了 GPU 渲染。解码 H.264 视频计算成本高,需要硬件来确保在 iOS 设备上播放性能可接受。尽管视频不是显示列表的一部分,但它位于显示列表的后面,这意味着显示对象,如 UI 组件,可以叠加在顶部。

如需更多信息,请在 Adobe 社区帮助中搜索 flash.net.NetConnection, flash.net.NetStreamflash.media.StageVideo

还有更多...

现在,让我们回到元数据的话题。在继续之前,我们还将讨论一些其他注意事项。

元数据和提示点事件

当视频播放时,可以使用其 NetStream 对象捕获和处理提示点和各种元数据事件,包括 onMetaData, onCuePointonXMPData

虽然这个配方不需要 onMetaData 事件,但我们仍然必须为它编写一个空的回调处理程序。如果不这样做,当事件被触发时,将会抛出一个运行时异常。

为了处理此类事件和其他事件,将 NetStream 对象的 client 属性设置为包含每个事件的回调方法的对象。方法名称必须与事件名称完全匹配。对于本菜谱,我们只需将 client 属性设置为 this 并将处理程序添加到文档类中。

有关如何实际使用提示点和元数据事件的数据的详细信息,请参阅 help.adobe.com/en_US/as3/dev/WSD30FA424-950E-43ba-96C8-99B926943FE7.html

播放默认相机捕获的视频

使用 CameraUI 类成功捕获的视频暂时存储在设备的文件系统中。通过 CameraUI 分发的 MediaEvent 对象,可以确定视频的 URL 以便播放。以下是一个示例:

private function captured(e:MediaEvent):void {
var mediaPromise:MediaPromise = e.data;
var videoUrl:String = mediaPromise.file.url; 
playVideo(videoUrl);
}

一旦你有了 URL,你可以简单地将它传递给 NetStream 对象的 play() 方法以启动播放。

CameraUI 类在 第十章 的 使用默认相机应用捕获 菜单中有所介绍。

确定视频的大小

你可以从 StageVideo 对象的只读属性 videoWidthvideoHeight 中检索编码视频的宽度和高度。但是,首先你需要等待这些信息可用,通过监听从你的 StageVideo 实例分发的 StageVideoEvent.RENDER_STATE 事件来实现。

此外,在播放从设备相机捕获的视频时也要小心。在 iOS 上,相机以横向模式捕获视频。如果你的应用程序使用纵向宽高比,那么在指定视口尺寸时需要交换 videoWidthvideoHeight 属性的值。

更多信息,请在 Adobe Community Help 中搜索 flash.events.StageVideoEvent

播放远程 H.264 视频

除了本地播放外,H.264 视频还可以从远程位置通过 HTTP 逐步流式传输。只需将视频的 URL 传递给 NetStream.play() 方法即可开始播放。你还可以通过监听 NetStream 对象内部播放缓冲区的状态来确定 NetStream 对象的状态,该状态通过分发 NetStatusEvent.NET_STATUS 事件来实现。

你可以在 help.adobe.com/en_US/as3/dev/WS901d38e593cd1bac-3d11a09612fffaf8447-8000.html 找到更多关于可用 NetStream 事件的信息。

编码 H.264 视频

H.264 视频播放可能计算成本较高。由于 iOS 设备种类繁多,硬件配置广泛,因此采用正确的编码策略至关重要,以确保在最低的共同基数上播放。Adobe 在 www.adobe.com/devnet/devices/articles/mobile_video_encoding.html 提供了一些 H.264 编码建议。

您可以使用 Adobe Media Encoder 对视频进行编码,该编码器是 Flash Professional 的可选安装程序,并使用 H.264 编解码器。Adobe Media Encoder 的介绍可以在 Adobe 开发者连接网站上找到,网址为www.adobe.com/devnet/flash/quickstart/video_encoder.html

捆绑多个视频

可以单独将文件添加到包含文件列表中,或者指定一个文件夹以包含文件。当编写具有多个视频的应用程序时,这很方便,因为您只需将文件分组在单个位置即可。文件夹中的每个文件都将与您的 IPA 捆绑在一起。

参见

  • 控制视频

  • 防止屏幕空闲,第三章

  • 理解 GPU-Vector 模式,第六章

控制视频

除了开始播放外,NetStream类还提供了对视频的额外控制。在本菜谱中,我们将添加用户暂停、恢复和重新启动 FLV 或 H.264 视频的能力。

准备工作

从本书的配套代码包中,打开chapter12\recipe3-flv\recipe.flachapter12\recipe3-mp4\recipe.fla,并将其作为起点。第一个 FLA 的文档类包含为播放本地 FLV 视频菜谱编写的代码,而第二个 FLA 包含播放本地 H.264 视频菜谱的代码。

已将两个电影剪辑添加到舞台。第一个被赋予了实例名称blocker。第二个被命名为controls,位于blocker之前。这两个电影剪辑都将位于 FLV 或 H.264 视频之前。

controls电影剪辑中包含三个按钮,分别命名为playBtnrestartBtnresumeBtn。这些按钮将分别用于播放、重新开始和取消暂停视频。在播放过程中,点击屏幕上的任何位置都会暂停视频。

blocker电影剪辑具有 60%的透明度,当视频处于暂停状态时将用于降低视频亮度。在播放过程中,blocker将变为不可见,确保视频不被遮挡。以下截图显示了由blocker电影剪辑降低亮度的视频:

准备工作

在继续之前,您还需要将 FLV 或 H.264 视频复制到 FLA 的根目录。如果您正在使用 FLV 视频,则将chapter12\resources\video.flv复制到chapter12\recipe3-flv\。对于 H.264 视频,将chapter12\resources\video.mp4复制到chapter12\recipe3-mp4\

好的,让我们编写这个菜谱所需的 ActionScript。

如何操作...

打开 FLA 的文档类,并对其进行以下更改:

  1. 添加两个新的导入语句:

    import flash.events.MouseEvent;
    import flash.events.NetStatusEvent;
    
    
  2. 在构造函数中,监听NetStream实例分发NetStatusEvent.NET_STATUS事件:

    netStream = new NetStream(netConnection);
    netStream.client = this;
    netStream.addEventListener(NetStatusEvent.NET_STATUS, statusUpdated); 
    
    
  3. 此外,从构造函数中删除以下代码行:

    netStream.play(VIDEO_URL);
    
    

    注意

    在上面的行以及整个配方中,VIDEO_URL 是一个包含要播放的本地视频 URL 的常量。它将指向 video.flvvideo.mp4,具体取决于你是在处理 FLV 还是 H.264 视频。

    • 我们不再希望视频立即开始播放。相反,我们将等待用户轻触播放按钮。
  4. 最后,在构造函数的末尾,调用一个支持方法来设置播放控件:

    setupControls();
    
    
  5. 现在添加实际的 setupControls() 方法。为每个控制按钮添加一个事件监听器,并最初只显示播放按钮——我们将在视频暂停时显示其他按钮。

    private function setupControls():void {
    controls.playBtn.addEventListener(MouseEvent.MOUSE_UP, playVideo);
    controls.restartBtn.addEventListener(MouseEvent.MOUSE_UP, restartVideo);
    controls.resumeBtn.addEventListener(MouseEvent.MOUSE_UP, resumeVideo);
    stage.addEventListener(MouseEvent.MOUSE_UP, pauseVideo);
    showBtns(["playBtn"]);
    }
    
    
  6. 当按下播放按钮时,我们将开始播放视频并隐藏控件。添加以下事件处理程序来完成此操作:

    private function playVideo(e:MouseEvent):void {
    netStream.play(VIDEO_URL);
    hideBtns();
    e.stopPropagation();
    }
    
    
  7. 用户可以在播放期间通过在屏幕上任何地方轻触来暂停视频。当暂停时,控制面板的重置和恢复按钮将显示。为这个添加一个事件处理程序并暂停 NetStream 对象的视频流:

    private function pauseVideo(e:MouseEvent):void {
    if(controls.visible == false)
    {
    netStream.pause();
    showBtns(["resumeBtn", "restartBtn"]);
    }
    }
    
    
  8. 现在为重置按钮添加一个事件处理程序。此处理程序将使 NetStream 对象的视频回到开始,并隐藏控件:

    private function restartVideo(e:MouseEvent):void {
    netStream.seek(0);
    netStream.resume();
    hideBtns();
    e.stopPropagation();
    }
    
    
  9. 为重置按钮编写一个类似的处理程序,取消暂停 NetStream 对象的视频流:

    private function resumeVideo(e:MouseEvent):void {
    netStream.resume();
    hideBtns();
    e.stopPropagation();
    }
    
    
  10. 我们还希望用户在视频播放完成后有机会再次观看视频。为 NetStream 对象的 NET_STATUS 事件编写一个处理程序,如果视频已停止则显示播放按钮:

    private function statusUpdated(e:NetStatusEvent):void {
    if(e.info.code == "NetStream.Play.Stop")
    {
    showBtns(["playBtn"]);
    }
    }
    
    
  11. 我们即将完成。添加以下两个支持方法来管理控制按钮和遮挡器的可见性:

    private function hideBtns():void {
    controls.visible = false;
    blocker.visible = false;
    }
    private function showBtns(btns:Array):void {
    controls.visible = true;
    blocker.visible = true;
    for(var instName:String in controls)
    {
    if(btns.indexOf(instName) != -1)
    {
    controls[instName].visible = true;
    }
    else
    {
    controls[instName].visible = false;
    }
    }
    }
    
    
  12. 保存你的文档类并回到 FLA。

  13. 在你的设备上发布并测试应用程序。

它是如何工作的...

以下三个 NetStream 类的方法被用来控制视频播放:

  • pause(): 暂停当前视频流

  • resume(): 恢复暂停的视频流的播放

  • seek(): 移动到视频流中的特定时间点

seek() 方法期望一个时间,以秒为单位,用于移动到。实际上这是一个近似值,因为 NetStream 对象将移动到最接近该时间的键帧。

应注意,不应使用 play() 方法来恢复播放。它仅用于开始播放。相反,调用 resume() 以继续播放暂停的视频。

NetStream 类不提供 stop() 方法。在我们的代码示例中,暂停的视频是通过定位到第一个关键帧然后恢复播放从开始重新启动的。

还有更多...

在我们离开视频并转到音频之前,这里有一些最后的话。

NetStream 状态

NetStatusEvent 对象在响应大量有用的状态变化、错误和警告时被触发。以下是一些可以查询 info.code 属性的字符串:

  • NetStream.Play.Start: 播放已开始

  • NetStream.Play.Stop: 播放已停止

  • NetStream.Play.StreamNotFound: 无法找到视频文件

  • NetStream.Play.InsufficientBW: 客户端没有足够的带宽以期望的帧率播放视频

  • NetStream.Pause.Notify: 流已暂停

  • NetStream.Unpause.Notify: 流已暂停

  • NetStream.Buffer.Flush: 播放结束,缓冲区现在为空

您可以通过检查 info.level 属性来确定代码的类型,该属性将被设置为以下字符串之一:status, errorwarning。要获取支持字符串的完整列表,请在 Adobe Community Help 中搜索 flash.events.NetStatusEvent

flash.net.NetConnection 对象也会派发 NetStatusEvent 对象,您可以监听这些对象。

关闭视频流

当您完成视频并不再需要它时,调用 NetStream 对象的 close() 方法。这将停止视频播放并使流可用于其他用途。

嵌入音频

声音是任何应用程序的重要组成部分,并且当正确应用时,可以沉浸用户于交互体验中。为了提供这种体验,在播放过程中最小化延迟是很重要的。例如,在播放游戏音效或从用户界面提供音频反馈时,不应有延迟。

Flash 允许将声音文件直接嵌入到库中,为您的音频提供最快的播放路径。让我们一步步了解完成此操作所需的步骤。

如何操作...

在 FLA 库中嵌入声音的步骤如下:

  1. 从 Flash Professional 中,通过选择 文件 | 新建 (Ctrl + N | Cmd + N) 创建一个新的 AIR for iOS 文档。从 新建文档 面板中选择 AIR for iOS 文档类型,然后点击 确定 按钮。

    注意

    如果您是 Flash Professional CS5 用户,那么它被称为 iPhone OS 文档而不是 AIR for iOS 文档。

  2. 从 Flash 的下拉菜单中选择 文件 | 导入 | 导入到库。将出现一个文件浏览器窗口。

  3. 从浏览器窗口中,导航到并选择 chapter12\resources\sound.mp3。点击 打开 按钮。声音文件将被导入并在库面板中列出为 sound.mp3

  4. 在库面板中,右键单击 sound.mp3 并从下拉菜单中选择 属性。将打开 声音属性 面板。

  5. 声音属性 面板中,从 压缩 下拉框中选择 ADPCM。确保选中 将立体声转换为单声道 复选框;将 采样率 设置为 22kHzADPCM 位4 位。如果您使用的是 Flash Professional CS5.5,那么,如以下截图所示,请确保首先选中面板的 选项 选项卡。如何操作...

  6. 现在检查导出为 ActionScript复选框,并将字段中的文本更改为SoundEffect。如果您使用的是 Flash Professional CS5.5,则应从面板的ActionScript选项卡执行此操作。

  7. 单击确定按钮关闭面板。

  8. 根据您在 Flash Professional 中的首选项设置,可能会出现包含以下文本的警告面板:

    无法在类路径中找到此类定义,因此将在导出 SWF 文件时自动生成。

    这是预期的。单击确定按钮继续。声音文件已被分配了一个名为 SoundEffect 的 ActionScript 类名。

  9. 保存您的 FLA 文件。

它是如何工作的...

在您的库中嵌入声音文件将它们直接放置在应用程序的二进制文件中,使它们立即可用于播放。然而,以这种方式添加声音文件将增加您的应用程序文件大小。您的应用程序越大,加载所需的时间就越长,消耗的内存就越多。在嵌入声音文件之前,请仔细考虑您是否真的需要立即访问它。

选择合适的音频编解码器对于您的嵌入声音也很重要。Flash 提供两种类型的编解码器:压缩和非压缩。压缩声音,如 MP3,比非压缩声音,如 ADPCM,占用更少的空间。然而,设备需要在播放时解码音频,这可能会很耗时,尤其是如果您试图同时播放多个压缩声音。

如果您需要同时播放多个声音文件并且具有最小延迟,则使用非压缩编解码器。Flash 提供 ADPCM 和 RAW 用于此目的。当然,使用非压缩音频会增加您的应用程序内存占用。

如果您一次只播放一个声音,则选择 MP3。这样做将减少您的应用程序内存占用。

如果您想使用 ActionScript 访问您的嵌入音频,则必须为库中的每个声音分配一个唯一的类名。在本菜谱中,我们将类名SoundEffect分配给了我们的嵌入声音。

参见

  • 创建 iOS 的 AIR 文档,第二章

  • 播放嵌入音频

播放嵌入音频

可以使用 ActionScript 播放 FLA 库中嵌入的声音文件。声音必须有一个与之关联的唯一类名。

在本菜谱中,我们将介绍如何播放此类嵌入声音。

准备工作

从书籍的代码包中,将chapter12\recipe5\recipe.fla打开到 Flash Professional 中,并将其作为起点使用。

来自“嵌入音频”菜谱的嵌入声音可以在 FLA 的库中找到,并且有一个名为SoundEffect的类名与之关联。

此外,舞台上还有一个名为playBtn的按钮。我们将在此按钮被按下时播放嵌入的声音。

如何操作...

执行以下步骤以播放与SoundEffect类关联的声音:

  1. 创建一个名为Main的文档类。

  2. 导入MouseEvent类并监听playBtn被按下:

    package {
    import flash.display.MovieClip;
    import flash.events.MouseEvent; 
    public class Main extends MovieClip {
    public function Main() {
    playBtn.addEventListener(MouseEvent.MOUSE_UP, playSound); 
    }
    }
    }
    
    
  3. 现在为按钮添加一个事件处理程序,并在其中创建嵌入声音的SoundEffect类的实例:

    private function playSound(e:MouseEvent):void {
    var soundEffect:SoundEffect = new SoundEffect();
    }
    
    
  4. 在处理程序内部,调用SoundEffect对象的play()方法:

    private function playSound(e:MouseEvent):void {
    var soundEffect:SoundEffect = new SoundEffect();
    soundEffect.play(); 
    }
    
    
  5. 保存您的类文件和 FLA 文件。

  6. 发布应用程序并在您的设备上测试它。轻触按钮以启动声音的播放。重复轻触按钮以启动多个实例。

它是如何工作的...

使用flash.media.Sound对象播放音频。所有用于 ActionScript 的链接嵌入声音都将继承自这个类。

要使用嵌入的声音,只需实例化它,然后调用它的play()方法。这只是Sound类提供的许多方法和属性之一。

在此菜谱中,我们使用了一个具有SoundEffect类名的嵌入声音文件。以下两行代码就足以播放它:

var soundEffect:SoundEffect = new SoundEffect();
soundEffect.play();

当调用play()时,会创建一个SoundChannel对象来播放声音。连续调用play()会创建新的SoundChannel对象,它们独立地播放自己的声音副本。您可以通过在此菜谱示例应用程序中重复轻触播放按钮来听到这个效果。

虽然在这个菜谱中我们没有用到它,但play()方法返回一个对新实例化的SoundChannel对象的引用,该对象可以用来控制声音的播放。这在本章的控制音频播放菜谱中有详细说明。

更多内容...

让我们看看在播放声音时可供选择的一些更多选项。

播放位置

play()方法有几个默认参数,其中第一个参数从声音中的指定位置开始播放。以下示例显示了从开始点 500 毫秒处开始播放:

soundEffect.play(500);

如果省略,声音将从开头播放。

循环

可以通过将值传递给play()方法的第二个参数来循环播放声音。在以下示例中,声音从开始点 200 毫秒处连续播放六次:

soundEffect.play(200, 6);

如果省略,播放将只发生一次。

相关内容

  • 嵌入音频

  • 控制音频播放

流式音频

当处理大型声音文件时,您可能希望将它们放在应用程序的二进制文件之外,以减少其加载时间和内存消耗。Sound类可以从网络或从设备的文件系统流式传输 MP3 文件,从而无需直接在 FLA 中嵌入音频。

在此菜谱中,我们将 MP3 文件与应用程序捆绑在一起,并逐步播放它。

准备工作

为此菜谱提供了一个.mp3文件。使用 Windows 资源管理器或 Finder,将chapter12\resources\music.mp3从书籍的配套代码包中复制到chapter12\recipe6\

在 Flash Professional 中打开chapter12\recipe6\recipe.fla。位于舞台中央的是一个名为playBtn的按钮。我们将编写一些 ActionScript,以便在按下此按钮时流式传输music.mp3

如何做到...

此配方将分为两部分。首先,我们将与应用程序捆绑一个 MP3 文件,然后我们将编写播放它所需的 ActionScript。

捆绑 MP3 文件

按照以下步骤将.mp3文件与应用程序捆绑:

  1. 通过从 Flash 的下拉菜单中选择文件 | AIR for iOS 设置来打开 AIR for iOS 设置面板。

  2. 如果尚未选中,请单击面板的常规选项卡。

  3. 在面板底部是包含的文件列表。在列表上方点击+符号,并选择chapter12\recipe6\music.mp3。当 FLA 发布时,该文件将与应用程序捆绑在一起。

  4. 点击确定关闭 AIR for iOS 设置面板。

播放 MP3 文件

现在 MP3 已包含在您的 FLA 中,让我们将注意力转向流式传输它所需的 ActionScript。

  1. 创建一个名为Main的文档类。

  2. 将以下导入语句添加到类中:

    package {
    import flash.display.MovieClip;
     import flash.events.MouseEvent;
    import flash.media.Sound;
    import flash.net.URLRequest; 
    public class Main extends MovieClip {
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 在构造函数中,监听playBtn被按下:

    public function Main() {
    playBtn.addEventListener(MouseEvent.MOUSE_UP, playSound); 
    }
    
    
  4. 现在,让我们添加按钮的事件处理程序。在其内部,为本地music.mp3文件创建一个URLRequest对象:

    private function playSound(e:MouseEvent):void {
    var url:URLRequest = new URLRequest("music.mp3");
    }
    
    
  5. 最后,将请求传递给一个新的Sound对象,并调用其play()方法:

    private function playSound(e:MouseEvent):void {
    var url:URLRequest = new URLRequest("music.mp3");
    var sound:Sound = new Sound(url);
    sound.play(); 
    }
    
    
  6. 保存您的类文件和 FLA。

  7. 发布应用程序并在您的设备上进行测试。轻触按钮以启动.mp3文件的流式传输。重复轻触按钮以启动多个实例。

它是如何工作的...

除了播放嵌入式音频外,flash.media.Sound类还可以流式传输外部声音文件。所采用的技术与播放 FLV 或 H.264 视频时使用的渐进式下载技术相同,可用于与应用程序捆绑或存储在网络上存储的声音文件。

虽然 Flash 支持压缩和非压缩嵌入式音频,但只有.mp3文件可以使用Sound类直接流式传输。因此,建议将同时流式传输的外部文件数量保持在最低,因为解码音频可能计算成本高昂。

使用Sound类播放.mp3文件很简单。首先需要创建一个声音文件的URLRequest

var url:URLRequest = new URLRequest("music.mp3");

然后将请求传递给一个新的Sound实例。当调用Sound对象的play()方法时,文件开始流式传输:

var sound:Sound = new Sound(url);
sound.play();

一旦调用play()Sound对象就不能与另一个.mp3文件一起使用。要流式传输不同的文件,请创建一个新的Sound对象。

更多...

以下细节适用于 Flash 中的一般声音,但在处理存储在设备文件系统或网络上的 MP3 文件时尤其重要。

增加缓冲时间

如果音频数据消耗速度超过加载速度,则播放将暂停,直到Sound对象的内部缓冲区再次填满。

为了帮助防止缓冲区下溢,您可以在播放开始之前增加已收集的数据的毫秒数。使用 flash.media.SoundLoaderContext 对象来指定缓冲时间,并将其传递给 Sound 对象的构造函数:

var context:SoundLoaderContext = new SoundLoaderContext(9000);
var sound:Sound = new Sound(request, context);

此示例指定缓冲区必须包含 9000 毫秒的音频数据,播放才能继续。默认值为 5000 毫秒。

您可以查询Sound对象的isBuffering属性以确定音频是否在加载更多数据时被暂停。

监控加载进度

在加载过程中,Sound对象会触发多个事件,可以帮助您监控其进度:

  • Event.COMPLETE: 声音的数据已完全加载

  • ProgressEvent.PROGRESS: 随着数据的接收定期触发

  • IOErrorEvent.IO_ERROR: 声音文件找不到

此外,ProgressEvent 类提供了 bytesLoadedbytesTotal 属性,可以用来确定文件加载了多少。

声音长度

Sound 类提供了一个 length 属性,可以用来确定当前声音的长度(以毫秒为单位)。当处理流式声音时,请注意,此属性将仅返回已加载的数据的长度。如果您想了解完整声音文件的持续时间,那么请先等待 Sound 对象触发 Event.COMPLETE 事件。

声音元数据

MP3 音频可以包含以 ID3 标签形式存在的元数据,这些标签包含诸如标题、艺术家、专辑和曲目编号等信息。如果一个文件包含 ID3 元数据,那么其Sound对象将触发Event.ID3事件。您可以监听此事件,然后使用Sound对象的id3属性来读取标签。

以下代码示例显示了如何枚举id3属性以发现声音文件中嵌入的所有标签:

private function ID3InfoReceived(e:Event):void {
var id3:ID3Info = e.target.id3;
for(var prop:String in id3)
{
trace(prop + ": " + id3[prop]);
}
}

ID3Info 类可以在 flash.media 包中找到。

处理原始 PCM 声音数据

虽然Sound类主要允许加载和播放外部 MP3 文件,但 AIR 3.0 提供了一种新的方法来处理未压缩的 PCM 声音数据。loadPCMFromByteArray()方法将来自ByteArray对象的 PCM 32 位浮点声音数据注入到Sound对象中。

在后台播放音频

从 AIR 3.0 开始,您可以编写可以在后台继续播放音频的多任务应用程序。这是通过在您的应用程序描述符文件中插入 UIBackgroundModes 键来实现的:

<iPhone>
<InfoAdditions>
<![CDATA[<key>UIDeviceFamily</key>
<array><string>1</string></array>
<key>UIBackgroundModes</key>
<array><string>audio</string></array>]]> 
</InfoAdditions>

当应用程序关闭时,任何正在播放的音频将继续播放。

参见

  • 嵌入音频

  • 控制音频播放

  • 编辑应用程序描述符文件,第三章

控制音频播放

为每个播放的声音创建一个SoundChannel对象。使用类的 API,你可以控制声音的播放。

在这个食谱中,我们将学习如何暂停和恢复声音。

准备工作

书籍附带代码包中提供了一个.mp3文件和一个 FLA 文件。

chapter12\recipe7\recipe.fla打开到 Flash Professional 中。在舞台中央有一个名为playBtn的按钮。在直接位于其下的图层中是另一个名为pauseBtn的按钮。在这个食谱中,我们将编写 ActionScript 在两个按钮之间切换,以指示 MP3 是否正在播放。

我们将要使用的 MP3 文件可以在chapter12\resources\music.mp3中找到。在继续之前,将其复制到 FLA 的根文件夹chapter12\recipe7\中。

如何操作...

这个食谱分为两个主要步骤。首先,我们将 MP3 与应用程序捆绑在一起,然后我们将编写用于控制其播放的 ActionScript。

捆绑 MP3 文件

让我们先捆绑.mp3文件到你的应用程序中:

  1. 通过从 Flash 的下拉菜单中选择文件 | AIR for iOS 设置来打开 AIR for iOS 设置面板。

  2. 如果尚未选择,请点击面板的常规选项卡。

  3. 在面板底部是包含的文件列表。点击列表上方的+符号,并选择chapter12\recipe7\music.mp3。当 FLA 发布时,该文件将捆绑到你的 IPA 文件中。

  4. 点击确定关闭 AIR for iOS 设置面板。

控制播放

现在 MP3 文件已经包含在内,让我们专注于 ActionScript:

  1. 创建一个文档类,并将其命名为Main

  2. 导入此食谱所需的类:

    import flash.display.MovieClip;
     import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.net.URLRequest; 
    
    
  3. 声明以下成员变量,我们将使用它们来控制声音:

    private var sound:Sound;
    private var channel:SoundChannel;
    private var pausePosition:int;
    
    
  4. 在构造函数中,为每个按钮添加事件监听器,并最初隐藏暂停按钮:

    public function Main() {
     pausePosition = 0;
    playBtn.addEventListener(MouseEvent.MOUSE_UP, playSound);
    pauseBtn.addEventListener(MouseEvent.MOUSE_UP, pauseSound);
    pauseBtn.visible = false; 
    }
    
    
  5. 注意,pausePosition成员变量已经被初始化。每次 MP3 暂停时,我们将使用停止的时间更新此变量。

  6. 当按下播放按钮时,MP3 的播放应从第一次开始,或者从上次暂停的地方继续。我们还需要监听 MP3 播放完成。此外,应显示暂停按钮,使用户能够在某个点停止 MP3。

    为了管理所有这些,添加以下事件处理程序:

    private function playSound(e:MouseEvent):void {
    if(sound == null)
    {
    var url:URLRequest = new URLRequest("music.mp3");
    sound = new Sound(url);
    }
    channel = sound.play(pausePosition);
    channel.addEventListener(Event.SOUND_COMPLETE, complete);
    toggleBtn();
    }
    
    
  7. 当暂停 MP3 播放时,需要获取并存储达到的当前时间点。此外,应再次提供播放按钮,使用户能够方便地继续播放。以下代码块处理此操作:

    private function pauseSound(e:MouseEvent):void {
    pausePosition = channel.position;
    channel.stop();
    channel.removeEventListener(Event.SOUND_COMPLETE, complete);
    toggleBtn();
    }
    
    
  8. 添加一个事件处理程序,当 MP3 播放完成时被调用。这将重置pausePosition成员变量,并再次使播放按钮可见,使用户能够重新开始 MP3 的播放:

    private function complete(e:Event):void {
    channel.removeEventListener(Event.SOUND_COMPLETE, complete);
    audio playbackcontrollingpausePosition = 0;
    toggleBtn();
    }
    
    
  9. 最后添加以下支持方法,用于在播放和暂停按钮之间切换:

    private function toggleBtn():void {
    playBtn.visible = !playBtn.visible;
    pauseBtn.visible = !pauseBtn.visible;
    }
    
    
  10. 现在保存你的类文件和 FLA 文件。

  11. 发布应用并在您的设备上测试它。通过按下播放和暂停按钮切换播放。

它是如何工作的...

当调用 Sound.play() 方法时,会创建并返回一个 SoundChannel 对象。SoundChannel 对象负责单个声音的播放。连续调用 Sound.play() 将返回额外的 SoundChannel 对象,每个对象播放 Sound 对象的独立副本。

虽然 play() 调用最初会从头到尾播放声音,但 SoundChannel 类的 API 可以用于执行其他操作。在这个菜谱中,我们利用该类为用户提供暂停和恢复功能。

在播放过程中,无法真正暂停声音;SoundChannel 类仅提供停止播放的方法。然而,您可以存储声音停止时的位置,稍后从该位置重新播放声音。

这是通过在停止声音之前存储 position 属性来实现的。position 属性返回声音的时间位置,以毫秒为单位:

pausePosition = channel.position;
channel.stop();

通过传递存储的位置到 Sound.play() 来恢复播放。这样做会从指定的时间点播放 MP3,并返回一个表示它的新的 SoundChannel 对象:

channel = sound.play(pausePosition);

记住,pausePosition 成员变量在构造函数中被初始化为 0。这保证了第一次按下播放按钮时,MP3 的播放将从开头开始。

当声音播放完毕时,其 SoundChannel 对象将触发一个 Event.SOUND_COMPLETE 事件。

虽然我们在这个菜谱中使用了外部 MP3,但嵌入到库中的声音播放也是以相同的方式进行控制的。

更多信息,请在 Adobe Community Help 中搜索 flash.media.Soundflash.media.SoundChannel

还有更多...

这里有一些关于声音控制的相关信息。

音量和声像

声音的音量和立体声声像也可以进行控制。为此,创建一个 flash.media.SoundTransform 对象,并将其传递给 SoundChannel 对象的 play() 方法或对象的 soundTransform 属性。

SoundTransform 对象的构造函数接受两个参数:声音的音量和指定其左右声像的值。音量范围从 0(静音)到 1(全音量),而声像范围从 -1(完全左偏)到 1(完全右偏)。

以下是一个示例,其中声音以全音量播放并硬声像左偏:

soundTransform = new SoundTransform(1, -1);
soundChannel = sound.play(0, 1, soundTransform);

在播放过程中,可以调整声音的音量和声像。只需更改您的 SoundTransform 对象并将其分配给 SoundChannel 对象的 soundTransform 属性:

soundTransform.pan = 0;
soundTransform.volume = 0.5;
soundChannel.soundTransform = soundTransfrom;

注意使用 SoundTransform 对象的 panvolume 属性来进行所需的更改。

在测试立体声声像时,请注意您需要使用耳机,因为 iOS 设备上发现的扬声器仅提供单声道声音。

全球音量

除了个别声音外,还可以使用flash.media.SoundMixer类全局控制音量和声像。它有一个自己的soundTransform属性,当设置该属性时,会影响所有正在播放的声音。

参见

  • 播放嵌入音频

  • 流式音频

第十三章. 连接性、持久性和 URI 方案

在本章中,我们将涵盖:

  • 监控互联网连接

  • 指定持久的 Wi-Fi 连接

  • 引用应用的公共目录

  • 编写文件

  • 读取文件

  • 启动系统应用

  • 启动 App Store

  • 启动地图应用

  • 声明设备功能

简介

在本书的整个过程中,我们已经覆盖了很多内容,但有一些我们触及的话题值得更多关注。在本章中,我们将通过探索应用描述符文件的一些额外用途,花时间了解如何访问设备的文件系统,以及如何从 Flash 打开原生 iOS 应用来整理这些悬而未决的问题。

监控互联网连接

对于移动应用来说,在某个时刻连接到互联网是一种常见现象。对于许多人来说,这将是简单的任务,例如提交用户的分数或发布到社交网络网站。更复杂的应用可能试图从各种来源聚合数据,甚至从 Flash 媒体服务器流式传输视频。

在尝试发送或接收数据之前检查设备是否具有活跃的互联网连接是一种良好的做法。如果找不到活跃的连接,则应用可以相应地调整。例如,一个游戏可能会隐藏其在线排行榜并移除上传分数的任何设施。

此菜谱将向您展示如何使用 AIR 的 URLMonitor 类在调用之前检查 URL 的可用性。

准备工作

已提供了一个 FLA 作为起点。

从本书的配套代码包中,将 chapter13\recipe1\recipe.fla 打开到 Flash Professional。

一个名为 output 的动态文本字段覆盖了舞台。我们将编写一些动作脚本以检查互联网连接并在文本字段中显示结果。

如何操作...

URLMonitor 类属于 air.net 包,并在 AIR 运行时中未定义。相反,该类包含在 aircore.swc 文件中,在使用之前必须将其静态链接到您的 FLA。

链接 SWC 文件

在编写此菜谱的动作脚本之前,让我们将 aircore.swc 链接到 FLA。

  1. 从 Flash Professional 的下拉菜单中选择 文件 | 动作脚本设置。这将打开动作脚本 3.0 设置面板,您可以在其中添加 SWC。

  2. 选择 库路径 选项卡。点击 添加新路径 图标,它由一个 + 符号表示。

  3. 现在点击 浏览到 SWC 文件 图标,并从您的 Flash 安装文件夹中选择 aircore.swc。其位置取决于您使用的 Flash Professional 版本。对于 CS5,浏览到:Adobe Flash CS5\AIK2.5\frameworks\libs\air\aircore.swc。如果您使用的是 CS5.5,它位于:Adobe Flash CS5.5\AIR2.6\frameworks\libs\air\aircore.swc

    注意

    在 Microsoft Windows 上,你的 Flash Professional 安装可以在C:\Program Files (x86)\Adobe找到。在 32 位 Windows 版本上,路径将是C:\Program Files\Adobe

    如果你正在使用 Mac OS X,那么你的 Flash 安装可以在以下位置找到:Macintosh HD/Applications

    链接 SWC 文件

  4. SWC 将被添加到在发布应用程序时使用的库列表中。通过单击其路径左侧的图标展开 SWC 文件的条目,并确保其链接类型选项设置为合并到代码

  5. 点击确定以关闭面板。

检查连接性

aircore.swc链接到你的 FLA 文件后,你现在可以使用URLMonitor类提供的 API。好的,现在让我们编写一些 ActionScript 代码。

  1. 创建一个文档类,并将其命名为Main

  2. 添加以下三个导入语句,以及一个URLMonitor成员变量:

    package {
     import air.net.URLMonitor; 
    import flash.display.MovieClip;
     import flash.events.StatusEvent;
    import flash.net.URLRequest; 
    public class Main extends MovieClip {
    private var monitor:URLMonitor; 
    public function Main() {
    // constructor code
    }
    }
    }
    
    
  3. 创建一个检查特定 HTTP 请求可用性的URLMonitor实例,并监听其dispatching StatusEvent.STATUS

    public function Main() {
     var request:URLRequest = new URLRequest(
    "http://www.yeahbutisitflash.com");
    monitor = new URLMonitor(request);
    monitor.addEventListener(StatusEvent.STATUS, statusUpdated);
    monitor.start(); 
    }
    
    
  4. URLMonitor对象的STATUS事件编写一个处理程序:

    private function statusUpdated(e:StatusEvent):void {
    if(monitor.available)
    {
    output.text = "Internet connection available.";
    }
    else
    {
    output.text = "Internet connection unavailable.";
    }
    }
    
    
  5. 将该类保存为Main.as,然后返回到你的 FLA 文件。

  6. 发布 FLA 文件并在你的设备上测试应用程序。以下文本应显示在屏幕上:

    互联网连接可用

  7. 尝试将你的文档类更改为监控一个不存在的 URL。重新发布并测试你的应用程序。这次你将收到以下消息:

    互联网连接不可用

它是如何工作的...

URLMonitor类监控并检测指定 URL 的 HTTP 或 HTTPS 连接变化。

其构造函数接受一个URLRequest作为参数,其中包含要探测的 URL。在创建URLMonitor对象后,调用其start()方法开始监控。

当确定 URL 的可用性时,URLMonitor对象将派发StatusEvent.STATUS。你可以查询StatusEvent对象的available属性以确定是否可以建立到 URL 的连接。

监控将持续进行,直到调用URLMonitor.stop()方法。也可以通过检查URLMonitor.running属性来确定是否正在进行监控。

如需更多信息,请在 Adobe 社区帮助中搜索air.net.URLMonitor

还有更多...

这里有一些额外的细节。

监控套接字

air.net.SocketMonitor类与URLMonitor类似,但检测指定端口的主机连接变化。这对于需要套接字服务器连接的应用程序,如多人游戏,非常有用。

SocketMonitor类的构造函数期望传入要监控的主机名和端口号:

monitor = new SocketMonitor("www.example.com", 6667);

一旦实例化,SocketMonitor对象的使用方式与URLMonitor相同。

轮询间隔

URLMonitorSocketMonitor都提供了一个pollInterval属性,可以用来指定一个以毫秒为单位的间隔,用于定期轮询服务器。

默认情况下,其值为 0,这意味着在调用 start() 后,服务器将立即轮询,之后仅在网络状态改变时才会轮询。

相关内容

  • 指定持久的 Wi-Fi 连接

指定持久的 Wi-Fi 连接

虽然许多应用程序定期连接到互联网,但也有一些,如聊天客户端和多用户游戏,需要持续连接。如果没有持续连接,这类应用程序可能会变得毫无用处。通过编辑其应用程序描述符文件,您可以指定您的应用程序需要连接到 Wi-Fi 网络的持续连接。

让我们看看如何做这件事。

准备工作

从本书的配套代码包中,将 chapter13\recipe2\recipe.fla 打开到 Flash Professional 中,并从这里开始工作。其文档类包含上一个示例中的代码,监控互联网连接性。如果您没有尝试过这个示例,请不要担心,因为理解它不是必需的。

如何操作...

您可以从外部文本编辑器或从 Flash Professional 中编辑您的应用程序描述符文件。我们将使用 Flash Professional。

  1. 通过从 Flash Professional 的下拉菜单中选择 文件 | 打开 (Ctrl + O | Cmd + O) 打开应用程序描述符文件。从文件浏览器中,选择 recipe-app.xml

  2. 将文件向下滚动,直到找到以下 XML 片段:

    <iPhone>
    <InfoAdditions>
    <![CDATA[<key>UIDeviceFamily</key>
    <array><string>1</string></array>]]>
    </InfoAdditions>
    
    
  3. CDATA 节点中,将以下键值对添加到 XML 中:

    <iPhone>
    <InfoAdditions>
    <![CDATA[<key>UIDeviceFamily</key>
    <array><string>1</string></array>
    <key>UIRequiresPersistentWiFi</key><true/>]]> 
    </InfoAdditions>
    
    
  4. 保存文件。

  5. 现在发布 FLA,并将生成的 .ipa 文件安装到您的设备上。

  6. 在启动应用程序之前,停止您的设备自动连接到您的 Wi-Fi 网络。从您的设备设置中,选择 Wi-Fi,然后点击网络名称右侧的图标。这样做将带您进入该网络的设置页面。从这里,按 忘记此网络 按钮,然后按 忘记如何操作...

  7. 现在返回到设备的主屏幕并启动您的应用程序。iOS 会注意到应用程序需要持久的 Wi-Fi 连接,并将显示一个原生对话框,要求您 选择无线网络。从列表中选择您的网络,并在提示时输入其密码。

    初始时,您的应用程序将报告以下内容:

    互联网连接不可用

    但在短暂的瞬间后,它将检测到您的网络连接,并将状态更新如下:

    互联网连接可用

它是如何工作的...

您的 FLA 应用描述符是一个包含 iOS 特定设置的 XML 文件。在 <iPhone> 节点中是 <infoAdditions> 节点,您可以在其中设置不能在 Flash 中设置的自定义键值对。这些用于描述应用程序或当应用程序启动时直接使用。

对于这个示例,我们使用了以下键值对来提醒用户当找不到持久的 Wi-Fi 连接时:

<key>UIRequiresPersistentWiFi</key><true/>

当应用启动时,它会检测这个键的存在,因此会检查设备是否连接到活动的 Wi-Fi 网络。如果没有,它将执行搜索并显示一个网络选择对话框,其中包含用户可以选择的活跃 Wi-Fi 热点列表。或者,如果设备处于飞行模式,则显示一个对话框通知用户这一点。

Wi-Fi 硬件可能会消耗大量电力。为了节省电池,iOS 会自动在 30 分钟后关闭其 Wi-Fi 硬件。如果你的应用使用了 UIRequiresPersistentWiFi 键,那么 Wi-Fi 硬件将保持开启状态,直到应用保持活跃。如果设备的屏幕锁定,那么应用将被视为不活跃,Wi-Fi 连接可能会丢失。

你可以通过将其值设置为 <false/> 来关闭 UIRequiresPersistentWiFi 键。或者,也可以从应用程序描述符文件中删除整个条目。

相关内容

  • 编辑应用程序描述符文件,第三章

引用应用程序的常用目录

iOS 应用位于其自己的目录中,并可以访问包含在其内部的常用子目录。

这个菜谱将向你展示如何引用这些目录中的每一个。

准备工作

我们将使用书中附带代码包中的 chapter13\recipe3\recipe.fla 作为起点。将其打开到 Flash Professional 中。

在舞台上可以找到一个名为 output 的动态文本字段。我们将使用这个文本字段来显示应用程序每个常用目录的本地文件路径。

如何操作...

执行以下步骤:

  1. 创建一个新的文档类,并将其命名为 Main

  2. 导入 File 类:

    import flash.display.MovieClip;
    import flash.filesystem.File; 
    
    
  3. 在构造函数中,将每个目录的本地路径写入 output 文本字段:

    public function Main(){
    output.text = "Application Directory:\n" + File.applicationDirectory.nativePath + "\n\nApplication Storage Directory:\n" + File.applicationStorageDirectory.nativePath + "\n\nDocuments Directory:\n" + File.documentsDirectory.nativePath + "\n\nUser Directory:\n" + File.userDirectory.nativePath; 
    }
    
    
  4. 保存类,并在提示时将文件命名为 Main.as

  5. 最后,发布 FLA 文件并在你的设备上测试它。所有四个目录的路径将在屏幕上显示。

工作原理...

存储应用的目录被称为 应用程序主页,其路径类似于:/var/mobile/Applications/97C9F144-E97A-40BB-A4CD-82FF31CA2A3C。路径末尾的字符串是一个唯一标识应用程序的 ID,并在安装期间用于命名主目录。

flash.filesystem.File 类提供了几个常量,可用于引用应用程序主页及其各种子目录。这些常量允许你以平台无关的方式访问目录,从而消除了记住长串本地路径的需要。它们是:

  • File.userDirectory: 应用程序主页目录

  • File.applicationDirectory: 一个只读目录,包含应用程序的二进制文件以及与之捆绑的任何文件,例如默认启动屏幕

  • File.applicationStorageDirectory: 任何本地共享对象数据都存储在这里

  • File.documentsDirectory: 任何应用程序特定的数据都可以写入并从这个目录中检索

在这四个中,applicationDirectorydocumentsDirectory 可能是使用最频繁的两个。虽然您不能向应用程序目录写入,但您可以从中读取,甚至可以将文件从其中复制到其他位置。

文档目录对于状态管理很有用,允许存储应用程序所需的数据文件。这些文件可以是任何东西,从简单的偏好文件到用户创建的图像。此目录的内容由 iTunes 备份。

如果您希望临时存储文件,则应用程序主目录中提供了一个 tmp 子目录。要引用未作为常量提供的文件夹,请使用 File 类的 resolvePath() 方法修改现有的 File 对象。例如:

var tmpDir:File = File.userDirectory.resolvePath("tmp");

还提供了一个 nativePath 属性,允许您从 File 对象引用中检索目录的本地路径:

var nativePath:String = File.applicationDirectory.nativePath;

当使用期望本地路径而不是 File 对象的 API 时,这很有用。

更多信息,请在 Adobe Community Help 中搜索 flash.filesystem.File

更多内容...

在使用 File 类和目录时,还有一些其他选项。

创建目录

除了引用现有目录外,File 类还允许您使用其 createDirectory() 方法创建目录。以下两行代码在应用程序的 Documents 目录中创建了一个名为 images 的目录:

var dir:File = File.documentsDirectory.resolvePath("images");
dir.createDirectory();

您也可以使用 deleteDirectory()deleteDirectoryAsync() 删除目录。在异步删除目录时,监听 Event.COMPLETE 事件。

参见

  • 写入文件

  • 读取文件

写入文件

AIR 提供了一个文件系统 API,可以用于将任何类型的文件写入设备。

让我们看看如何写入包含简单偏好数据的文本文件,例如,可能被游戏使用。

准备工作

已提供一个 FLA 作为本菜谱的起点。

从本书的配套支持文件中,将 chapter13\recipe4\recipe.fla 打开到 Flash Professional。

阶段上有一个名为 output 的动态文本字段。我们将向设备写入一些偏好数据,并使用文本字段来指示数据已被写入。

如何操作...

flash.filesystem 包包含提供文件系统访问的类。让我们利用其中的一些类将数据写入设备。

  1. 创建一个名为 Main 的文档类。

  2. 导入以下类:

    import flash.display.MovieClip;
    import flash.events.Event;
     import flash.events.IOErrorEvent;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream; 
    
    
  3. 添加一个 FileFileStream 成员变量:

    private var file:File;
    private var stream:FileStream;
    
    
  4. 创建一个将偏好数据写入设备的方法,并在构造函数中调用它:

    public function Main() {
    savePreferences();
    }
    private function savePreferences():void {
    file = File.documentsDirectory.resolvePath("prefs.txt");
    stream = new FileStream();
    stream.addEventListener(IOErrorEvent.IO_ERROR, ioError);
    stream.addEventListener(Event.CLOSE, fileSaved);
    stream.openAsync(file, FileMode.WRITE);
    stream.writeUTFBytes(
    "music_vol=0.5&sound_vol=0.7&difficulty=easy");
    stream.close();
    }
    
    
  5. 添加一个处理程序,如果写入偏好数据时发生错误,则会调用它:

    private function ioError(e:IOErrorEvent):void {
    output.appendText(e.errorID + ": " + e.text);
    }
    
    
  6. 添加第二个处理程序,一旦文件已成功写入设备文件系统,则会调用它:

    private function fileSaved(e:Event):void {
    output.appendText("File Saved\n");
    }
    
    
  7. 保存类文件,并在提示时将其命名为 Main.as

  8. 在您的设备上发布 FLA 并进行测试。偏好文件将被写入,屏幕上将显示以下文本:

    文件已保存

它是如何工作的...

此配方利用了flash.filesystem.Fileflash.filesystem.FileStream类将数据写入设备的文件系统。数据通过一系列写入应用程序文档目录的文本文件中的名称-值对表示。

在向文件写入时,必须首先使用File类获取表示它的引用——即使对于尚未创建的文件也是如此。除了表示文件外,File类还可以用来表示目录。通过使用File.resolvePath(),可以进一步细化目录引用,以指向相对于它的文件或子目录。

以下行代码展示了为偏好文件创建的File对象:

file = File.documentsDirectory.resolvePath("prefs.txt");

下一步是实例化一个FileStream对象,并使用openAsync()方法对其进行初始化以进行写入:

stream = new FileStream();
stream.openAsync(file, FileMode.WRITE);

如您所见,File对象被传递给openAsync()。作为第二个参数,还传递了FileMode.WRITE常量,表示数据将被写入文件。如果指定的文件不存在,则openAsync()将创建它。如果它已经存在,则其内容将被清除。

FileStream类在写入数据时触发各种事件。如果它无法创建或找到文件,则触发IOErrorEvent.IO_ERROR事件,一旦它已将数据写入文件,则触发Event.CLOSE事件。应添加对这两个事件的监听器:

stream = new FileStream();
stream.addEventListener(IOErrorEvent.IO_ERROR, ioError);
stream.addEventListener(Event.CLOSE, fileSaved); 
stream.openAsync(file, FileMode.WRITE);

文件打开用于写入后,调用writeUTFBytes()实际上将文本写入文件:

stream.writeUTFBytes(
"music_vol=0.5&sound_vol=0.7&difficulty=easy");

最后一步是关闭FileStream对象,以防止更多数据被写入:

stream.close();

重要的是要理解,在您调用close()方法时,文件不一定已经完全写入。当向设备写入大量数据时,可能需要一些时间。如果是这种情况,则FileStream对象将延迟关闭文件,直到所有数据都写入完毕。一旦完成,FileStream对象将触发Event.CLOSE事件。

虽然您可以在应用程序主目录内的任何位置写入文件,但由于沙盒限制,您不能在目录外写入。

您可以从 Adobe 社区帮助中获取有关flash.filesystem.FileStream, flash.filesystem.Fileflash.filesystem.FileMode类的更多信息。

还有更多...

这里有一些更详细的说明,这些说明在向设备的本地文件系统写入时可能很有用。

处理数据格式

FileStream类提供了许多用于写入数据的方法。您选择的方法取决于您希望使用的数据格式。

例如,当处理文本时,您有writeUTF(), writeUTFBytes()writeMultiByte()方法可用。如果您选择使用字节数组,则还有writeByte()writeBytes()方法。您甚至可以使用writeBoolean(), writeDouble(), writeFloat(), writeInt()writeShort()来写入原始数据。

同步写入

本食谱使用了openAsync(),这意味着数据可以异步写入设备。异步操作在后台进行,允许您的 ActionScript 代码继续执行,而不是在操作完成之前被阻塞。

作为openAsync()的替代方案,FileStream类还提供了open(),它允许以同步方式处理数据。尽管执行将在操作完成之前被阻塞,但同步工作更直接,因为您不需要注册事件。在以下代码片段中,您可以看到savePreferences()方法的替代版本,它以同步方式写入数据:

private function savePreferences():void {
file = File.documentsDirectory.resolvePath("prefs.txt");
stream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeUTFBytes(
"music_vol=0.5&sound_vol=0.7&difficulty=easy");
stream.close();
output.appendText("File Saved\n");
}

注意

本书中的示例在写入设备文件系统时,都是同步进行的,以帮助保持对当前任务的关注。

监控进度

当异步写入文件时,FileStream对象将定期触发OutputProgressEvent.OUTPUT_PROGRESS事件。从该事件对象中,您可以通过检查其bytesPendingbytesTotal属性来监控写入操作的进度。bytesPending属性指定了还需要写入的字节数,而bytesTotal表示到目前为止已写入的字节数。

持久化

写入文件系统允许您将应用程序的状态保存到设备上。当应用重新启动时,它可以使用这些保存的数据从上次离开的地方继续。

作为 AIR 文件系统 API 的替代方案,您还可以使用 Flash 的SharedObject类来管理状态。此外,可以使用在 AIR 3.0 中引入的EncryptedLocalStore类存储少量私有数据。有关加密本地存储的详细信息,请参阅 Adobe 社区帮助。

另一个选项是将您的数据存储在本地 SQLite 数据库中,并使用 ActionScript 来访问它。苹果本身在 iOS 设备上使用 SQLite 数据库来存储信息,例如联系人。

关系型数据库理论和 SQLite API 不在此书的范围之内。然而,您可以从 Adobe 社区帮助或访问 SQLite 网站获取更多关于此主题的信息:sqlite.org

参见

  • 保存应用程序状态,第四章

  • 引用应用程序的常见目录

  • 读取文件

读取文件

AIR 提供了一个文件系统 API,可以用来从设备读取任何类型的文件。

在本食谱中,我们将看到如何加载之前写入设备上的文件。

准备工作

如果您还没有这样做,请在继续之前完成写入文件食谱。

您可以继续使用在该食谱中编写的代码。或者,从本书的配套代码包中,将chapter13\recipe5\recipe.fla打开到 Flash Professional 中,并从那里开始工作。

如何操作...

让我们更新 FLA 的文档类,以加载并显示写入到设备上的首选项。

  1. 打开文档类。

  2. 添加一个将加载首选项数据的方法:

    private function loadPreferences():void {
    file = File.documentsDirectory.resolvePath("prefs.txt");
    stream = new FileStream();
    stream.addEventListener(IOErrorEvent.IO_ERROR, ioError);
    stream.addEventListener(Event.COMPLETE, fileLoaded);
    stream.openAsync(file, FileMode.READ);
    }
    
    
  3. 修改类的 fileSaved() 处理程序,使其调用前面的方法:

    private function fileSaved(e:Event):void {
    output.appendText("File Saved\n");
    loadPreferences(); 
    }
    
    
  4. 当文件已加载时,将分派一个 COMPLETE 事件。添加一个处理程序来解析和显示文件的偏好数据:

    private function fileLoaded(e:Event):void {
    var prefs:String = stream.readUTFBytes(stream.bytesAvailable);
    stream.close();
    var vars:URLVariables = new URLVariables(prefs);
    output.appendText(
    "File Loaded\n" +
    "music volume: " + vars.music_vol + "\n" + "sound volume: " + vars.sound_vol + "\n" + "difficulty: " + vars.difficulty + "\n"
    );
    }
    
    
  5. fileLoaded() 处理程序使用 Flash 的 URLVariables 类来解码首选项数据。将 URLVariables 添加到文档类的导入语句列表中:

    import flash.net.URLVariables;
    
    
  6. 保存 Main.as

  7. 发布 FLA 并在您的设备上测试它。

应用程序将首先将首选项数据写入文件系统,然后再将其加载回并显示在屏幕上的首选项。

它是如何工作的...

从设备文件系统读取数据所需的步骤几乎与写入数据相同。

首先创建一个 File 对象,它引用目标文件:

file = File.documentsDirectory.resolvePath("prefs.txt");

然后使用 openAsync() 方法实例化并初始化 FileStream 对象。当正在读取文件而不是写入文件时,将 FileMode.READ 作为方法的第二个参数传递:

stream = new FileStream();
stream.openAsync(file, FileMode.READ);

当写入文件时,FileSystem.close()openAsync() 后立即调用,但在读取时,不应调用它,直到获取文件的全部数据。这可以通过监听 FileStream 对象分派 Event.COMPLETE 来确定。

要实际获取数据,需要使用 FileSystem 类的读取方法之一。对于此配方,使用了 readUTFBytes(),并将从文件缓冲区读取的字节数传递给它:

var prefs:String = stream.readUTFBytes(stream.bytesAvailable);
stream.close();

在调用 readUTFBytes() 时使用了 FileStream 类的只读 bytesAvailable 属性。此属性表示文件完全加载后的大小。注意,文件流在读取数据后关闭,因为不再需要它。

更多...

您会发现 AIR 的文件系统 API 对于许多 iOS 项目非常有价值。在我们离开这个主题之前,这里有一些最终的信息要带在身边。

处理数据格式

FileStream 类提供了许多从文件读取数据的方法。您选择的方法取决于您正在读取的数据格式。

例如,当处理文本时,有 readUTF(), readUTFBytes(),readMultiBytes() 方法可用。如果文件包含字节数组,则可以使用 readByte()readBytes() 方法。可以使用 readBoolean(), readDouble(), readFloat(), readInt(), 和 readShort() 获取原始类型。

同步读取

与之前的配方一样,使用了 openAsync(),这意味着文件是异步处理的。以下代码使用 open() 方法来同步读取此配方的首选项文件:

private function loadPreferences():void {
file = File.documentsDirectory.resolvePath("prefs.txt");
stream = new FileStream();
stream.open(file, FileMode.READ);
var prefs:String = stream.readUTFBytes(stream.bytesAvailable);
stream.close();
}

注意

本书中的示例从设备文件系统读取数据,这样做是为了同步,以帮助保持对当前任务的关注。

监控进度

当异步读取文件时,FileStream对象将定期派发ProgressEvent.PROGRESS事件。从该事件对象中,你可以通过检查其bytesLoadedbytesTotal属性来监控读取进度。bytesLoaded属性指定已加载的字节数,而bytesTotal表示如果文件成功加载,将加载的字节数。

删除文件

你可以使用File类的deleteFile()deleteFileAsync()方法删除文件。在异步删除时,监听Event.COMPLETE事件。

其他文件模式

还有两种其他文件模式可用:FileMode.APPENDFileMode.UPDATE

追加模式始终将数据写入文件末尾,这意味着现有文件的数据将被添加而不是被破坏。

更新模式允许你使用单个文件流从文件中读取和写入。为了成功管理这一点,FileStream类提供了position属性,可以用来确定和设置文件中的当前位置。每次写入或读取一个字节时,position属性都会增加。也可以通过设置此属性来移动到文件中的任何位置。这样做后,下一次读取或写入操作将从该位置开始。

参见

  • 引用应用程序的常用目录

  • 写入文件

启动系统应用程序

有时你可能希望你的应用程序提供 iOS 系统应用程序已经提供的功能。为了保证一致和熟悉的使用体验,可以启动某些系统应用程序,而不是在应用程序内部执行任务。为了启用此功能,iOS 支持各种 URI 方案,可以用来启动特定的应用程序。

在本食谱中,你将学习如何使用mailto URI 方案从邮件应用程序打开和发送电子邮件。

准备工作

从本书的配套代码包中,将chapter13\recipe6\recipe.fla加载到 Flash Professional 中,并将其作为起点使用。

在其舞台上有一个名为mailBtn的按钮。当按下时,它将启动设备的邮件应用程序并为用户预填充一封电子邮件以便发送。

让我们编写实现这一功能的 ActionScript 代码。

如何实现...

我们将使用 Flash 的navigateToURL()函数和URLRequest类来启动邮件应用程序。

  1. 创建一个文档类,并将其命名为Main

  2. 导入以下内容:

    import flash.display.MovieClip;
     import flash.events.MouseEvent;
    import flash.net.navigateToURL;
    import flash.net.URLRequest; 
    
    
  3. 在构造函数中,监听按钮被按下:

    public function Main() {
    mailBtn.addEventListener(MouseEvent.MOUSE_UP, sendMail); 
    }
    
    
  4. 创建一个方法,用于启动邮件应用程序并编写电子邮件。在其中,初始化表示收件人电子邮件地址、主题标题和电子邮件正文的字符串:

    private function sendMail(e:MouseEvent):void {
    var address:String = "someone@somewhere.com";
    var subject:String = "Flash iOS Apps Cookbook";
    var body:String = "Sent from the Mail application.";
    }
    
    
  5. 在此代码中,将某人@somewhere.com替换为你希望的目标电子邮件地址。出于测试目的,请使用你自己的地址。

  6. sendMail()方法中保持,构建一个使用mailto URI 方案的 URL:

    private function sendMail(e:MouseEvent):void {
    var address:String = "someone@somewhere.com";
    var subject:String = "Flash iOS Apps Cookbook";
    var body:String = "Sent from the Mail application.";
    var url:String = "mailto:" + address + "?subject=" + subject + "&body=" + body;
    var request:URLRequest = new URLRequest(url); 
    }
    
    
  7. 最后,通过将 URL 传递给 Flash 的navigateToURL()函数来启动邮件应用:

    private function sendMail(e:MouseEvent):void {
    var address:String = "someone@somewhere.com";
    var subject:String = "Flash iOS Apps Cookbook";
    var body:String = "Sent from the Mail application.";
    var url:String = "mailto:" + address + "?subject=" + subject + "&body=" + body;
    var request:URLRequest = new URLRequest(url);
    navigateToURL(request); 
    }
    
    
  8. 保存类文件,并在提示时将其命名为Main.as

  9. 发布 FLA 并在您的设备上测试应用。点击按钮将打开邮件应用,并包含预先填充的电子邮件。

它是如何工作的...

mailto URI 用于启动邮件应用并撰写电子邮件。URI 必须正确构建和格式化,以便邮件应用能够理解它。一旦构建完成,将请求传递给 Flash 的navigateToURL()包级函数以实际启动应用。

至少,必须在mailto URI 中指定收件人的电子邮件地址:

mailto:someone@somewhere.com

您还可以通过在 URI 中添加查询字符串参数来预先填充电子邮件中的字段。例如,以下预先填充了电子邮件的主题和正文字段:

mailto:someone@somewhere.com?subject=Test&body=This is a test

支持的查询字符串参数如下:

  • subject: 电子邮件的主题字段

  • body: 电子邮件的主体

  • to: 允许在“收件人”字段中添加多个收件人

  • cc: 允许将收件人添加到抄送字段

  • bcc: 允许将收件人添加到密件抄送字段

当在字段中添加多个收件人时,使用逗号分隔每个地址。

电子邮件的主体可以指定为纯文本或 HTML。以下是一个使用 HTML 的示例:

mailto:someone@somewhere.com?body=<a href='http://www.yeahbutisitflash.com'>Yeah But Is It Flash?</a>

mailto规范禁止在 URI 中选择电子邮件账户。当多个账户与设备关联时,始终使用默认账户。附件也不受支持。

在 iOS 4 或更高版本上启动系统应用会强制当前应用进入后台。在 iOS 4 之前的设备上,当前应用将完全关闭。因此,在打开系统应用之前存储您应用的状态是明智的。当用户完成使用系统应用后,他们将从设备的主屏幕或快速应用切换器重新启动您的应用。

还有更多...

我们已经介绍了mailto URI 方案,现在让我们看看可以通过navigateToURL()打开的几个其他应用。

拨打电话号码

tel URI 方案可用于启动 iPhone 的电话应用并拨打指定的号码。以下示例显示了tel URI 的格式非常简单:

tel:1-408-555-5555

大多数有效的电话号码都被接受,但为了防止恶意行为,包含*#字符的 URI 不被接受。当使用tel URI 方案时,电话号码必须在 URI 中指定。

发送短信消息

可以使用sms URI 方案打开 iPhone 的消息应用。可以包含一个可选的电话号码,表示要创建新的短信消息:

sms:1-408-555-1212

如果省略电话号码,则消息应用将打开,但不会为用户创建要发送的消息。

无法预先填充文本消息或指定多个收件人。

播放 YouTube 视频

navigateToURL() 函数可以用来启动本地的 YouTube 应用。没有特定的 URI 方案;相反,使用一个针对 YouTube 服务器的 URL。

简单地构造一个包含您想播放的视频 ID 的 URL。该 URL 应采用以下格式:http://www.youtube.com/watch?v=ID。您可以通过访问 YouTube 网站,并从浏览器的地址栏中提取视频 ID 来获取视频的 ID。

这里是一个可以传递给 navigateToURL() 的示例 URL:

http://www.youtube.com/watch?v=awNMSiGzuRk

HTML 中的 URI 方案

URI 方案也可以嵌入到 HTML 页面中的链接。这允许用户在 StageWebView 对象内启动系统应用。例如,以下 HTML 链接将启动一个电话呼叫:

<a href="tel:1-408-555-5555">Call us now!</a>

关于 StageWebView 类的更多信息,请参阅第十一章。

参见

  • 优雅地退出应用,第三章

  • 在 Safari 中打开网页,第十一章

  • 启动 App Store

  • 启动 Maps 应用

启动 App Store

出版商经常在他们最新的发布中推广他们的旧作品,在 App Store 中为他们的每个产品提供直接链接。这不仅使购买过程对用户来说极其简单,而且也鼓励冲动购买。

您可以直接从您的 AIR for iOS 应用中启动 App Store,通过传递特定的 iTunes URL 到 Flash 的 navigateToURL() 函数。让我们看看如何做到这一点。

准备工作

已提供 FLA 文件作为本菜谱的起点。

从本书的配套代码包中,将 chapter13\recipe7\recipe.fla 打开到 Flash Professional 中。在其舞台上有名为 storeBtn 的按钮。

让我们编写一些 ActionScript 代码,当按下此按钮时启动 App Store。

如何操作...

我们将打开 WeeWorld 的 WeeMee Avatar Creator 应用的 App Store 页面。首先,我们将获取应用页面的 URL,然后我们将编写实际的代码来从我们的应用中链接到它。

获取应用的 URL

构造 URL 格式比较复杂。为了简化过程,苹果创建了在线链接制作工具。

  1. 访问其网页:itunes.apple.com/linkmaker获取应用的 URL

  2. 通过填写页面字段来定义搜索。在搜索字段中输入WeeMee Avatar Creator,将国家设置为USA,并从媒体类型下拉菜单中选择iOS Apps

  3. 点击页面右侧的搜索按钮以启动搜索。将生成一个匹配列表,并显示在页面底部。

  4. iPhone Apps部分查找WeeMee Avatar Creator,然后在其条目的右侧点击iPhone App 链接。将出现一个包含应用详细信息的对话框。

  5. 从对话框中复制直接链接URL。

从 ActionScript 链接到应用程序

现在我们将编写启动 App Store 页面的 ActionScript。

  1. 在 Flash Professional 中创建一个新的文档类,并将其命名为Main

  2. 添加所需的导入语句,并监听storeBtn被按下:

    package {
    import flash.display.MovieClip;
     import flash.events.MouseEvent;
    import flash.net.navigateToURL;
    import flash.net.URLRequest; 
    public class Main extends MovieClip {
    public function Main() {
    storeBtn.addEventListener(MouseEvent.MOUSE_UP, openAppStore);
    }
    }
    }
    
    
  3. 为按钮添加事件处理程序,并在其中使用从链接制作工具获取的 URL 打开 App Store:

    private function openAppStore(e:MouseEvent):void {
    var url:String = "http://itunes.apple.com/us/app/weemee-avatar-creator/id352506978?mt=8&uo=4";
    var request:URLRequest = new URLRequest(url);
    navigateToURL(request);
    }
    
    
  4. 现在保存文档类的文件,并在提示时将其命名为Main.as

  5. 在您的设备上发布并测试应用程序。轻触按钮以在 App Store 应用程序中打开 WeeMee 头像创建器的条目。

它是如何工作的...

将一个应用的合法 iTunes URL 传递给 Flash 的navigateToURL()包级函数将打开该应用的 App Store 应用程序。特定应用的 URL 可以从苹果的链接制作在线工具中检索。

不仅可以从您的应用程序中打开 App Store,链接制作工具还可以创建指向 iTunes Store 和 iBookstore 内容的链接。只需对相关内容进行搜索,然后获取其 URL。

不同的商店也可以从StageWebView对象内的 HTML 链接中启动。链接制作工具在直接链接URL 的同一对话框中提供所需的 HTML。您可以从带有链接的 HTML文本框中复制它。

参见

  • 在应用程序内渲染网页,第十一章

  • 启动系统应用程序

  • 启动地图应用程序

启动地图应用程序

由于 iOS 具有位置感知功能,因此地图是 iOS 的一个基本组成部分。本机地图应用程序允许您找到您当前的位置,搜索附近的兴趣点,并获得逐个转弯的指示。许多开发人员通过直接从自己的应用程序中打开地图来利用地图,为用户提供一致的经验。

让我们看看如何做到这一点。

准备工作

从书籍的配套代码包中,将chapter13\recipe8\recipe.fla打开到 Flash Professional 中。

在其舞台上有按钮,实例名为mapBtn。当按下此按钮时,我们将添加代码以显示 Adobe 总部的位置。

如何做到这一点...

我们将使用 Flash 的URLRequest类和navigateToURL()函数来打开地图应用程序。

  1. 创建一个文档类,并将其命名为Main

  2. 导入此菜谱所需的类,并监听按钮被按下:

    package {
    import flash.display.MovieClip;
     import flash.events.MouseEvent;
    import flash.net.navigateToURL;
    import flash.net.URLRequest; 
    public class Main extends MovieClip {
    public function Main() {
    mapBtn.addEventListener(MouseEvent.MOUSE_UP, openMaps); 
    }
    }
    }
    
    
  3. 最后,为按钮添加事件处理程序,并在其中打开 Adobe 总部的地图应用程序:

    private function openMaps(e:MouseEvent):void {
    var addr:String = "Adobe Systems Inc, 345 Park Avenue, " +
    "San Jose, CA";
    var url:String = "http://maps.google.com/maps?q=" + addr;
    var request:URLRequest = new URLRequest(url);
    navigateToURL(request);
    }
    
    
  4. 保存类,并在提示时将其文件命名为Main.as

  5. 在您的设备上发布并测试应用程序。轻触按钮。本机地图应用程序将打开,并显示 Adobe 总部的位置。

它是如何工作的...

如果您的应用程序包含地址或位置信息,您可以将这些信息转发到地图应用程序。为此,构造一个 URL 并将其传递给 Flash 的navigateToURL()包级函数。该 URL 应针对 Google Maps 服务器并包含一个或多个 Google Maps 参数。

对于这个菜谱,使用了 Google Maps 查询参数来映射 Adobe 总部的位置:

http://maps.google.com/maps?q=Adobe Systems Inc, 345 Park Avenue, San Jose, CA

地图应用程序支持许多 Google Maps 参数,但并非全部。以下是一个支持参数的列表:

参数 描述
q 查询参数。其值被视为已输入到 Google Maps 网页上的查询框中。
near 可以用作查询的位置部分。
ll 地图中心点的纬度和经度。
sll 商业搜索应进行的纬度和经度。
spn 大约的纬度和经度跨度。缩放级别将进行调整以适应。
sspn 屏幕跨度。缩放级别将进行调整以适应。
t 要显示的地图类型。可以选择 m 表示地图,k 表示卫星,或 h 表示混合。
z 地图的缩放级别,范围从 1 到 20。
saddr 生成方向时使用的源地址。
daddr 生成方向时使用的目标地址。
latlng Google 用于识别商业的自定义 ID 格式。
cid Google 用于识别商业的另一种自定义 ID 格式。

启动地图应用程序会将当前应用程序在 iOS 4 或更高版本上置于后台。在 iOS 4 之前的设备上,当前应用程序将完全关闭。因此,在打开地图之前存储应用程序的状态是明智的。当用户完成地图应用程序的使用后,他们将从设备的首页或快速应用程序切换器重新启动您的应用程序。

访问 mapki.com/wiki/Google_Map_Parameters 了解每个 Google Maps 参数的详细描述。

还有更多...

这里是地图应用程序的一些其他常见用途。

生成方向

您可以指示地图应用程序在两个地址之间生成方向。以下 ActionScript 代码片段使用 Google Maps 的 saddrdaddr 参数生成 Adobe 和苹果公司总部的驾驶方向:

var saddr:String = "Adobe Systems, 345 Park Avenue, San Jose";
var daddr:String = "Apple, 1 Infinite Loop, Cupertino";
var url:String = "http://maps.google.com/maps?" + "saddr=" + saddr + "&daddr=" + daddr;
var request:URLRequest = new URLRequest(url);
navigateToURL(request);

映射您的当前位置

您还可以显示用户的当前位置。这可以通过使用 AIR 的 Geolocation 类确定他们的近似位置,并将该信息传递给地图应用程序来实现。

以下 ActionScript 从 GeolocationEvent 对象中获取纬度和经度,并构建 Google Maps URL:

private function geoUpdated(e:GeolocationEvent):void {
var lat:Number = e.latitude;
var lon:Number = e.longitude;
var url:String = "http://maps.google.com/maps?" + "ll=" + lat + "," + lon;
var request:URLRequest = new URLRequest(url);
navigateToURL(request);
}

ll 属性用于指定位置的纬度和经度。两个值之间用逗号分隔。

相关内容

  • 确定您的当前位置,第九章

  • 启动系统应用程序

  • 启动 App Store

声明设备功能

iOS 设备的硬件和软件功能各不相同。例如,一些设备具有内置摄像头,而另一些则没有。确保您的应用程序只能下载并安装在其兼容的设备上非常重要。为此,可以为您的应用程序显式设置所需的功能。

您不能直接从 Flash Professional 指定这些功能。相反,您需要编辑 FLA 的应用程序描述符文件。让我们看看如何为一个需要原生消息应用程序和内置 GPS 接收器的应用程序执行此操作。

准备工作

从书籍的配套代码包中打开 chapter13\recipe9\recipe.fla 并从那里开始工作。FLA 的舞台是空的,但其 AIR for iOS 设置已经应用,让您准备好发布。

如何操作...

让我们在 Flash Professional 内部编辑您的应用程序描述符文件。

  1. 从 Flash Professional 中选择 文件 | 打开 并选择 recipe-app.xml

  2. 将文件向下滚动,直到找到以下 XML 片段:

    <iPhone>
    <InfoAdditions>
    <![CDATA[<key>UIDeviceFamily</key>
    <array><string>1</string></array>]]>
    </InfoAdditions>
    
    
  3. CDATA 节点中,将以下键值对添加到 XML 中:

    <iPhone>
    <InfoAdditions>
    <![CDATA[<key>UIDeviceFamily</key>
    <array><string>1</string></array>
     <key>UIRequiredDeviceCapabilities</key>
    <array>
    <string>sms</string>
    <string>gps</string>
    </array>]]> 
    </InfoAdditions>
    
    
  4. 保存文件。

  5. 发布 FLA。如果您有一部缺少原生消息应用程序或 GPS 的 iOS 设备,那么尝试安装 .ipa 文件。您将收到类似于以下错误消息的信息:

    应用程序 "c13 r9" 未安装,因为它与此设备不兼容。

工作原理...

您的 FLA 应用程序描述符是一个包含 iOS 特定设置的 XML 文件。在 <iPhone> 节点内是 <infoAdditions> 节点,您可以在其中设置不能在 Flash 中设置的定制键值对。这些键值对用于描述应用程序或当应用程序启动时直接使用。

UIRequiredDeviceCapabilities 键用于指定应用程序所需的功能。如果设备缺少这些功能,则应用程序将无法安装。

每个功能都应该列在 <array> 节点内:

<key>UIRequiredDeviceCapabilities</key>
<array>
<string>sms</string>
<string>gps</string>
</array>

此示例 XML 片段显示了 smsgps 功能的列表。sms 功能规定您的应用程序需要消息应用程序的存在,而 gps 则表示设备应包含 GPS 硬件。

可以使用 UIRequiredDeviceCapabilities 键指定以下功能:

功能 描述
telephony 应用程序需要电话应用程序的存在。
wifi 应用程序将访问设备的网络功能。
sms 应用程序需要消息应用程序的存在。
still-camera 捕获照片需要摄像头。
auto-focus-camera 捕获照片需要具备自动对焦功能的摄像头。
front-facing-camera 应用程序需要前置摄像头。
camera-flash 拍照或拍摄视频需要摄像头闪光灯。
video-camera 设备上需要具备视频功能的摄像头。
accelerometer 需要访问加速度计。
location-services 应用程序将尝试获取设备的当前位置。
gps 设备应包含用于位置跟踪的 GPS 硬件。
microphone 应用程序需要内置麦克风。

应用程序描述文件中列出的功能也被 App Store 用于防止用户下载无法运行的应用。

请注意官方 Apple 文档,随着 iOS 每个新版本的发布,设备功能列表也在增长:developer.apple.com/library/ios/#documentation/general/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html.

当然,您能否利用任何新功能也将取决于 AIR 的未来版本或您决定使用的任何原生扩展。

还有更多...

最后关于设备功能的话。

已弃用对 ARMv6 设备的支持

使用 AIR 2.6 及以上版本发布的应用程序不支持较旧的 ARMv6 iOS 设备。为了防止旧 iOS 设备的用户下载和安装这些应用程序,AIR 自动在应用程序描述文件中包含armv7opengles-2功能。

您不需要明确将这些两个功能添加到应用程序描述文件中。

参见

  • 编辑应用程序描述文件,第三章
posted @ 2025-09-28 09:15  绝不原创的飞龙  阅读(2)  评论(0)    收藏  举报