Livecode-移动开发初学者指南-全-
Livecode 移动开发初学者指南(全)
原文:
zh.annas-archive.org/md5/22c3e2f849bce6854d99de0199f046a1
译者:飞龙
前言
你所认识的人几乎都拥有某种智能移动设备。你可能也拥有好几个!在手机上拥有实用应用程序的想法并不新鲜。甚至手机和 PDA 游戏也早已存在多年,但 iPhone 使用触摸而非笔或键盘,以及它使用手势来减少执行某项任务所需的步骤,这些都带来了革命性的变化。
iPhone 于 2007 年 6 月发布,Android 操作系统于 2008 年 9 月发布。如果你想要创建能在两个平台上运行的应用,你就必须学习两个开发环境和语言:iPhone 的 Objective-C 和 Android 的 Java。
在桌面领域,有几种开发工具允许你在 Mac 和 Windows 上发布应用,在 LiveCode 的情况下,还可以在 Linux 上发布。其中最成功的这些工具包括 Adobe Director、Adobe Flash、Unity 和 LiveCode。将应用发布到 iOS 是在 Adobe Director 12 中引入的,这意味着这四种工具也都适用于移动开发。
这些工具具有不同的优势;在某些情况下,这些优势与你可以制作的应用的性质有关,在其他情况下,它们与工具对非硬编码程序员的可访问性有关。如果你想制作高质量的 3D 游戏,Unity 将是最佳选择,其次是 Director 和 Flash。如果你需要大量的角色动画,Flash 将是最佳选择,Adobe Director 是一个不错的选择。
如果对你来说,最重要的东西是工具的易用性,那么 LiveCode 无疑是一个容易的选择。它也是一个制作大多数你可能希望制作的应用的合理选择。实际上,对于由单个屏幕组成的应用,例如大多数实用应用以及桌面游戏和拼图游戏,LiveCode 比其他工具更适合。它还能更好地访问原生界面元素;使用其他工具时,你通常需要创建类似于原生 iOS 和 Android 控件的外观图形,而不是直接访问真实的东西。
通过其易于使用的类似英语的编程语言和卡片堆隐喻,LiveCode 让你能够更多地专注于创建你想要的应用,而不是开发环境的细节。
本书涵盖的内容
第一章, LiveCode 基础,将向您介绍 LiveCode 环境和其类似英语的编程语言。有经验的 LiveCode 用户可以跳过这一章,但对于 LiveCode 的新手来说,这一章将通过创建一个简单的计算器应用的过程,让你熟悉 LiveCode 的各种工具和层次结构。
第二章,开始使用 LiveCode Mobile,详细说明了如何设置您的 Mac 或 Windows 计算机,以便您准备好开发并发布移动应用程序。本章将带您从注册 iOS 和 Android 开发者到创建和测试您的第一个 LiveCode 移动应用程序的整个过程。
第三章,构建用户界面,展示了如何使用一些标准移动功能,例如日期选择器、相册和相机。本章还将向您展示如何制作具有 iOS 外观的自定义按钮,以及如何使用 LiveCode 附加组件 MobGUI 使您的生活更加轻松!
第四章,使用远程数据和媒体,讨论了您应用程序的结构、代码放置的位置以及如何读取和写入外部文本文件。在这里,我们还将创建一个移动应用程序,它是一个“网络爬虫”,能够从网页中提取链接和媒体,以显示或播放该页面的媒体。
第五章,制作拼图应用程序,将向您展示如何处理图像数据以及如何使用这些信息创建颜色选择器、检测区域以及制作碰撞图。然后我们将创建一个完整的拼图应用程序,该应用程序从相册或设备相机中获取图像。
第六章,制作提醒应用程序,探讨了表示“提醒”所需的信息以及如何设置通知事件,以便在指定日期和时间提醒您。在这里,我们将制作一个提醒应用程序,可以创建此类事件的列表,甚至可以根据您的当前位置列出这些事件。
第七章,部署到您的设备,是一个参考章节,描述了所有移动发布设置。本章还展示了如何将应用程序发送给测试人员以及如何开始将您的成品应用程序提交到各个应用商店。
附录,扩展 LiveCode,描述了 LiveCode 的附加组件,这些组件可以使您的移动应用程序看起来更好或扩展 LiveCode 的移动功能。本章还介绍了 LiveCode 版本 8 计划中的 LiveCode 构建器和小部件功能。
您需要为本书准备的物品
除了 Community LiveCode 7.0 或其后续版本外,如果您遵循本书中关于注册移动开发者的部分,您还需要一台 Mac 或 PC、iOS 和/或 Android 设备,以及一些钱!对于 iOS 开发,您需要访问 Mac OS 以执行某些步骤,并且这些步骤还要求它是一台基于 Intel 的 Mac。
本书面向的对象
这本书的理想读者是那些已经了解 LiveCode、对创建移动应用感兴趣,并希望节省我追踪所有如何入门信息所需的大量时间的那些人!第一章,LiveCode 基础,将帮助那些了解编程但不太熟悉 LiveCode 的人。你获得的知识应该足以让你从本书的剩余部分中受益。
部分
在这本书中,你会发现一些频繁出现的标题(行动时间、刚刚发生了什么?、快速测验、成为英雄),它们经常出现。
为了清楚地说明如何完成一个程序或任务,我们使用以下部分如下:
行动时间 – 标题
-
行动 1
-
行动 2
-
行动 3
这里的说明通常需要一些额外的解释以确保它们有意义,因此它们后面跟着以下部分。
刚刚发生了什么?
本节解释了你刚刚完成的任务或指令的工作原理。
你还会在书中找到一些其他的学习辅助工具。以下部分为例。
快速测验 – 标题
这些是简短的多项选择题,旨在帮助你测试自己的理解。
成为英雄 – 标题
这些是实际挑战,为你提供了实验你所学内容的想法。
规范
你还会发现许多文本样式,用于区分不同类型的信息。以下是一些这些样式的示例及其含义的解释。
文本中的代码单词如下所示:“显示字段的内容存储在currentValue
变量中,最后按下的操作按钮(即存储在currentCommand
中)被查看,以查看接下来会发生什么。”
代码块如下设置:
on togglesign
if character 1 of field "display" is "-" then
delete character 1 of field "display"
else
put "-" before field "display"
end if
end togglesign
任何命令行输入或输出都如下所示:
start using stack "utility stack"
新 术语 和 重要 词汇 以粗体显示。你在屏幕上看到的单词,例如在菜单或对话框中,在文本中如下所示:“在工具调色板中,点击编辑工具(右上角的图标)。”
注意
警告或重要注意事项以如下框的形式出现。
小贴士
小贴士和技巧看起来像这样。
读者反馈
我们欢迎读者的反馈。请告诉我们你对这本书的看法——你喜欢什么或不喜欢什么。读者反馈对我们来说很重要,因为它帮助我们开发出你真正能从中受益的标题。
要发送给我们一般性的反馈,只需发送电子邮件至 <feedback@packtpub.com>
,并在邮件的主题中提及书的标题。
如果你在某个主题上有专业知识,并且你对撰写或为书籍做出贡献感兴趣,请参阅我们的作者指南www.packtpub.com/authors。
客户支持
现在你已经是 Packt 图书的骄傲拥有者了,我们有一些事情可以帮助你从你的购买中获得最大收益。
下载示例代码
您可以从您在www.packtpub.com
的账户下载示例代码文件,适用于您购买的所有 Packt Publishing 书籍。如果您在其他地方购买了这本书,您可以访问www.packtpub.com/support
,并注册以将文件直接通过电子邮件发送给您。
勘误
尽管我们已经尽一切努力确保我们内容的准确性,但错误仍然会发生。如果您在我们的某本书中发现了错误——可能是文本或代码中的错误——如果您能向我们报告这一点,我们将不胜感激。通过这样做,您可以节省其他读者的挫败感,并帮助我们改进本书的后续版本。如果您发现任何勘误,请通过访问www.packtpub.com/submit-errata
,选择您的书籍,点击勘误提交表单链接,并输入您的勘误详情来报告它们。一旦您的勘误得到验证,您的提交将被接受,勘误将被上传到我们的网站或添加到该标题的勘误部分下的现有勘误列表中。
要查看之前提交的勘误,请访问www.packtpub.com/books/content/support
,并在搜索字段中输入书籍名称。所需信息将在勘误部分显示。
盗版
互联网上版权材料的盗版是所有媒体中持续存在的问题。在 Packt,我们非常重视我们版权和许可证的保护。如果您在互联网上发现我们作品的任何非法副本,无论形式如何,请立即提供位置地址或网站名称,以便我们可以寻求补救措施。
请通过<copyright@packtpub.com>
与我们联系,并提供疑似盗版材料的链接。
我们感谢您在保护我们作者和我们为您提供有价值内容的能力方面所提供的帮助。
问题
如果您对本书的任何方面有问题,您可以通过<questions@packtpub.com>
联系我们,我们将尽力解决问题。
第一章。LiveCode 基础知识
这一章适合你吗?
LiveCode 拥有类似英语的编程语言、图形开发环境和易于理解的架构隐喻。当你创建一个应用程序时,你花更多的时间思考如何实现不同的功能,而不是你使用的工具的复杂性。然而,如果你以前从未使用过 LiveCode,它最初仍然会感到陌生。本章旨在让你跟上进度,并为后续章节做好准备,这些章节将需要你更熟悉这个工具的术语和功能。
所有 LiveCode 都很容易,但有许多容易学习的东西!在整本书中,我们将探讨这些内容,特别是你可以用于移动应用的内容,但首先,我们应该回顾一些基础知识。
在本章中,我们将:
-
熟悉 LiveCode 环境
-
探究 LiveCode "堆栈"的层次结构
-
创建一个简单的计算器应用程序
-
了解许多不同的界面控件
那么,让我们开始吧。
背景历史和隐喻
许多开发工具只提供编程语言和系统例程的编程接口。高级工具通常以相同的方式提供这些内容,但结构得如此之好,以至于可以为工具的不同方面想出现实世界的隐喻。LiveCode 非常像这样,其隐喻是一堆卡片。这个隐喻起源于 20 世纪 80 年代中期的苹果电脑 HyperCard 创作工具,该工具由比尔·阿特金森创建。HyperCard 的第一个版本于 1987 年 8 月发布,并在教育和多媒体领域取得了巨大成功。像 Voyager 公司这样的公司,发布了其整个产品线,这些产品都是使用 HyperCard 创建的。
其他公司生产的工具与 HyperCard 非常相似,但它们也试图为用户提供比 HyperCard 更多的功能。其中最突出的是 SuperCard、Plus 和 MetaCard。Plus 继续拥有一个有趣的生命周期;该产品本身最初是跨平台的(最初是 Windows-only),但后来,相同的代码最终出现在 Oracle Media Objects 跨平台工具中。所有这些工具都延续了卡片堆栈的隐喻。
MetaCard 最显著的特点是它是多平台的,而不仅仅是跨平台的。"Stacks"是这些工具创建的文档的通用术语,使用 MetaCard 创建,在 Unix 和 Linux 系统上运行,以及 Mac 和 Windows。遗憾的是,它有点丑!苏格兰公司 RunRev 推出了一款产品,试图以更有吸引力的方式展示 MetaCard。最终,RunRev 收购了 MetaCard,自 2003 年以来,RunRev 一直使用产品名称 Runtime Revolution(后来更名为 LiveCode)在此基础上进行构建。
注意
在 2015 年 3 月,RunRev 还将公司名称更改为 LiveCode Ltd。本书中有许多关于 runrev.com/
的引用,并且应该继续这样维护。然而,如果您遇到 URL 问题,请将其替换为 livecode.com/
或在 LiveCode 网站上搜索。
在 2013 年,RunRev 成功地发起了 Kickstarter 营销活动,并筹集了 494k 英镑(775k 美元)的资金,以使 LiveCode 开源。LiveCode 的 6.0 版本于 2013 年 4 月发布,作为第一个开源版本。这导致了一个活跃的开发周期,接近 20 个稳定版本,最终在 2014 年 10 月推出了 LiveCode 的 7.0 版本。本书的这一版基于 LiveCode 的 7.0 版本。
7.0 版本的亮点包括对 Unicode 的支持、显示分辨率独立性、可拉伸图形、使用新浏览器的混合应用程序、Mac Cocoa 支持、Raspberry Pi 支持、64 位 Linux 支持,等等。您可以在 2014 年 10 月 23 日的通讯录第 180 期中了解更多关于 LiveCode 7.0 的信息。newsletters.livecode.com/october/issue180/
。所有 LiveCode 通讯录都可在 LiveCode 帮助 菜单下找到。
在 2014 年,RunRev 又发起了另一场融资活动,以支持 HTML5,并额外筹集了 395k 美元。这种能力和具有开放语言支持的 LiveCode 8.0 版本在 附录 扩展 LiveCode 中进一步描述。
在卡片堆栈隐喻的 HyperCard 变体下,文档由包含按钮、字段和位图图形的卡片组成;包含一组卡片的背景;以及包含一组背景的堆栈。LiveCode 采用略微不同的方法,而不是有包含卡片的背景,它允许您将任何一组界面控件分组,并将这些控件设置为作为背景实体来操作。这些最终变得更加灵活,尽管对于大量使用 HyperCard 的人来说可能有些陌生。
HyperCard 和 LiveCode 都提供了进一步扩展层次结构的方法。您能够链接其他堆栈。为了节省时间,您可能选择拥有一个专门用于这些函数的堆栈,并且可以使用以下命令将该堆栈添加到 stackInUse
属性中:
start using stack "utility stack"
此外,您还可以编写“外部”程序,这些是使用 C 语言编写的命令和函数,可以进一步扩展 LiveCode 的功能。
你确实有 LiveCode,不是吗?
如果您尚未安装 LiveCode,请访问 livecode.com/download
并下载适用于您的开发平台的社区版。这个版本是开源的,并且免费使用。您需要提供您的姓名和电子邮件,这将为您在 LiveCode 中建立一个用户账户。在撰写本书时,您还可以获得一个免费的 App 设计套件,其中包括一个介绍视频和一个移动 app2market.livecode
模板。
如果您计划购买商业版 LiveCode,请阅读www.runrev.com/store/
,了解那里提供的许多许可证变体。作为一个粗略的指南,基于撰写本书时的价格,要创建免费移动应用程序,成本将是 99 美元,如果您想制作可以收费的应用程序,成本将是 299 美元。额外的使用和支持级别需要额外付费。
LiveCode 的两个版本也有独特的配色方案,商业版使用蓝色元素,社区版使用绿色元素。
一旦您下载了社区版或购买了商业许可证之一,就可以启动它了!
了解环境布局
当您第一次打开 LiveCode 时,会显示一个开始中心窗口,它充当打开最近文档、链接到论坛和获取开始信息列表或查看促销信息的方式。保持该窗口打开没有害处,但如果您关闭了它,可以从帮助菜单重新打开它。您还可以通过从视图菜单中选择背景来隐藏屏幕上的其他应用程序窗口。
如果您第一次使用 LiveCode,您会注意到屏幕顶部的工具栏,位于菜单栏下方。请注意最右侧的项目,例如示例堆栈、教程、资源和字典。这些区域充满了帮助您开始使用 LiveCode 的信息。字典是您会经常使用的东西,浏览条目要么会立即回答您的问题,要么会提供有关您以后可能遇到的问题的详细信息。
帮助菜单还提供了访问用户指南和链接到其他有用信息的途径。请查看用户指南部分,深入了解这里提到的功能。
在线课程
除了 LiveCode 本身内部看到的资源之外,RunRev 网站上还有大量信息和许多教程。一个好的起点是lessons.runrev.com/
。
此截图显示了我们将要使用的窗口和调色板,以及文档窗口,这是一个我们将很快构建的简单计算器:
主要窗口
除了文档窗口本身之外,以下是我们现在需要熟悉的几个主要窗口:
-
工具调色板
-
检查器调色板
-
消息框
工具调色板的上部显示了您创建交互式应用程序所需的所有界面控件。在这些控件下方是一组用于编辑矢量图形的工具和一组用于编辑位图图形的工具。
检查器调色板显示了您当前所选控件的全部选项。在前面的屏幕截图中,计算器应用程序中没有选择任何内容,因此检查器调色板显示了堆栈本身的信息。
消息框是一个窗口,允许你尝试单行或多行代码。你还可以在堆栈中调用函数,这使得在追踪问题时测试单个函数变得非常方便。我们将在后面的章节中使用消息框。
如建议的那样,阅读用户指南以深入了解这些窗口,但现在让我们尝试组合一些简单的内容,以便你更熟悉如何使用工具调色板。
现在是行动时间——虽然有点麻烦,但你一定会喜欢的!
你在 LiveCode 中通过从工具调色板拖动图标到堆栈窗口中来构建东西。如果调色板尚未打开,可以通过单击工具栏左端的图标或从对象菜单中选择检查器菜单项来打开检查器调色板。可以通过从工具菜单中选择工具调色板并使用以下步骤来打开工具调色板
-
从文件菜单中选择新建主堆栈。
-
在工具调色板中,单击编辑工具(右上角的图标)。
选择编辑或不…
在 LiveCode 中,你可以不选择编辑工具,直接从工具调色板将控件拖动到卡片窗口中。然而,你无法选择控件来调整其位置或大小,因此,在以下说明中,我们故意在向卡片窗口添加控件之前选择编辑工具:
-
将工具调色板上方的图标拖动到堆栈窗口中。
-
尝试对象菜单底部的分层选项。
-
选择多个项目,并在检查器调色板中实验对齐对象选项。当你选择多个对象时,对齐选项会自动显示,但你也可以从检查器调色板的下拉菜单中选择对齐对象。如果只选择了一个对象,则不会看到此选项。在这里,我们能够看到这些选项,因为选定了三个按钮:
-
选择一个按钮,并在检查器调色板中输入一个名称和标签。如果你看不到名称和标签字段,请确保你已经从检查器调色板的下拉菜单中选择了基本属性。
-
向卡片窗口添加更多控件,并练习对齐和命名控件。你还可以在控件被选中时通过拖动角落和边上的手柄来调整它们的大小。如果你添加了一些按钮、字段、标签页面板、滑块和视频播放控件,窗口将看起来如下:
刚才发生了什么?
希望你已经创建了一堆随机的界面控件,也许还有一些排列得很好的!现在,从文件菜单中选择关闭并从内存中删除选项,创建一个新的主堆栈以制作简单的计算器界面。
首先,我们应该回顾一下 LiveCode 堆栈的结构和层次结构,并创建一些基本的导航。
创建层次结构
所有的东西都有其去处,但东西放在错误的地方可能会导致问题。我们应该更多地了解 LiveCode 堆栈的结构,以避免这种情况。
堆栈结构
如在背景历史和隐喻部分所述,LiveCode 使用卡片堆栈的隐喻。当你创建一个新的堆栈时,实际上你有一个单独的卡片堆栈。然而,即使是最简单的应用程序也可能包含多个卡片。例如,可能有启动屏幕、标题卡片、实际任务卡片和致谢页面。在计算器堆栈中,我们将使用两个卡片。工具菜单包括一个选项,可以通过显示项目浏览器或应用程序浏览器来查看堆栈的结构。项目浏览器是在 LiveCode 6.0 版本中引入的,并增加了额外的功能。
项目浏览器面板是一个强大的工具,它允许你在一个窗口中看到所有打开的堆栈、卡片和控制。除了获得全面的概述外,你还可以将其用作远程控制,在堆栈的所有部分之间跳转,并选择和修改按钮、字段等。
以我们即将制作的计算器堆栈为例,在下面的屏幕截图中,我们看到堆栈窗口和项目浏览器面板的并排视图,在项目浏览器面板中,我们已选择堆栈中的一个按钮:
项目浏览器的上部区域包括一个字段,你可以在此处输入和搜索文本,以减少浏览器中项目的列表,以匹配你输入的内容。在面板的左上角是一个齿轮图标,用于将你带到浏览器的首选项:
浏览器窗口的大部分区域允许你展开堆栈和卡片,并选择那些卡片上的单个控件。在项目浏览器中点击一个控件会在堆栈窗口中突出显示它,反之亦然。控件也可以通过上下拖动来重新排序以改变层级。通过点击眼睛和锁图标,控件也可以被隐藏或锁定。下方的区域按钮允许你执行所选控件的多种对齐方式,以添加或复制所选控件。将鼠标悬停在按钮上会显示一个弹出窗口,显示其功能。
关于项目浏览器如何工作的更详细概述可在以下链接找到:
www.runrev.com/newsletter/april/issue151/newsletter4.php
。
代码去哪里了?
在编程语言中,例如 LiveCode 中的编程语言,代码被称为脚本,而方法或函数被称为处理程序(尽管在 LiveCode 中,返回值的处理程序也称为函数)。使用难以使用的编程工具创建的项目通常包含数十个外部文本文件,每个模型、视图或控制器一个。在 LiveCode 中,这要简单得多,因为脚本被附加到需要该代码的对象上。
为了处理其他工具中的用户交互,你必须编写接收事件的代码(可能只是按钮上的鼠标点击)以执行相关操作。在 LiveCode 中,有一个消息路径负责这些事件,并将事件向上传递到层次结构。如果你点击一个没有鼠标事件处理程序的 LiveCode 界面控件,点击将向上传递到卡片级别。如果卡片没有为该事件提供处理程序,它将继续向上传递到堆栈级别。
通过使用其他堆栈,你可以有额外的层次结构级别,但就我们的目的而言,我们只需要这三个:按钮、卡片和堆栈。
这种消息层次结构允许我们在多个界面控件中放置所需的代码,这些控件在更高层次上对所有这些控件都是可用的。计算器数字按钮的一个例子是,每个都需要执行完全相同的事情,通过将代码放在卡片级别,所有这些都可以使用那个处理程序。
如果你在卡片级别有共享处理程序,或者文件大小有显著改进,那么并没有性能优势,但在为简单的计算器示例编写代码时,你可以在单个卡片脚本中而不是 11 个计算器按钮脚本中进行更改。
现在我们将开始构建计算器,并将脚本添加到 14 个按钮、一个字段和卡片中。
行动时间 - 制作卡片并在它们之间导航
计算器其实不需要标题屏幕,但为了练习添加脚本和进行一些基本导航,我们还是做一个吧。从文件菜单开始一个新的 Mainstack,并打开检查器调色板。
-
在检查器调色板中,在名称字段中输入
Simple Calculator
堆栈名称。 -
从对象菜单中选择新建卡片。
-
使用视图菜单转到上一张卡片(上一张)或第一张卡片(第一张)。
-
确保你在工具调色板中选择了编辑工具,并将标签字段拖到卡片窗口的中间。在这种情况下,你可以很容易地看到哪个是标签字段(图标上写着标签:),但作为一个一般提示,你可以将鼠标悬停在工具调色板中的控件上,并查看显示控件类型的帮助提示。
-
在检查器调色板的基本属性部分,取消选中不换行复选框。
-
在名称输入字段中输入
title
。 -
从检查器下拉菜单中选择内容,并将初始文本“标签:”替换为在内容输入字段中输入
Simple Calculator
。 -
从下拉菜单中选择文本格式化,然后点击中间的三个对齐按钮中的居中对齐按钮。
-
更改字体、大小和样式选项以制作一个看起来不错的标题,调整字段本身的大小,直到你喜欢它的外观:
-
从工具调色板中拖动一个推按钮(位于工具调色板左上角第二个图标)并将其放置在标题字段下方。
-
在检查器调色板中,从下拉菜单中选择基本属性(在先前的截图中说文本格式化的菜单)并在名称输入字段中输入
Begin
。尽管你未在标签输入字段中输入,LiveCode 也会自动显示与按钮标签相同的文本。 -
如果你愿意,也可以进入按钮的文本格式化选项!
-
在心理上做好准备;我们即将输入我们的第一个脚本!
-
在按钮被选中时,从对象菜单中选择对象脚本。你也可以右键单击按钮本身并选择编辑脚本。
-
脚本窗口将出现,并显示一个
on mouseUp
的起始脚本、空白行和end mouseUp
,如下截图所示:
通过在空白行中键入go next
来完成脚本,得到以下最终脚本:
on mouseup
go next
end mouseup
现在,执行以下步骤:
-
关闭脚本窗口,当询问是否要保存更改时,点击是。
-
从工具调色板(看起来像普通光标箭头的最左上角工具)中选择浏览工具,并点击你刚刚创建的开始按钮。如果一切顺利,你现在应该看到一个空白卡片。别担心,你并没有删除标题字段和按钮!你现在在之前创建的两个卡片中的第二个卡片上。再次使用视图菜单回到第一个卡片,再次尝试按钮。
-
从文件菜单中选择保存,并将名为
Simple Calculator
的堆栈保存在你稍后容易找到的地方。也许,你可以创建一个文件夹来存放你在这本书阅读过程中制作的几个堆栈。
刚才发生了什么?
这些步骤可能看起来很多,但我们确实创建了所需的两个卡片,布置了一个看起来不错的标题字段和一个带有自己脚本的开始按钮。实际上,这些步骤不到两分钟就能完成,随着你在 LiveCode 中积累经验,操作会更快。
快速问答 - 选择最佳名称?
如果你想在多媒体制作工具领域取得成功,以下哪个名字是不合适的?
-
亨利
-
比尔
-
鲍勃
-
凯文
答案:1
在多媒体的早期,似乎每个人都有一两个流行的名字。有比尔·阿特金森,他创建了 HyperCard,还有比尔·阿普尔顿,他创建了 SuperCard。凯文·卡尔霍恩曾是一段时间 HyperCard 的主要程序员,凯文·米勒是 LiveCode 的负责人。鲍勃·斯坦是 Voyager 公司的创始人之一,他与鲍勃·阿贝尔一起是视觉效果领域的先驱。丹是一个很好的选择,因为丹·温克勒是 HyperTalk 语言的作者,丹尼·古德曼是许多著名编程书籍的作者。如果你想制造汽车或者娶很多王后,亨利会是一个好名字。
制作一个简单的计算器应用程序
即使对 LiveCode 只有基本的熟悉度,你也能开始制作一些有用的东西。在这里,我们将制作一个非常简单的计算器堆栈。
检查器提示,哦!
你会发现自己在很多情况下都会使用检查器调色板;所以,花点时间研究一下它的行为。当你选择卡片上的一个对象时,你会看到检查器调色板会改变其外观,有时甚至高度也会改变,以显示你选择的项目的选项。它足够智能,能够注意到当你选择了多个项目时,并显示对齐工具。
有时候,你可能想要保持检查器调色板以查看卡片上特定对象的选择,而不是在做出其他选择时切换以显示不同的对象。在检查器调色板的右上角有一个锁形图标,这将允许你将检查器锁定到当前对象。
到目前为止,检查器调色板的大多数选项还没有影响我们,但即将变得相关的一个事实是,你可以为项目设置一个与标签不同的名称。你可能从其他编程语言中知道,这也适用于 LiveCode,有些名称比其他名称合法。也许你无法在名称中使用空格,或者使用冒号或反斜杠。如果你用数字命名一个按钮,按钮“1”可能不是按钮 1,这可能会导致混淆。
对于计算器键,我们将设置一个标签使其看起来正确,并设置一个不会引起混淆的名称。说到那些计算器键……
开始行动——制作计算器按钮
以本章开头所示的截图作为指南,让我们构建计算器按钮(如果你稍后想确保你正确地输入了这些脚本,下面列出的脚本也会列出):
-
如果你还没有到那里,请转到第二张卡片,当前为空的卡片。
-
确保在工具调色板中选中了编辑按钮,并将一个推按钮拖到卡片上,放置在
7
按钮的位置。 -
在检查器调色板的基本属性面板中,将样式下拉菜单设置为圆角矩形(在现实生活中,你会花时间制作漂亮的图形按钮;这里,你只是在匹配我的丑陋的“程序员艺术”!)。
-
将按钮的名称设置为
number7
,标签设置为7
。 -
从 对象 菜单中选择 对象脚本,就像你使用 开始 按钮那样查看起始脚本。
-
在
on mouseUp
和end mouseUp
之间的空白行中输入numberPressed the label of me
。注意,numberPressed
是一个需要稍后定义的新处理程序。当使用时,me
指的是当前对象;在这种情况下,是按下的按钮。 -
关闭并保存脚本。
-
选择按钮,通过从 编辑 菜单中选择 复制对象 来制作一个副本,并将其放置在 8 按钮的位置。复制/粘贴和 Alt-拖动是复制对象的另外两种方法。
-
将名称设置为
number8
,并将标签设置为8
。 -
使用相应的数字而不是
8
,对按钮 9、4、5、6、1、2、3、0 和小数点重复步骤 8 和 9。对于小数点,让名称为decimalpoint
。 -
再次复制一个按钮,将新按钮命名为
divide
,并将其标签设置为/
。 -
为除法按钮选择
Object Script
,并将中间行的numberPressed
改为operatorPressed
,使整行变为operatorPressed the short name of me
。 -
再复制除法按钮三次,并将名称分别设置为
multiply
、plus
和minus
。将标签分别设置为*
、+
和-
。 -
再次复制除法按钮,为新按钮命名为
equals
,标签为=
,并将脚本中间行改为equalsPressed
。 -
复制 = 按钮,并将新按钮的名称设置为
toggleSign
,标签设置为+-
;然后,将脚本中间行改为toggleSign
。 -
复制 = 按钮,并将新按钮的名称设置为
clear
,标签设置为C
;然后,将脚本中间行改为clearPressed
。 -
从 工具 面板拖动一个 标签 字段到 检查器 面板,从下拉菜单中选择
Text Formatting
。在Text Formatting
设置中,选择一个看起来不错的字体,右对齐文本,并设置大字体大小。将字段命名为display
。 -
编辑
display
字段的脚本。对于字段,你不会得到与按钮相同的起始脚本,因此你需要自己输入mouseUp
行。在脚本中输入这三行:on mouseUp
、set the clipboarddata["TEXT"] to me
和end mouseUp
。请确保在"TEXT"
两边输入引号。 -
将所有按钮移动到正确的位置,并选择按钮组然后使用对齐工具,使计算器布局与截图匹配。
-
现在保存它!
刚才发生了什么?
现在发生了很多事情!我们已经创建了所有的卡片级别对象并输入了它们的脚本。大多数脚本都是“调用”一个我们将要设置的卡片级别处理程序。在这样做之前,尝试理解我们刚刚输入的一些行是值得的。
详尽性、同义词和 "me"
LiveCode 中的编程语言具有英语般的性质,非常强大,但非常严格。在其他一些工具中,你可以选择是否使用冗长的英语语法、简洁的语法,或者称为 点语法 的语法。Adobe Director 中的 Lingo 语言 是一个很好的比较。
假设我们想要更改字段内的文本,即导演电影演员表的第一条记录,我们可以执行以下冗长的语法:
put "hello world" into the text of member 1
我们可以执行一种稍微不那么冗长的语法:
the text of member 1 = "hello world"
或者,我们可以执行点语法:
member(1).text = "hello world"
在 LiveCode 中,没有选择。你必须以以下形式输入:
put value into container
然而,你确实可以选择使用单词的完整形式、简短形式或缩写形式。还有同义词,这允许你使用对你更有意义的单词。
这里是两种表达相同意思的方式,第二种变体使用了关键词的缩写形式:
put character 3 of word 2 of card field "name of field 1" into aVariable
put char 3 of word 2 of fld 1 into aVariable
当你处理运行脚本的对象的内 容时,你可以使用关键词 me
来节省一些输入,如果可能的话,LiveCode 也会尽力理解你的意图。
以我们输入的行为例:
numberPressed the label of me
在这里,numberPressed
将传播到我们将要添加(很快)的卡片处理程序,而 the label of me
将查看脚本所在的对象的标签:
set the clipboarddata["TEXT"] to me
在这种情况下,me
通常指的是对象(就像 the label of me
的情况一样),但由于我们提供了额外的线索 ["TEXT"]
,LiveCode 就知道脚本和文本内容是字段的一部分,而不是字段本身。尽管如此,由于存在混淆的可能性,在以后阅读自己的代码时,你可以添加一些词语来使意思更加清晰:
set the clipboarddata["TEXT"] to the text of me
注意
顺便说一句,显示字段脚本对于计算器的工作不是必需的。它只是在那里,以便在任何时候,你都可以点击字段,将当前值复制到剪贴板,以便在其他应用程序中粘贴。
你可能会选择比必要的更冗长,只是为了可读性,在这些章节中,情况就是这样。通过使用以下方式,更容易知道将要发生什么:
put the text of me into textvariable
与前面的条目相比,以下内容将更加简洁,尽管它们同样有效:
put me into textVariable
在任何情况下,由于它是一个字段,LiveCode 都知道你的意图。
你在脚本中看到我们输入了 short name of me
,这是怎么回事?LiveCode 中的对象有一个关于它们位置的详细描述,例如,buttonname
按钮位于 path/to/stack.livecode
栈的 1234
卡片 ID 上。在计算器应用程序中,我们只需要你设置为按钮名称的单个单词。如果我们请求 name of me
,它仍然会说“buttonname
按钮”。为了只获取名称本身,我们使用 short name of me
。
有时候你会想要使用name
的其他变体,包括长名称和缩写名称,你可以在 LiveCode 字典条目中阅读有关name
的信息。除了描述如何使用name
的不同方式外,还有一些注意事项你需要注意。
小贴士
大小写敏感性
如果你们中的任何一位使用了高级 LiveCode,可能会注意到在某些情况下,我使用了错误的字母大小写。LiveCode 并不介意你使用了哪种大小写,所以当我错误地说成clipboarddata
而不是clipboardData
时,这并不重要。这个特性并不仅限于 LiveCode,但在接近英语的编程语言中,这是常见的,它们不会在命令执行前要求用户必须完全正确地使用大小写。
添加卡片处理程序
如果你敢尝试使用计算器按钮,你会看到很多脚本错误。我们需要添加卡片级别的处理程序,以便成为按钮发出的调用接收端。与其逐行引导你,一次输入一行代码,可能更快的方法是一次性展示所有行并解释每行的作用。作为练习,以下是到目前为止我们输入的行:
在所有数字按钮和小数点按钮上,你应该有这个脚本:
on mouseup
numberPressed the label of me
end mouseup
当你在numberPressed
调用时按下并释放左鼠标按钮时,将触发on mouseUp
事件。此事件将调用一个名为numberPressed
的卡片处理程序,并传递你为包含此脚本的按钮设置的标签。
C(清除)按钮有这个脚本:
on mouseUp
clearPressed
end mouseUp
clearPressed
事件将调用一个名为clearPressed
的卡片脚本。
其他按钮的工作方式相同;它们调用一个使用该名称的处理程序,我们即将将其添加到卡片脚本中。这是+、-、*和/按钮的脚本,将按钮的名称传递到卡片级别:
on mouseUp
operatorPressed the short name of me
end mouseUp
以下脚本是为加号按钮准备的:
on mouseUp
toggleSign
end mouseUp
显示字段有这个脚本:
on mouseUp
set the clipboardData["TEXT"] to me
end mouseUp
在字段的情况下,只执行一行代码,所以不需要将其放在卡片级别上,除非我们有很多字段做同样的事情。
那么,我们为什么不添加所有这些卡片级别的脚本呢!我们将逐个处理它们,并解释每个脚本是如何工作的。但首先,让我们看看 LiveCode 是如何处理变量的。
小贴士
下载示例代码
你可以从你购买的所有 Packt 书籍的账户中下载示例代码文件。www.packtpub.com
。如果你在其他地方购买了这本书,你可以访问www.packtpub.com/support
并注册以直接将文件通过电子邮件发送给你。
LiveCode 中的变量类型
一般而言,变量是存储你稍后需要访问的值的内存位置,但在大多数编程语言中,你可以指定哪些例程可以访问哪些变量。不那么像英语的语言可能包括public
、private
和protected
等术语。在 LiveCode 中,事情并没有那么不同,但使用的词汇更准确地描述了变量可以使用的区域。如果一个变量要在任何地方都可见,它将是global
。如果它只是要在当前脚本中使用,它将是local
。
LiveCode 还具有自定义属性变量,顺便提一下,许多人会使用这些变量来执行计算器按钮的值,而不是依赖于按钮的标签。也许,我们以后会用到它们!
现在,我刚才说到哪里了……哦,是的,卡片级别脚本。这是卡片脚本的第一个语句:
global currentTotal,currentValue,currentCommand,newNumber
如前所述,这些变量将允许许多处理器相互传递值。在这种情况下,变量可以是局部的,但通常,你可能会选择将它们设置为全局,认为将来可能会有需要从你所在的脚本外部访问这些变量的情况。
当你启动应用程序时重置事物是个好习惯,LiveCode 有一个openCard
事件,我们可以利用它。以下代码将重置事物:
on openCard
clearPressed
end openCard
on clearPressed
put true into newNumber
put 0 into field "display"
put 0 into currentTotal
put 0 into currentValue
put empty into currentCommand
end clearPressed
将重置行放在自己的clearPressed
处理器中,将允许我们在其他时间调用它,而不仅仅是当卡片打开时,并且当我们点击C清除按钮时,我们直接调用它。这将清零显示字段、计算的总计以及你最后输入计算器的数字。它还会清除用于记住你最后按下的运算符按钮的变量,以及一个布尔(真或假)变量,用于识别你按下的数字按钮是否应该清除显示或附加到显示。
所有编号按钮和小数点按钮都调用此处理器:
on numberPressed n
if newnumber is true then
put n into field "display"
put false into newnumber
else
put n after field "display"
end if
end numberPressed
处理器名称后面的n
注释是一个参数变量,它存储发送到处理器的内容。在这种情况下,它是被按下的按钮的标签。这个例程需要做的只是向显示字段末尾添加一个字符,除非你正在输入一个新的数字。这就是newNumber
布尔变量的作用;如果它设置为true
,传入的字符将替换显示字段的所有内容。如果它是false
,字符将被添加到字段末尾。
当你按下+、-、****或/按钮时,将使用此处理器:
on operatorPressed operator
if currentCommand is empty then
put field "display" into currentTotal
put operator into currentCommand
put true into newNumber
else
put operator into currentCommand
equalsPressed
end if
end operatorPressed
当你使用计算器时,你输入一个数字,一个运算符,然后另一个数字,接着是另一个运算符或equals
按钮。现在你按下运算符按钮,因为没有办法知道你在做什么(因为你还没有输入计算中的下一个数字),所以我们必须在按下等于按钮时记住运算符。如果currentCommand
变量还没有值,我们将显示字段文本存储到currentTotal
变量中,将你按下的运算符字符存储到currentCommand
变量中,并确保newNumber
设置为true
。这样做确保了下一个你按下的数字按钮将清除显示字段。如果currentCommand
已经有值,我们将其替换为新值,然后调用在按下equals
按钮时使用的相同处理程序。
很可能存在处理按下equals
按钮的更短方法,但在这里,我们将使用几个if
语句并运行适当的计算代码:
on equalsPressed
put field "display" into currentValue
if currentCommand is empty then exit equalsPressed
if currentCommand is "divide" then put currentTotal / currentValue into field "display"
if currentCommand is "multiply" then put currentTotal * currentValue into field "display"
if currentCommand is "minus" then put currentTotal - currentValue into field "display"
if currentCommand is "plus" then put currentTotal + currentValue into field "display"
put field "display" into currentTotal
put true into newNumber
put empty into currentCommand
end equalsPressed
显示字段的内容存储在currentValue
变量中,最后按下的运算符按钮(存储在currentCommand
中)被检查,以查看接下来会发生什么。如果没有先前的运算符,例如连续两次按下“等于”,我们将忽略按钮按下并退出程序。对于四个运算符,我们执行适当的计算。之后,我们将新的运行总数存储在currentTotal
变量中,确保newNumber
布尔值为true
(这样下一个数字按钮按下时将清除显示字段),并通过将empty
放入currentCommand
变量中忘记最后按下的运算符按钮。
有一个需要注意的事情是,LiveCode 足够智能,知道显示字段内的文本字符串应该被当作浮点数处理。
togglesign
最后一个处理程序如下:
on togglesign
if character 1 of field "display" is "-" then
delete character 1 of field "display"
else
put "-" before field "display"
end if
end togglesign
这是一个非常简单的程序,不需要理解它所表示的是浮点数。它只是检查第一个字符是否为负号,如果是,则删除该字符;如果不是,则插入一个连字符,LiveCode 稍后会将其解释为负值。
快速问答——试着记住…
当你学习一个新的工具时,你可能会花费很多时间记住你可能需要的一切所在的位置。你知道你想要做什么,你知道如何做,但你就是记不住那个东西在哪里!例如:
Q1. 你去哪里设置计算器标题字段的文本样式?
-
编辑菜单。
-
对象菜单。
-
检查器调色板的文本格式化部分。
-
文本菜单。
答案:3
进入这一部分需要从工具调色板中选择编辑工具,点击卡片 1 上的标题字段,然后从检查器调色板下拉菜单中选择文本格式化。然而,确实有一个文本菜单。实际上,这正是我们应该使用的!
扩展计算器
可以向简单的计算器添加更多功能。如果我们考虑卡片脚本中的函数以及按钮的命名,我们可以开始了解添加新功能所涉及的过程,以下是一些过程:
-
计算器操作按钮的命名是为了让卡片脚本知道您点击了哪个。
-
当按下“等于”按钮时,在
equalsPressed
处理程序中有一组if
语句,用于确定接下来会发生什么。
尝试英雄之旅 – 探索事物的本质
在 Windows 上,你可以使用Alt 251
添加平方根符号,而在 Mac 上,则使用快捷键option + v。不幸的是,LiveCode 不喜欢将这些作为按钮标签!至少在 Mac 上,当你在这个检查器调色板中输入字符时,字符会立即消失。一种解决方案是使用消息框并输入以下内容:
set the label of btn "squareroot" to "√"
这应该会给你正确的符号作为按钮标签。
LiveCode 有一个平方根函数;在消息框中输入此内容将产生 10 的平方根:
put sqrt(10)
现在您已经掌握了这些信息,尝试向计算器添加平方根功能。
其他界面控件
到目前为止,我们只需要查看按钮和字段就能创建计算器。在后面的章节中,我们将使用更多的控件,所以让我们先预览一下那些控件。
视频播放器控件
LiveCode 可以使用播放器控件类型播放电影。这些可以通过多种方式添加到卡片中,然后使用脚本命令:
-
您可以通过从文件菜单中选择导入为控件/视频文件…来从您的硬盘驱动器添加文件
-
您可以通过从对象菜单中选择新建控件/播放器来创建一个空播放器
-
您可以从工具调色板中将播放器控件拖动到卡片上。在这种情况下,包含了一个示例电影
-
您可以使用以下代码创建一个带有名称的播放器控件:
new player "player name"
在将播放器添加到卡片后,您可以通过在检查器调色板的基本设置选项下输入文件的路径或 URL 来设置要播放的视频文件。您也可以使用脚本设置视频的路径:
set the filename of player "player name" to "file path or URL"
静态图像控件
就像您刚才看到的视频播放一样,静态图像也可以添加到堆栈中。添加视频播放器的所有选项都可以以相同的方式应用于图像。例如,以下是将 RunRev 公司标志添加到卡片的脚本:
new image "revlogo"
set the filename of image "revlogo" to "http://runrev.com/wp-content/themes/runrev2013/ims/runrev_logo.png"
滚动按钮
您可以导入的图像可以用作按钮的图标。要设置按钮,使其具有漂亮的空闲状态图像和相关的突出显示图像,您需要执行以下步骤:
-
选择文件 | 导入为控件 | 图像文件…。
-
选择代表空闲和突出显示状态的图像,然后点击打开。
-
选择你希望看起来像这些图像的按钮,并在检查器调色板中的图标 & 边框下,点击顶部条目右侧的魔法棒按钮(“图标”)。
-
在出现的对话框中,从下拉菜单中选择此堆栈。
-
选择按钮空闲状态下的图像。
-
点击高亮条目旁边的魔法棒按钮,并选择高亮状态图像。
-
在基本 属性下,从样式下拉菜单中选择透明按钮。
-
取消选中显示名称、自动高亮和共享高亮的复选框。
-
调整按钮的大小,使其足够大,以便显示图像。
-
选择每个原始图像,并在基本属性下取消选中可见框。
在下面的屏幕截图中,我们可以看到导入的两个图像,目的是给开始按钮一个更类似 iOS 的外观。按钮被选中,检查器调色板显示了图标选择选项:
当你选择用于的图像时,按钮本身会更新。在这种情况下,高亮图标已被设置为图形的较暗版本,但如所示,按钮仍然需要调整大小。
许多更多控件...
LiveCode 有很多不同的控件。许多只是细微的变体,但也有很多彼此之间相当不同。查看对象菜单和新控件。正如你所看到的,列表非常长!
调试
如果我们在输入所有需要的脚本之前尝试了计算器,你很可能会看到脚本调试的实际操作。希望你已经设法应对你所看到的,一开始可能会令人不知所措。这就是它的样子:
你在这里看到的大部分内容与你在编辑脚本时看到的内容相同,但如果你看到了调试变体,实际上你处于暂停状态,这是程序运行时的冻结帧。在这个例子中,程序停止是因为第 46 行正在寻找名为dis play
的字段。没有这样的字段,它应该是display
。
面板底部的错误信息清楚地表明错误与字段名称有关,你可以快速找到错误。有时,你可能需要检查变量以确保它们包含你认为应该包含的值,例如,变量选项卡将显示这些值的列表。
一个意外的问题是,你可能看到调试器,但在编写脚本时,你能够通过点击位于你想要停止程序的那一行左侧的列来设置断点。
一旦脚本通过断点停止,你可以使用顶部的按钮行逐行通过代码。当你将鼠标悬停在按钮上方时显示的内容是它的含义。这些按钮是:
-
继续:这将再次运行脚本
-
停止:这会停止脚本运行,并切换到编辑器,以便你可以进行更改
-
显示下一语句:这将在当前行的左侧显示一个指示器
-
进入下一语句:这用于进入不同的处理器
-
跳过下一语句:这用于在不进入当前行上提到的处理器的情况下,进入当前处理器中的下一语句
-
退出当前处理器:这用于跳过之前进入的处理器中剩余的行,并退出到调用当前处理器的处理器
随着你继续操作,你将熟悉脚本编辑器和调试器,但这些都足以让你开始!
在本章中,我们只介绍了足够的内容,让你熟悉环境,以便你可以练习使用一些控件,并进行一些脚本编写。LiveCode 作为一个工具有很多内容,你可能对其他主题感兴趣,或者想要比这里介绍得更深入。
一个好的起点是 LiveCode 自己的在线教程集,这些教程位于lessons.runrev.com/
。
在搜索框中输入描述你感兴趣领域的词语,你将看到该主题的文章列表。
摘要
通过从头创建一个简单的计算器,你现在应该对 LiveCode 环境更加熟悉了。
在本章中,我们介绍了按钮、字段、脚本和堆栈结构,以了解它们是如何协同工作的。我们还展示了几个简短的脚本,以说明 LiveCode 在脚本窗口中调试脚本时使用的类似英语的语法。
然后,我们检查了其他界面控件,为在本书的后续章节中使用这些控件做准备。
我们还讨论了 LiveCode 使用的变量类型以及它如何使用缩写命令和同义词。
现在你已经学到了足够的知识来制作常规的 LiveCode 堆栈,我们需要从 Google 和 Apple 下载并安装额外的软件,这些软件是发布堆栈到移动设备所必需的,然后我们需要开始尝试移动特定的功能——这两者都在下一章中介绍。
第二章。LiveCode 移动入门
在我们能够做些有趣的事情之前…
创建有用的堆栈或最终成为你可以出售的移动应用是一个非常令人满意的过程。你可以分分秒秒地取得进步,并立即看到你所做的改进。不幸的是,在你制作出杰作之前和之后,还有很多不那么令人满意的工作要做。本章将带你了解“之前”的部分。
LiveCode 通过使用你制作的堆栈以及你添加的任何支持文件来制作移动应用,并使用从移动操作系统提供商下载的开发工具编译应用程序文件,对于 Android 是 Google,对于 iOS 是 Apple。
在本章中,我们将:
-
注册 Google Play
-
在 Amazon Appstore 注册账号
-
下载并安装 Android SDK
-
配置 LiveCode,使其知道在哪里查找 Android SDK
-
通过 Apple 成为 iOS 开发者
-
下载并安装 Xcode
-
配置 LiveCode,使其知道在哪里查找 iOS SDK
-
设置模拟器和物理设备
-
在模拟器和物理设备上测试堆栈
注意
免责声明
本章引用了许多我们无法控制的互联网页面。在这里,我们确实展示了截图或 URL,但请记住,自我们撰写本内容以来,内容可能已经发生变化。供应商也可能更改了一些细节,但总的来说,我们对程序的描述应该仍然按照我们所描述的方式工作。
我们开始了...
iOS、Android 还是两者都要?
可能你对 iOS 或 Android 只有兴趣。除非你对另一半的工作原理感到好奇,否则你应该能够轻松地跳转到你感兴趣的章节!如果你像我一样,是一个资本家,那么你应该对这两个操作系统都感兴趣。
获取 Android SDK 所需的步骤比 iOS 开发工具要少得多,因为对于 iOS,我们必须在 Apple 注册为开发者。然而,Android 的配置更为复杂。我们将逐步介绍 Android 的步骤,然后是 iOS 的步骤。如果你是仅使用 iOS 的人,请跳过接下来的几页,从“成为 iOS 开发者”部分重新开始。
成为 Android 开发者
没有注册任何东西就可以开发 Android 操作系统应用。我们将尽量保持乐观,并假设在接下来的 12 个月内,你将找到时间制作一个让你致富的出色应用!为此,我们将概述在 Google Play(以前称为 Android Market)和 Amazon Appstore 发布你的应用所需的所有过程。
Google Play
打开 Google Play 的起始位置是developer.android.com/
:
我们很快会回到这个页面下载 Android SDK,但现在,点击菜单栏中的分发链接,然后点击下一屏幕上的开发者控制台按钮。由于谷歌偶尔会更改这些页面,你可以使用 URL play.google.com/apps/publish/
或搜索“Google Play 开发者控制台”。你将逐步通过的屏幕在这里没有展示,因为它们会随着时间的推移而变化。
将出现一个登录页面;使用你常用的谷歌详细信息登录。
小贴士
使用哪个电子邮件地址?
如果你有一个 Gmail 账户,注册一些谷歌服务会更容易。创建一个 Google+账户或注册他们的一些云服务需要 Gmail 地址(或者当时在我看来是这样的!)!如果你之前已经将谷歌钱包作为账户的一部分设置好,注册步骤中的一些步骤会变得简单。所以,使用你的 Gmail 地址,如果你没有,就创建一个!
谷歌会收取你 25 美元的费用来注册谷歌播放。至少现在,你知道这个信息了!输入开发者名称、电子邮件地址、网站 URL(如果你有的话)和你的电话号码。25 美元的支付将通过谷歌钱包完成,这样你就不必再次输入账单详情。
现在,你已经注册完毕,准备好赚大钱!
亚马逊应用商店
虽然谷歌播放的规则和费用相对宽松,但亚马逊在注册费用和接受应用提交的审查流程方面都采取了更类似苹果的方法。打开亚马逊应用商店的 URL 是 developer.amazon.com/public
:
按照以下步骤开始使用亚马逊应用商店:
-
当你选择开始时,你需要登录你的亚马逊账户。
小贴士
使用哪个电子邮件地址?
这感觉像是 deja vu!在注册亚马逊应用商店开发者程序时使用你的谷歌电子邮件地址并没有真正的优势,但如果你碰巧有亚马逊的账户,就使用那个账户登录。这将简化支付阶段,并且你的开发者账户和一般的亚马逊账户将相互关联。
-
在了解费用之前,你需要同意应用商店分发协议条款。
-
这些费用是每年 99 美元,但第一年是免费的。所以这很好!
-
与谷歌安卓市场不同,亚马逊在注册时就会要求你的银行详情,希望以后能给你发很多钱!
-
就这样,你已经准备好再赚一笔,与谷歌给你的那笔一样多!
快速问答——什么时候某件事变得太多?
你已经完成了你的大型应用开发,它的大小为 49.5 MB,你只需要添加标题屏幕音乐。为什么你不添加你准备好的两分钟的史诗级曲目呢?
-
加载会花费太长时间。
-
人们通常会很快跳过标题屏幕。
-
文件大小将超过 50 MB。
-
重金属可能不适合儿童故事书应用!
答案:3
其他答案也是有效的,尽管您可以将音乐作为外部声音播放以减少加载时间,但如果您的文件大小超过 50 MB,那么您将失去通过蜂窝网络而不是无线网络连接的人的潜在销售。在撰写本书时,所有商店都要求您通过无线网络连接到网站,如果您打算下载超过 50 MB 的应用程序。
下载 Android SDK
返回到 developer.android.com/
并点击 获取 SDK 链接,或直接转到 developer.android.com/sdk/index.html
。此链接默认为您正在运行的操作系统。点击 其他下载选项 链接,查看其他系统的完整选项,如下所示:
注意
在本书中,我们只将涵盖 Windows 和 Mac OS X (Intel),并且仅涵盖使 LiveCode 与 Android 和 iOS SDK 一起工作所需的内容。如果您打算制作基于原生 Java 的应用程序,您可能对阅读网页 developer.android.com/sdk/installing.html
中描述的所有步骤感兴趣。
点击您平台上的 SDK 下载链接。请注意,除非您计划在 LiveCode IDE 之外开发,否则不需要 ADT Bundle。您将必须经历的步骤对于 Mac 和 Windows 是不同的。让我们从 Mac 开始。
在 Mac OS X (Intel) 上安装 Android SDK
LiveCode 本身不需要 Intel Mac;您可以使用基于 PowerPC 的 Mac 开发堆栈,但 Android SDK 和一些 iOS 工具需要基于 Intel 的 Mac,这很遗憾地意味着如果您正坐在您的 Mac G4 或 G5 旁边阅读此内容,您可能不会走得太远!
Android SDK 需要 Java 运行时环境(JRE)。由于苹果停止在较新的 OS X 系统中包含 JRE,您应该通过在终端窗口中输入 java –version
来检查您的系统中是否有它。终端将显示已安装的 Java 版本。如果没有,您可能会收到如下消息:
点击 更多信息 按钮,按照说明安装 JRE 并验证其安装。在撰写本书时,JRE 8 与 OS X 10.10 不兼容,我不得不使用从 support.apple.com/kb/DL1572
获取的 JRE 6。
您刚刚下载的文件将自动展开以显示一个名为 android-sdk-macosx
的文件夹。它现在可能位于您的 下载
文件夹中,但更自然的位置是在您的 文档
文件夹中,因此在执行下一步之前将其移动到那里。
SDK 读取文件中列出了您在安装过程中需要遵循的步骤。如果这些步骤与这里的不同,那么请遵循读取文件中的步骤,以防它们自这里编写程序以来已更新。
打开终端应用程序,它在应用程序/实用工具中。您需要更改 android-sdk-macosx
文件夹中现有的默认目录。使用终端的一个实用技巧是,您可以拖动项目到终端窗口以获取该项目的文件路径。使用这个技巧,您可以在终端窗口中键入 cd
和一个空格,然后拖动 android-sdk-macosx
文件夹到空格字符后面。如果您的用户名是 Fred,您将得到以下行:
new-host-3:~ fred$ cd /Users/fred/Documents/android-sdk-macosx
当然,行首的用户文件夹将与您匹配,而不是 Fred 的!
无论您的名字是什么,在输入前面的行之后,按回车或Enter键。位置行现在将更改为如下所示:
new-host-3:android-sdk-macosx colin$
您可以仔细键入或从读取文件中复制并粘贴以下行:
tools/android update sdk --no-ui
再次按回车或Enter键。文件下载所需的时间取决于您的互联网连接。即使互联网连接非常快,也可能需要超过一个小时。
如果您想跟踪更新进度,只需在 tools
目录中运行 android
文件。这将打开 Android SDK 管理器,它与本书中几页后展示的 Windows 版本类似。
在 Windows 上安装 Android SDK
下载页面建议您使用 .exe
下载链接,因为它为您提供了额外服务,例如检查您是否已安装Java 开发工具包(JDK)。当您点击链接时,可以使用运行或保存选项,就像下载任何 Windows 安装程序一样。在这里,我们选择使用运行;如果您选择保存,那么您需要在文件保存到您的硬盘后打开该文件。在以下情况下,由于 JDK 未安装,会弹出一个对话框提示您前往 Oracle 网站获取 JDK:
如果您也看到这个屏幕,您可以保持对话框打开,并点击访问 java.oracle.com按钮。在 Oracle 页面上,点击复选框同意他们的条款,然后点击与您的平台对应的下载链接。如果您正在运行 64 位版本的 Windows,请选择 64 位选项;如果您正在运行 32 位版本的 Windows,请选择 x86 选项。
无论哪种方式,您都会遇到另一个安装程序,您可以根据喜好运行或保存。当然,安装程序完成其任务也需要一段时间!安装完成后,您将看到一个 JDK 注册页面,您可以选择是否注册。
回到 Android SDK 安装程序对话框,你可以点击后退按钮,然后点击下一步按钮回到 JDK 检查阶段;但现在,它看到你已经安装了 JDK。像任何 Windows 安装程序一样完成 SDK 安装程序的剩余步骤。
需要注意的一个重要事项是,安装程序的最后一屏会提供打开 SDK 管理器的选项。你应该这么做,所以请抵制取消勾选该框的诱惑!
点击完成,你将短暂地看到一个命令行窗口,如以下截图所示,然后,Android SDK 管理器将出现并执行其操作:
与 Mac 版本一样,所有这些附加组件的下载需要非常长的时间。
将 LiveCode 指向 Android SDK
在完成所有安装和命令行工作之后,回到 LiveCode 是一种令人耳目一新的变化!
打开LiveCode 首选项并选择移动支持:
我们将在 iOS 启动后设置两个 iOS 条目(但在 Windows 中这些选项将会变灰)。目前,请点击 Android 开发 SDK 根字段旁边的…按钮,并导航到 SDK 安装的位置。如果你已经正确地遵循了前面的步骤,那么 SDK 将在 Mac 的Documents
文件夹中,或者在 Windows 上你可以导航到C:\Program Files (x86)\Android\
来找到它(或者如果你选择使用自定义位置,可能在其他地方)。
根据 SDK 管理器中加载的 API,你可能会收到一条消息,指出路径不包括对 Android 2.2(API 8)的支持。如果是这样,请使用 Android SDK 管理器来安装它。尽管此时 Android 5.0 使用 API 21,但 LiveCode 似乎需要 API 8。
呼吸!现在,让我们为 iOS 做同样的事情…
快速问答 - 美味的代号
安卓操作系统为每个版本使用一些奇怪的代号。在撰写本书时,我们使用的是 Android OS 5,其代号为 Lollipop。版本 4.1 是 Jelly Bean,版本 4.4 是 KitKat。以下哪个最可能是下一个 Android 操作系统的代号?
-
柠檬芝士蛋糕
-
小吃
-
面条
-
棉花糖
答案:4
如果不明显的话,模式是这样的:代号采用字母表的下一个字母,是一种食物,但更具体地说,是一种甜点。"Munchies"几乎适用于 Android OS 6,但"Marshmallow"或"马卡龙"会是更好的选择!
成为 iOS 开发者
创建 iOS LiveCode 应用程序需要 LiveCode 能够访问 iOS SDK。这作为 Xcode 开发者工具的一部分进行安装,并且是仅限 Mac 的程序。此外,当您将应用程序上传到 iOS App Store 时,所使用的应用程序仅限 Mac,并且是 Xcode 安装的一部分。如果您是 Windows 基础的开发者,并且希望为 iOS 开发和发布,您需要一个实际的基于 Mac 的系统或一个可以运行 Mac OS 的虚拟机。我们甚至可以使用 VirtualBox 来运行基于 Mac 的虚拟机,但性能可能会成为问题。有关更多信息,请参阅 apple.stackexchange.com/questions/63147/is-mac-os-x-in-a-virtualbox-vm-suitable-for-ios-development
。
成为 Android 开发者和成为 iOS 开发者之间最大的区别是,即使您从未为 iOS App Store 制作过应用程序,您也必须注册 Apple 的开发者计划,而成为 Android 开发者则不需要这样的注册。如果一切顺利,您为各种商店制作了应用程序,那么这并不是什么大问题。将应用程序提交到 Android Market 需要支付 $25,将应用程序提交到 Amazon Appstore 需要支付每年 $99(第一年免费),而成为 Apple 的 iOS 开发者每年需要支付 $99(包括第一年)。只需尝试卖出超过 300 份您那令人惊叹的 $0.99 应用程序,您就会发现这已经足够支付费用了!
注意,LiveCode 会员资格包括免费的 iOS App Store 和应用程序许可,每年费用为 $99。作为 LiveCode 会员,您可以提交您的免费非商业应用程序给 RunRev,他们将提供一份许可,允许您将应用程序作为“封闭源代码”提交到 iOS App Store。这项服务仅限于 LiveCode 会员。每年第一次提交是免费的;之后,每次提交需支付 $25 的管理费。有关更多信息,请参阅 livecode.com/membership/
。
您可以在 developer.apple.com/programs/ios/
注册 iOS 开发者计划:
在注册成为 iOS 开发者时,您的当前状态有多种可能性。如果您已经有了 Apple ID,您可以使用它来购买 iTunes 或 Apple 在线商店的产品,您可以选择我已经有 Apple ID…选项。为了说明注册的所有步骤,我们将从一个全新的用户开始,如下面的截图所示:
您可以选择是否以个人身份或公司身份注册。我们将选择个人,如下面的截图所示:
在任何此类注册过程中,您都需要输入您的个人详细信息,设置安全问题,并输入您的邮政地址:
大多数苹果软件和服务都有自己的法律协议供您签署。以下截图显示的是一般的 注册苹果开发者协议:
为了验证您使用的电子邮件地址,会通过电子邮件发送一个带有链接的验证码给您,您可以点击此链接,或者手动输入代码。一旦您完成了验证码步骤,您就可以输入您的账单详情。
可能您会继续为 Mac App Store 开发 LiveCode 应用程序,在这种情况下,您需要添加 Mac 开发者计划 产品。对于我们来说,我们只需要注册 iOS 开发者计划,如下截图所示:
您注册的每个产品都有自己的协议。有很多小字需要阅读!
实际购买 iOS 开发者账户是通过您所在地区的苹果商店处理的,如下所示:
如您在下一张截图中所见,如果您也注册了 Mac 开发者账户,那么这将花费您每年 $99 或 $198。大多数 LiveCode 用户不需要注册 Mac 开发者账户,除非他们的计划是向 Mac App Store 提交桌面应用程序。
在提交订单后,您会收到一条消息,告诉您您现在已注册为苹果开发者!
很遗憾,您不会立即获得批准,就像 Android 市场或亚马逊应用商店那样。您必须等待五天的批准。在早期 iPhone 开发者时期,批准可能需要一个月或更长时间,所以 24 小时是一个改进!
快速问答 - iOS 代码名
关于 Android 操作系统代码名的快速问答您可能觉得很简单!但对于 iOS 来说并非如此。
以下哪个名称更有可能是 iOS 未来版本的代码名?
-
拉斯维加斯
-
拉古纳海滩
-
Hunter Mountain
-
死亡谷
答案:3
虽然没有公开宣传,但苹果确实为每个 iOS 版本使用代码名。之前的例子包括 Big Bear、Apex、Kirkwood 和 Telluride。这些,以及其他所有名称显然都是滑雪胜地。Hunter Mountain 是一个相对较小的山(3,200 英尺),所以如果它被使用,可能只是一个小更新!
安装 Xcode
一旦您收到成为 iOS 开发者的确认,您将能够登录到 iOS 开发中心,网址为 developer.apple.com/devcenter/ios/index.action
。
这个页面被不使用 LiveCode 的 iOS 开发者所使用,里面充满了可以帮助你使用 Xcode 和 Objective-C 创建原生应用的支持文档。我们不需要所有这些支持文档,但我们确实需要下载 Xcode 的支持文档。
在 iOS Dev Center 页面的下载区域,你会看到一个链接指向当前版本的 Xcode,以及一个链接可以访问旧版本。当前版本通过 Mac App Store 提供;当你尝试给定的链接时,你会看到一个按钮,它会带你到 App Store 应用。
从 Mac App Store 安装 Xcode 非常简单。它就像在商店购买任何其他应用一样,只是它是免费的!但它确实要求你使用最新的 Mac OS X 版本。Xcode 将出现在你的Applications
文件夹中。
如果你使用的是旧系统,那么你需要从开发者页面下载旧版本之一。旧版本的 Xcode 安装过程与其他 Mac 应用的安装过程非常相似:
旧版本的 Xcode 安装需要很长时间,但最终,你应该有一个为 LiveCode 准备的Developer
文件夹或新的 Xcode 应用。
小贴士
处理新旧设备
在 2012 年初,苹果推出了一款新的 iPad 版本。与 iPad 2 相比,这款产品的卖点主要是它拥有 Retina 显示屏。原始的 iPad 分辨率为 1024 x 768,而 Retina 版本分辨率为 2048 x 1536。如果你希望构建利用这一特性的应用,你必须从 Mac App Store 获取当前版本的 Xcode,而不是从开发者页面获取旧版本。新版本的 Xcode 要求你在 Mac OS 10.10 或更高版本的操作系统上工作。因此,为了完全支持最新的设备,你可能需要更新你的系统软件比预期的更多!但是等等,还有更多……通过使用较晚版本的 Xcode,你将错过支持旧版 iOS 设备(如原始 iPhone 和 iPhone 3G)所需的 iOS SDK 版本。幸运的是,你可以在 Xcode 的“首选项”中找到这些旧 SDK,在“下载”标签页中你可以下载这些旧 SDK 到新版本的 Xcode 中。通常,苹果只允许你下载比当前 Xcode 提供的版本旧一个版本的 SDK。虽然有一些旧版本可用,但苹果不认可这些版本用于 App Store 提交。
将 LiveCode 指向 iOS SDKs
打开 LiveCode 的首选项并选择移动****支持:
在窗口右上角点击 添加条目 按钮,将看到一个对话框询问您是否使用 Xcode 4.2 或 4.3 或更高版本。如果您选择 4.2,那么继续选择您硬盘根目录下名为 Developer
的文件夹。对于 4.3 或更高版本,请选择您的 Applications
文件夹中的 Xcode 应用程序。LiveCode 知道如何找到 iOS 的 SDK。
在我们制作第一个移动应用之前...
现在所需的 SDK 已安装,LiveCode 也知道它们的位置,我们可以在模拟器或物理设备上制作堆栈并测试它。然而,我们确实需要预热模拟器和物理设备...
准备在 Android 设备上进行测试开发
在 iOS 上模拟比在 Android 上更容易,在物理设备上测试比在 iOS 上更容易,但设置物理 Android 设备可能非常困难!
行动时间 - 启动 Android 虚拟设备
您可能需要深入 Android SDK 文件夹以找到 Android 虚拟设备设置程序。您不妨为它提供一个快捷方式或别名以便快速访问。以下步骤将帮助您设置并启动一个 Android 虚拟设备:
-
在 Windows 上,导航到位于
C:\Program Files (x86)\Android\android-sdk\
的 Android SDK 工具文件夹,在 Mac 上导航到您的Documents/android-sdk-macosx/tools
文件夹。 -
在 Windows 上打开 AVD 管理器或在 Mac 上打开 android(这些看起来像 Unix 可执行文件;只需双击它,应用程序将通过命令行窗口打开)。
-
如果您使用的是 Mac,请从 工具 菜单中选择 管理 AVDs…。
-
如果设备列表中有 平板电脑,请从列表中选择。如果没有,您可以根据以下章节的说明添加自己的自定义设备。
-
点击 开始 按钮。
-
在虚拟设备启动时耐心等待!
-
打开 LiveCode,创建一个新的 Mainstack,然后点击 保存 将堆栈保存到您的硬盘上。
-
导航到 文件 | 独立应用程序设置…。
-
点击 Android 图标,然后点击 为 Android 构建复选框以选择它。
-
关闭设置对话框,查看 开发 菜单。
-
如果虚拟机正在运行,您应该会在 测试目标 子菜单中看到它。
创建 Android 虚拟设备
如果在打开 Android 虚拟设备(AVD)管理器时没有列出设备,您可能需要...如果您想创建一个设备,请点击 创建 按钮。执行此操作时将出现以下截图。有关各个字段的进一步说明,请参阅 developer.android.com/tools/devices/index.html
。
在您创建了一个设备之后,您可以点击开始来启动虚拟设备并更改一些启动选项。通常情况下,您应该选择按实际大小缩放显示,除非它对于您的开发屏幕来说太大。然后,点击启动来启动模拟器。有关如何运行模拟器的更多信息,可以在developer.android.com/tools/help/emulator.html
找到。
刚才发生了什么?
现在您已经打开了一个 Android 虚拟设备,LiveCode 将能够使用此设备测试堆栈。一旦它加载完成,就可以这样做!
连接物理 Android 设备
连接物理 Android 设备可能非常直接:
-
通过 USB 将您的设备连接到系统。
-
从开发 | 测试目标子菜单中选择您的设备。
-
从开发菜单中选择测试,或者点击工具栏中的测试按钮。
尽管如此,可能会有一些问题情况,在您解决完这些问题之前,Google 搜索将成为您的最佳朋友!我们应该看看一个示例问题情况,这样您就可以了解如何解决您可能遇到的类似情况。
使用 Kindle Fire
当涉及到查找 Android 设备时,Android SDK 会自动识别很多设备。有些设备没有被识别,您需要做些事情来帮助Android 调试桥接器(ADB)找到这些设备。
Android 调试桥接器(ADB)是 Android SDK 的一部分,它充当您的设备与任何需要访问设备的软件之间的中介。在某些情况下,您需要进入设备的 Android 系统,告诉它允许开发目的的访问。例如,在 Android 3(蜂巢)设备上,您需要进入设置 | 应用程序 | 开发菜单,并激活USB 调试模式。在 ADB 连接到 Kindle Fire 设备之前,该设备必须首先进行配置,以便允许连接。这是第一代 Kindle Fire 设备上的默认设置。在所有其他 Kindle Fire 型号上,进入设备设置屏幕,选择安全,并将启用ADB 设置为开启。
原始的 Kindle Fire 型号已经启用了 USB 调试,但 ADB 系统根本不知道这个设备。您可以修复这个问题!
行动时间 – 将 Kindle Fire 添加到 ADB
只需一行文本即可将 Kindle Fire 添加到 ADB 所知的设备列表中。困难的部分是找到要编辑的文本文件,并在进行必要的更改后重启 ADB。在 Windows 上使用时比在 Mac 上更复杂,因为您还需要配置 USB 驱动程序,所以这两个系统在这里被展示为单独的步骤。
将 Kindle Fire 添加到 Windows 操作系统中的 ADB 的步骤如下:
-
在 Windows 资源管理器中,导航到
C:\Users\yourusername\.android\
,这是adv_usb.ini
文件所在的位置。 -
在文本编辑器中打开
adv_usb.ini
文件。该文件没有可见的换行符,因此最好使用 WordPad 而不是记事本。 -
在三条指令行之后的一行,输入
0x1949
。 -
确保文件中没有空白行;文本文件的最后一个字符在
0x1949
的末尾应该是9
。 -
现在,保存文件。
-
导航到
C:\Program Files (x86)\Android\android-sdk\extras\google\usb_driver\
,这是android_winusb.inf
文件所在的位置。 -
右键单击文件,在 属性、安全 中从列表中选择 用户 并点击 编辑 来设置权限,以便你可以写入文件。
-
在记事本中打开
android_winusb.inf
文件。 -
将以下三行添加到
[Google.NTx86]
和[Google.NTamd64]
部分,并保存文件:;Kindle Fire %SingleAdbInterface% = USB_Install, USB\VID_1949&PID_0006 %CompositeAdbInterface% = USB_Install, USB\VID_1949&PID_0006&MI_01
-
你需要设置 Kindle,使其使用你刚刚编辑的 Google USB 驱动程序。
-
在 Windows 控制面板中,导航到 设备管理器 并在 USB 下的列表中找到 Kindle 条目。
-
右键单击 Kindle 条目并选择 更新驱动程序软件…。
-
选择允许你在本地驱动器上找到驱动器的选项,导航到
google\usb_driver\
文件夹,然后选择它作为新驱动器。 -
当驱动程序更新时,打开命令窗口(打开命令窗口的一个方便技巧是在桌面上使用 Shift-右键单击并选择“在此处打开命令窗口”)。
-
通过输入以下命令更改目录到 ADB 工具所在的位置:
cd C:\Program Files (x86)\Android\android-sdk\platform-tools\
-
输入以下三行代码,并在每行后按 Enter 键:
adb kill-server adb start-server adb devices
-
如果你仍然运行着虚拟设备,你应该会看到 Kindle Fire(以一个看起来很神秘的数量)以及虚拟设备被列出。
对于 Mac(系统)的步骤(非常简单!)如下:
-
导航到
adv_usb.ini
文件所在的位置。在 Mac 上,在 Finder 中,通过导航到 前往 | 前往文件夹… 并输入~/.android/
来选择。 -
在文本编辑器中打开
adv_usb.ini
文件。 -
在三条指令行之后的一行,输入
0x1949
。 -
确保文件中没有空白行;文本文件的最后一个字符在
0x1949
的末尾应该是9
。 -
保存
adv_usb.ini
文件。 -
导航到 实用工具 | 终端。
-
你可以通过输入以下行让 OS X 知道如何从任何地方找到 ADB(将
yourusername
替换为你的实际用户名,如果你将 Android SDK 安装到了其他位置,也请更改路径):export PATH=$PATH:/Users/yourusername/Documents/android-sdk-macosx/platform-tools
-
现在,尝试与 Windows 相同的三个步骤:
adb kill-server adb start-server adb devices
-
再次,你应该在这里看到 Kindle Fire 被列出。
发生了什么?
我怀疑你将会因为所有这些步骤而做噩梦!在网络上进行了大量的研究才找到了一些这些神秘的技巧。在 Windows 上使用 Android 设备的一般情况是,你必须修改设备的 USB 驱动程序,以便使用 Google USB 驱动程序来处理,你可能还需要修改adb_usb.ini
文件(在 Mac 上也是如此),以便将设备视为 ADB 兼容设备。
准备在 iOS 设备上进行测试开发
如果你仔细地完成了所有这些 Android 步骤,尤其是在 Windows 上,你可能会对这个部分的简短感到惊讶!但是有一个问题;你实际上无法从 LiveCode 在 iOS 设备上进行测试。我们稍后会看看你需要做什么,但首先,我们将看看在 iOS 模拟器中测试应用程序所需的步骤。
行动时间 - 使用 iOS 模拟器
初始步骤与我们为 Android 应用程序所做的大致相同,但在后续步骤中,这个过程会变得更快。记住,这仅适用于 Mac OS;如果你在虚拟机中使用 Mac OS,则只能在 Windows 上执行这些操作,这可能会导致性能问题。这很可能不在 Mac OS 的用户协议范围内!换句话说,如果你打算为 iOS 开发,请获取 Mac OS。以下步骤将帮助你实现这一点:
-
打开 LiveCode,创建一个新的主堆栈,并将其保存到你的硬盘上。
-
选择文件,然后选择独立应用程序设置…。
-
点击 iOS 图标以选择为 iOS 构建复选框。
-
关闭设置对话框,查看开发下的测试目标菜单。
-
您将看到 iPhone 和 iPad 的模拟器选项列表以及不同版本的 iOS。
-
要启动 iOS 模拟器,选择一个选项,然后点击测试按钮。
刚才发生了什么?
这就是我们使用 iOS 模拟器完成测试所需的所有步骤!要在物理 iOS 设备上进行测试,我们首先需要创建一个应用程序文件。让我们来做这件事。
最后,应用程序开发成功!
到目前为止,你应该能够创建一个新的主堆栈,保存它,在独立设置对话框中选择 iOS 或 Android,并在开发/测试菜单项中看到模拟器或虚拟设备。在 Android 应用程序的情况下,如果你在此时通过 USB 连接,你也会看到你的设备列出来。
行动时间 - 在模拟器中测试简单的堆栈
感谢你使用我们这些步骤制作出比我们更复杂的东西!以下说明假设你知道如何在对象检查器调色板中自己找到东西:
-
打开 LiveCode,创建一个新的主堆栈,并将其保存到一个容易找到的地方。
-
将卡片窗口的大小设置为 480 x 320,并取消选择可调整大小复选框。
-
将标签字段拖到卡片窗口的左上角,并设置其内容为适当的内容。"Hello World"可能就足够了。
-
如果你正在 Windows 上开发,请跳到步骤 11。
-
打开独立应用程序设置对话框,点击 iOS 图标,然后点击为 iOS 构建复选框。
-
在方向选项下,将iPhone 初始方向设置为横屏左。
-
关闭对话框。
-
导航到开发 | 测试目标子菜单并选择 iPhone 模拟器。
-
从开发菜单中选择测试。
-
你现在应该能够在 iOS 模拟器中看到你的测试栈正在运行!
-
如前所述,启动 Android 虚拟设备。
-
打开独立应用程序设置对话框,点击 Android 图标,然后点击为 Android 构建复选框。
-
在用户界面选项下,将初始方向设置为横屏。
-
关闭对话框。
-
如果虚拟设备现在正在运行,请尽一切努力越过锁定的主屏幕,如果它显示的是这个屏幕。
-
从开发/测试目标子菜单中选择Android 模拟器。
-
从开发菜单中选择测试。
-
你现在应该能在 Android 模拟器中看到你的测试栈正在运行!
发生了什么?
如果一切顺利,你刚刚在 Android 和 iOS 上都制作并运行了你的第一个移动应用!为了锦上添花,我们应该只在物理设备上尝试,这样可以让 Android 有机会展示它有多容易完成。还有一些我们没有打开的“大问题”,这与配置 iOS 设备有关,以便它可以用于测试。这部分内容将在第七章中详细介绍,部署到您的设备,你现在可以阅读它,或者你可以访问 iOS 配置文件门户developer.apple.com/ios/manage/overview/index.action
,并查看每个不同部分的如何操作标签。
行动时间 - 在设备上测试简单栈
现在,让我们尝试在物理设备上运行我们的测试。准备好您的 USB 线缆并将设备连接到您的计算机。
让我们先来了解一下在 Android 设备上的步骤:
-
你仍然需要在独立应用程序设置中选择 Android。
-
如果有初始锁屏,请将您的设备切换到主屏幕。
-
选择开发/测试目标并选择您的 Android 设备。它可能说“Android”和一个非常长的数字。
-
选择开发/测试。
-
栈现在应该在您的 Android 设备上运行。
现在,我们将通过以下步骤在 iOS 设备上测试一个简单栈:
-
如果你还没有阅读第七章,即关于如何将当前环境部署到您的设备或苹果页面的指南,或者还没有安装证书和配置文件,你现在将不得不跳过这个测试。
-
将独立应用程序设置改回iOS。
-
在 iOS 设置的基本应用程序设置下,有一个配置文件的配置文件下拉菜单。选择一个为你将要测试的设备配置的配置文件。
-
关闭对话框,并从文件菜单中选择另存为独立应用程序…。
-
在Finder中找到刚刚创建的文件夹,并打开它以显示应用程序文件本身。由于我们没有给堆栈起一个有意义的名字,它将被命名为未命名 1。
-
打开
Xcode
,它位于你之前安装的Developer
文件夹中的Applications
子文件夹。 -
如果
Xcode
文件夹未选中,请在窗口菜单中选择设备。 -
你应该能看到你的设备列出来。选择它,如果你看到一个标有用于开发的按钮,点击该按钮。
-
将应用程序文件直接从Finder菜单拖到设备窗口中的你的设备上。你应该看到一个带有+号的绿色圆圈。你还可以点击已安装应用程序下方的+号,并在Finder窗口中找到你的应用程序文件。你还可以从这个窗口替换或删除已安装的应用程序。
-
你现在可以在你的 iOS 设备上打开应用程序了!
发生了什么?
除了在真实设备上使测试堆栈工作之外,我们还看到了一旦配置完成,直接在 Android 设备上测试堆栈是多么容易。如果你正在开发一个将在 Android 和 iOS 上部署的应用程序,你可能发现使用 iOS 模拟器进行 iOS 测试可能是最快的工作方式,但为此,你需要直接在 Android 设备上测试,而不是使用 Android SDK 虚拟设备。
尝试一下英雄 - Nook
直到最近,Barnes & Noble 的 Nook Color 对 Android 的支持还不够好,无法安装 LiveCode 应用程序。但似乎有所改善,可能又是一个值得你关注的软件商店。
调查注册过程、下载他们的 SDK 等。如果有任何运气,你在注册其他商店时学到的某些流程也可能适用于 Nook 商店。你可以从这里开始注册过程:
nookdeveloper.barnesandnoble.com
。
进一步阅读
SDK 提供商 Google 和 Apple 提供了大量关于如何设置开发环境、创建证书和配置文件的页面信息。这些信息涵盖了大量不适用于 LiveCode 的主题,所以尽量不要迷失方向!如果你想要进一步阅读,以下 URL 将是良好的起点:
摘要
注册程序、下载文件、到处使用命令行,并耐心等待 Android 模拟器启动——完成本章所涵盖的内容可能需要花费一天中的大部分时间!幸运的是,你只需要经历一次。
在本章中,我们完成了一系列任务,这些任务是在你使用 LiveCode 创建移动应用之前必须完成的。在我们能够下载和安装 Xcode 和 iOS SDK 之前,我们必须注册为 iOS 开发者。然后我们下载并安装了 Android SDK,并配置了 LiveCode 以支持设备和模拟器。
我们还介绍了一些在你准备好上传完成的应用时将非常有用的主题。我们展示了如何注册 Android 市场和 Amazon 应用商店。
在本书的结尾,我们还将介绍一些更平凡的事情,但不是现在!接下来,我们将开始探索移动设备的一些特殊功能。
第三章。构建用户界面
有这么多不同的屏幕!
在为台式计算机制作实用程序或游戏应用程序时,你通常可以避开特定大小的窗口,并为它制作完全适合的定制图形。在移动设备上,你必须应对广泛的屏幕尺寸和宽高比,并且还需要有适合用户设备操作系统的界面元素。
LiveCode 能够在 Mac、Windows 和 Linux 上发布,并在一定程度上解决了为每个平台制作界面元素看起来正确的问题。视图 菜单中有一个 外观和感觉 菜单项,你可以从中选择 原生主题、Mac OS Classic、Windows 95 和 Motif。对于移动操作系统来说,情况并非如此,因为所有控件看起来都像 Motif。尽管如此,你仍然有两个选择:你可以创建看起来属于目标操作系统的图形,或者你可以调用原生例程,以便让系统本身显示适当的控件。
在本章中,我们将:
-
设置一个 测试床 移动应用程序
-
打开电子邮件和浏览器窗口
-
显示日期选择器控件
-
从图库和相机加载图片
-
创建一个 iOS 风格的按钮
-
手动布局界面
-
使用代码来布局界面
-
查看一个强大的移动界面控制的附加组件
设置测试床移动应用程序
作为我们要尝试的事情的试验场,我们将设置一个具有多个屏幕的单个移动应用程序,每个屏幕对应我们想要测试的每个事物。
我们应该怎么称呼测试床应用程序?我们可以叫它几乎任何名字,但我们将让 iPhone 为我们做出决定。在 iPhone 和 iPod touch 上,主屏幕图标下方只有一小块空间显示名称。iOS 会显示你的长应用程序名称,并使用省略号将名称的末尾连接起来,显示名称的缩短版本。我的超级无敌应用程序将显示为 My sup…app,信息量不是很大!在不截断文本的情况下可以显示的字母数量会根据使用的字母宽度而变化,但通常,它有一个 11 个字母的限制。因此,我们将测试床应用程序命名为 LC Test Bed,正好是 11 个字母!
行动时间 - 制作测试床栈
在我们创建 iOS 和 Android 应用之前,我们应该准备好我们想要的内容,作为一个 LiveCode 栈,并在我们的台式计算机上对其进行全面测试。以下步骤将假设你知道如何在 LiveCode 中完成所要求的内容,而不需要精确的指令。
-
打开 LiveCode,创建一个新的 主栈,并将其保存为
LCTestBed
。 -
设置屏幕大小为 320 x 480。这只是确保在最小的屏幕上显示内容。我们将制作的内容将出现在较大屏幕的左上角区域。
-
我们将为栈中的每一张卡片制作一个按钮;让我们先制作一个名为 菜单 的卡片。
-
添加电子邮件、浏览器、日期选择器和图片按钮。确保按钮足够大,可以在你的设备上触摸。你应该有如下所示的内容:
-
创建四张新的卡片,并将每张卡片的名称与按钮名称匹配。
-
回到第一张卡片,将每个按钮的脚本设置为跳转到匹配的卡片,使用以下脚本:
on mouseUp go card the short name of me end mouseUp
-
在每张卡片上创建一个按钮,用于返回菜单卡片。将按钮命名为
Menu
。设置其脚本与其他按钮相同。 -
选择运行(浏览)工具并尝试点击按钮跳转到四张卡片并返回到菜单。
刚才发生了什么?
嗯,没有什么特别激动人心的!然而,你现在应该有五张卡片,并且能够进入和退出菜单卡片。我们将为每张卡片添加脚本以帮助说明其各种功能。最有效的方法是添加所有脚本和相关按钮以及字段,然后一次性测试最终的测试床应用。然而,那样有什么乐趣呢!相反,我们将一次添加一个功能…
调用桌面电子邮件应用
有许多情况你可能想从你的应用程序用户那里得到反馈。也许,你希望他们通过电子邮件提出改进建议或向你提问。你可以轻松地启动他们的电子邮件程序,让用户自己决定写什么。或者,你可以设置收件人地址、主题,甚至消息的正文部分。至少,这会使你的生活更轻松,因为你可以根据你在主题字段中放置的内容过滤收到的电子邮件。
行动时间 - 调用原生电子邮件应用
在以下步骤中,我们将创建一些字段和一个按钮来尝试发送电子邮件功能:
-
前往电子邮件卡片并创建四个字段。将它们命名为收件人、抄送、主题和正文。
-
创建一个名为测试的按钮。
-
在测试按钮中添加以下脚本:
on mouseUp put field "To" into toText put field "CC" into ccText put field "Subject" into subjectText put field "Body" into bodyText revMail toText,ccText,subjectText,bodyText end mouseUp
-
选择运行工具并在每个字段中输入示例信息。
-
在设置独立应用程序设置…并选择测试目标后,点击测试按钮。
刚才发生了什么?
LiveCode 语法的巧妙之处在于,移动端的代码也适用于桌面应用程序,反之亦然。如果一切顺利,当你点击测试按钮时,你将发现自己已经进入了默认的电子邮件应用,准备发送你在 LiveCode 堆栈字段中输入的消息。
在设备上安装电子邮件测试
桌面测试能够成功运行并不令人惊讶。打开其他应用程序的能力是 LiveCode 的基本功能。尽管如此,发送一些初始文本给新消息还是很有趣的。接下来,我们应该检查这也在设备上是否可行。
行动时间 - 在设备上尝试测试床堆栈
使用 USB 将你的 Android 和/或 iOS 设备连接到电脑。这些说明几乎与上一章中测试 "Hello World" 堆栈时的说明相同。从这一点开始,任何指示都将更简短,并基于你已知在设备上测试应用程序的步骤。第七章,将应用程序部署到您的设备,描述了 独立应用程序设置 对话框中的所有选项。目前,我们只将填写一些细节,所以在这里,我们将只查看对话框的一部分,从 Android 设置开始:
-
确保在 独立应用程序设置 对话框中勾选了 Android。
-
在 标识符 字段中,输入一个唯一的标识符;
com.yourname.lctestbed
就可以。 -
如果有初始锁屏,将设备切换到主屏幕。
-
在 LiveCode 中,选择 开发/测试目标 并选择你的 Android 设备。它将被命名为 Android 后跟一个长数字。
-
选择 开发/测试 选项。
-
编译后,堆栈应该在您的 Android 设备上运行,您应该能够触摸 电子邮件 按钮并执行一个测试消息,该消息将使用 Android 电子邮件应用程序。
在 iOS 上,如果你还没有这样做,请阅读第七章,将应用程序部署到您的设备,了解如何将应用程序部署到您的设备。至少阅读那些展示如何安装您的 iOS 开发者证书和配置文件的章节。就像 Android 一样,我们只会在独立应用程序设置中更改几个项目。以下是我们将要更改的对话框截图:
对 iOS 设备执行以下步骤:
-
将 独立应用程序设置 更改为 iOS。
-
在 iOS 设置的 基本应用程序设置 下,有一个 配置文件 下拉菜单,用于选择你已安装的配置文件。选择一个为你将要测试的设备配置的配置文件。
-
在 内部应用程序 ID 字段中,输入一个唯一的 ID。就像 Android 一样,
com.yourname.lctestbed
就可以。当然,yourname
将是你的名字或公司名字。 -
如果你正在 iPad 上测试,从 支持设备 下拉菜单中选择 iPod, iPhone 和 iPad 选项。
-
关闭对话框,并从 文件 菜单中选择 另存为独立应用程序…。
-
保存完成后,你可能看到一个警告消息,告诉你缺少启动画面和图标。现在这并不重要。
-
在 Finder 中找到刚刚创建的文件夹,并打开它以显示应用程序文件本身。
-
打开 Xcode 并从 窗口 菜单中选择 设备。
-
您应该能看到您的设备列出来。选择它,如果您看到一个标记为用于开发的按钮,请点击该按钮。
-
直接从查找器窗口将应用程序文件拖放到您的设备在组织者窗口中。
-
设备旁边的小彩色圆圈会暂时变成橙色,然后变回绿色。
-
现在,您可以打开应用程序并尝试邮件按钮和测试消息,这将使用标准的 iOS 邮件应用程序。
发生了什么?
我们已经完成了在 Android 和 iOS 设备上安装测试床应用程序所需的步骤。我们还必须在独立应用程序设置中更改一些事情。如您所见,那里有很多设置。您可以在第七章中期待了解它们的所有内容,将应用程序部署到您的设备!
打开网页
您的应用程序中还有一个要求,就是能够展示额外的在线信息。您希望用户点击链接,或者触摸,以便他们被带到列出用户可以从您那里购买的所有其他应用程序的页面!
行动时间 - 调用原生浏览器应用程序
下一个测试将会更快,或者至少,说明将会更简短,因为我们将会将一些步骤浓缩成更简洁的指示,如下所示:
-
复制测试按钮,将其从邮件卡片粘贴到浏览器卡片上,这样您可以节省一些时间来使按钮看起来更美观。
-
编辑测试按钮脚本并将其更改为以下内容:
on mouseUp launch url "http://www.runrev.com/" end mouseUp
-
选择运行工具并点击测试按钮。您将在默认浏览器中看到 RunRev 的主页。
在设备上尝试应用程序的步骤与测试电子邮件功能的步骤完全相同。对于 Android:
-
在独立应用程序设置中选择 Android。
-
从开发菜单中选择您的 Android 设备作为测试目标(最有可能的是,它仍然是从之前选择的)。
-
从开发菜单中选择测试。
-
应用程序的前一个测试将被覆盖,并将自动启动新版本。
-
尝试点击您在浏览器卡片上刚刚创建的浏览器按钮和测试按钮。如果您点击它们,应该会打开
runrev.com/
页面。
对于 iOS:
-
在独立应用程序设置中选择 iOS。
-
重新执行另存为独立应用程序,然后将应用程序文件拖放到 Xcode 的组织者窗口中,就像您第一次做的那样。
-
尝试点击浏览器和测试按钮;您应该看到 RunRev 的主页在 Safari 中打开。
发生了什么?
与电子邮件测试一样,添加打开网页的标准代码在 Android 和 iOS 上与在桌面计算机上一样有效。
如果你同时在 Android 和 iOS 上进行测试,你会在查看网页后返回时注意到行为的不同。在 Android 上,你可以按返回箭头按钮,仍然处于你的堆栈的浏览器卡片上。在 iOS 上,当你返回时,堆栈会重新启动。我们将在稍后探讨一个解决方案,我们将数据写入外部文件,这样当应用重新打开时,我们可以返回用户在离开应用之前的状态。
仅移动设备使用的日期选择器
接下来的几个示例我们将尝试的,是只在移动设备上工作,而不是在桌面计算机上工作的。
动作时间 - 显示日期选择器
许多应用程序需要用户为事件选择一个日期,并且在使用移动设备时,日期选择器会有一个特定的外观。使用 LiveCode,我们可以显示这样的控件:
-
将浏览器卡片上的Test按钮复制并粘贴到 DatePicker 卡片上。
-
编辑脚本使其看起来像这样:
on mouseUp iphonePickDate "date" end mouseUp
-
选择Run工具并尝试Test按钮。你会看到一个错误,因为这是一个仅适用于移动设备的功能。
-
为了改变一下,从Development/Test Target菜单中选择iPhone或iPad Simulator,然后从Development菜单中选择Test。
-
你会在 iOS 模拟器中看到你的堆栈打开,你可以尝试DatePicker和Test按钮,然后看到 iOS 日期选择器显示出来。
-
使用组织者窗口中的相同旧版“另存为”和安装步骤来尝试在你的 iOS 设备上使用日期选择器。
-
点击菜单卡片上的DatePicker按钮和 DatePicker 卡片上的Test按钮。应该会出现一个 iOS 原生日期选择器。
刚才发生了什么?
希望你现在已经变得更好,能够更快地构建和安装移动应用!除了在设备上再次测试之外,我们还尝试了模拟器。一般来说,只要可能,使用 iOS 模拟器会更快,只有在检查多指触摸、加速度计和相机支持等问题时才需要在设备上进行测试。
动作时间 - 为移动设备加载图片
或许有一天,我们可以从用户的桌面计算机照片应用或他们的网络摄像头中导入图片,但到目前为止,这些功能只适用于移动设备。
LiveCode 可以调用原生的照片库和相机应用。我们将在 Android 和 iOS 上测试这两个应用,但当然,前提是你的设备上保存了一些图片和相机。对于没有相机的 Kindle Fire,请确保你在图库应用中保存了一些图片,这样我们至少可以尝试加载这些图片。按照以下步骤为移动设备加载图片:
-
将
DatePicker
卡片上的Test按钮复制并粘贴到图片卡片上两次。将按钮的名称更改为 Test Camera 和 Test Library。 -
编辑测试相机按钮的脚本为:
on mouseUp mobilePickPhoto "camera" end mouseUp
-
编辑测试库按钮的脚本为:
on mouseUp mobilePickPhoto "library" end mouseUp
-
当我们测试图片加载时,加载的图片将位于测试按钮之上,阻止我们返回到菜单卡片。为了解决这个问题,请将以下内容添加到卡片脚本中:
on mouseUp if word 1 of the target is "image" then delete the target end mouseUp
-
进入独立应用程序设置并选择Android。
-
我们必须请求 Android 操作系统权限来使用相机并存储图片,因此请勾选相机和写入外部存储的复选框:
-
在您的 Android 设备上进行测试步骤,或在 iOS 设备上安装。
-
一旦应用程序在您的设备上运行,请触摸第一个屏幕上的图片,然后测试库。您应该看到典型的操作系统特定选项,用于从您的图库或相册中选择图片。
-
您选择的图片已加载到卡片窗口中,并将填充大部分屏幕,遮挡我们的测试和菜单按钮。我们输入的卡片脚本让您能够触摸图片以删除它,这样您就可以尝试另一个测试。
-
尝试测试相机按钮。您将看到操作系统特定的相机应用程序,当您拍照并在相机应用程序中触摸使用或确定按钮时,图片将被放置在图片卡片上。
刚才发生了什么?
这些简单的脚本说明了 LiveCode 如何能够调用操作系统特定的应用程序来完成其他情况下需要大量编码的工作。更重要的是,随着 iOS 和 Android 操作系统版本的更新,相同的简单脚本可以激活苹果和谷歌将实现的高级功能。
突击测验 - 获得整体概念
Q1. 当提到技术改进时,我们往往认为这是理所当然的。如果您的手机相机只有 2 百万像素,您可能会感到不公平,但回想一下很久以前的事情,以及您习惯看到的大画面。从像素数量来看,一个单张 800 万像素的图片可以容纳多少个原始 Macintosh 屏幕的面积?
-
4
-
15
-
24
-
45
答案:45!
原始 Mac 的屏幕分辨率为 512 x 342 像素。这将在 800 万像素照片的面积中容纳超过 45 次。
制作操作系统风格的按钮
很好,LiveCode 可以调用操作系统的原生控件,但这引发了一个问题,因为当与操作系统按钮一起使用时,标准 Motif 风格的按钮看起来会很丑。我们可以通过使用 LiveCode 的内置功能或使用附加产品来解决这个问题。
使用位图
如我们在第一章中看到的,LiveCode 基础,你可以为按钮的不同状态使用不同的位图。你可以通过在你的移动设备上截图按钮来获取这样的图片,至少在 iOS 和 Android OS v4 及更高版本中可以这样做,或者你也可以通过下载其他人提供的文件来节省大量时间。其中一些文件仅授权用于原型设计;在这里,我们将查看一个也授权用于商业产品的文件。
使用 Photoshop 准备按钮状态的行动时间
我们将要使用的文件包含 Photoshop 滤镜效果,其他程序无法处理,所以很遗憾,你需要 Photoshop 来执行所有这些步骤,或者至少有一个拥有 Photoshop 的朋友!Mac OS X 上的 Pixelmator 和 GraphicConverter 也可以从文件中提取图形,可能只需复制屏幕的一个区域即可。
-
阅读以下文章:
spin.atomicobject.com/2011/03/07/photoshop-template-for-ios-buttons/
-
文章指向了一些其他信息来源;不过,现在请下载以下文件:
-
在 Photoshop 中打开文件(它可能会自动打开)。
-
在图层调板中隐藏名为 Background 和 ToolBar – Retina 的层。
-
展开名为Bar Button – Retina的层,并隐藏按钮标签层。
-
使用矩形选框工具选择右上角按钮周围的区域。它应该看起来像这样:
-
从编辑菜单中选择合并拷贝。
-
从文件菜单中选择新建,并确保背景内容属性设置为透明,接受你给出的尺寸。
-
粘贴内容,它将是一个完美的匹配,你将看到该按钮的空闲状态。
-
从文件菜单中选择另存为网页和设备…。
-
在保存对话框中,选择24 位 PNG并确保透明度框被勾选。使用合适的名称保存 PNG,例如
bluebuttonup.png
。 -
返回主文档并打开 Visible = Active 层。
-
再次执行合并拷贝 | 新建 | 粘贴 | 另存为网页和设备…。
-
将 PNG 保存为
bluebuttondown.png
。 -
返回 LiveCode。
-
重新打开测试床堆栈。
-
使用文件,导入为控件,和图像文件…将两个 PNG 文件导入堆栈。
-
你可以将这两张图片放置在任何位置。在每个图片的基本属性中取消勾选可见。
-
在第一张卡片上添加一个新的按钮,并将其命名为位置。
-
设置按钮脚本为:
on mouseUp iphoneStartTrackingLocation put iphoneCurrentLocation() into theLocation answer theLocation["latitude"] end mouseUp
-
选择位置按钮,并在检查器调板的基本属性中关闭显示名称和不透明。
-
在图标与边框中,关闭三维效果、边框和高亮边框。
-
点击检查器调色板中图标条目旁边的魔法棒按钮。
-
从图像库下拉菜单中选择此堆栈。
-
点击两个蓝色图像中较亮的一个。
-
点击高亮图标条目旁边的魔法棒按钮,然后点击两个图像中较暗的一个。
-
调整按钮的大小,使其刚好足够显示蓝色图像而不会被裁剪。
-
在按钮上方放置一个标签字段。
-
在基本属性中,勾选禁用框。这是为了确保字段不会捕获你将要执行的点击。我们希望按钮能够获得那个点击。
-
在内容中输入
Location
。 -
在文本格式化下,将字段设置为使用Helvetica Neue,18 点,粗体,居中对齐。
-
在颜色与调色板下,设置文字颜色为白色。
-
将字段和按钮对齐,使两者相互居中。
-
如果你现在使用 iOS 模拟器进行测试并点击位置按钮,你将只看到一个零,但在设备上尝试应该会在你触摸按钮时显示你的纬度(你将不得不在第一次按下按钮时允许应用程序知道你的位置。)
备注
注意,示例是 iOS 6 格式。iOS 8 可以在以下位置找到:
www.teehanlax.com/tools/iphone/
刚才发生了什么?
尽管我们制作的按钮可能不是完美的尺寸,甚至可能不符合独立 iOS 按钮的正确外观,但我们确实完成了制作按钮状态图像所需的所有步骤。在图像按钮上放置 LiveCode 字段并不一定能够给出最佳的外观。实际上,你会在 Photoshop 中花费更多的时间来制作适合你使用的标签的正确宽度的按钮,并且可能还需要将文本添加到图像本身。这将看起来更好,并且不需要字段在 LiveCode 中显示按钮的名称。
LiveCode 能够通过设置图形的点及其fillGradient
来使用代码创建我们需要的图像。然而,一旦你有了模拟按钮或其他类型控件所需的组件,仍然需要更多的脚本才能管理这些元素。
有一个简单的解决方案,尽管这会花费你 50 美元!
快速问答——现在的物价
Q1. 随着你对数码照片大小的期望增加,你今天也期望得到更多的价值。当你权衡花费 50 美元的利弊时,你认为与 25 年前相比,电脑的内存现在价值提高了多少?
-
10 倍的效果
-
一半的效果
-
100 倍的效果
-
20,000 倍!
答案:4
的确如此。25 年前,苹果公司以大约 1,500 美元的价格出售 Macintosh II 的 4MB 附加套件。现在他们以 1,200 美元的价格出售 Mac Pro 的 64GB 附加套件。
MobGUI 来拯救!
RunRev 总部位于苏格兰爱丁堡,他们是一群有才华的人!然而,他们并不是唯一有才华的苏格兰人,还有约翰·克雷格。他为 LiveCode 开发了一个强大的附加组件,其中包括一个越来越长的类似 iOS 和 Android 操作系统的控件列表。如果你要购买他的产品,你需要支付 50 美元,你将获得当前版本以及在你购买日期后 12 个月内发布的任何更新。虽然我们在这里查看它,我们也可以使用产品的试用版。
行动时间 - 开始使用 MobGUI
与 LiveCode 的其他附加组件一样,MobGUI 需要安装到 LiveCode 插件文件夹中。在 Windows 上,这将是在 My Documents/My LiveCode/Plugins
。在 Mac 上,这将是在 ~/Documents/My LiveCode/Plugins
。此默认位置可以在 LC Preferences 菜单和 Files & Memory 下进行更改。以下步骤将指导你开始使用 MobGUI:
-
从
mobgui.com/download.php
下载 MobGUI 的最新版本。 -
.zip
文件将展开成为一个名为 MobGUI_V1-28.livecode 的 LiveCode 堆栈,用于当前版本。希望当你下载时,会有更新的版本。 -
将堆栈拖入插件文件夹,并重新打开 LiveCode。
-
创建一个新的 Mainstack。
-
从 Development 菜单中选择 Plugins/revMobGUI。当你这样做时,会出现以下窗口:
-
MobGUI 窗口类似于 LiveCode 工具调色板和检查器调色板的组合。
-
尝试将不同的项目拖放到卡片上,并查看每个项目的选项。
-
左侧的列表是可滚动的,并显示额外的控件。
-
一旦控件放置在卡片上,它们就可以像正常的 LiveCode 控件一样进行操作。
-
上右角的选项字段允许选择不同的主题。选择 android 主题,然后点击 Apply。请注意,你拖出的控件会发生变化。在撰写本书时,android 主题代表较老的预 Lollipop 主题。
-
在你操作完堆栈后,你可以导出当前主题以供以后使用。你需要保存新创建的名为 MobGUI Theme 的堆栈。稍后打开时,此堆栈将有一个 Import 按钮。
刚才发生了什么?
LiveCode 的一个显著特点是,你在这个程序中使用的许多窗口和调色板实际上都是堆栈,我们已经开始使用一个相当专业的堆栈,这将为我们节省大量时间,并给我们一个像特定操作系统界面一样的好界面。
以 MobGUI 方式制作的测试床应用程序
我们将制作一个类似的测试床应用程序,但这次,我们将尝试给应用程序一个更类似 iOS 的外观。
行动时间 - 使用 MobGUI 制作测试床应用程序
当你在 LiveCode 中工作时,开始新的堆栈,关闭其他堆栈,以及打开之前保存的堆栈,这些操作仍然会占用内存。有时,你可能会陷入困惑的状态,只创建了一个新的未命名堆栈,却发现还有一个正在进行的未命名堆栈,这时你会被询问是否要清除。所以,为什么不给自己一个退出并重新启动 LiveCode 的机会呢!以下步骤将帮助您实现这一点:
-
创建一个新的主堆栈。将名称设置为
MGTestBed
,并将其保存在您容易找到的地方。也许在包含LCTestBed
堆栈的文件夹中,它感觉有点孤单! -
通过选择 Development/Plugins/revMobGUI 打开 MobGUI 窗口。
-
在 MobGUI 窗口的控件页面上,选择滑块调整大小复选框,并将滑块移动以选择320x480的大小。这是原始 iPhone 的大小。注意其他可用的大小。卡片也可以使用 LiveCode 检查器进行调整。
-
在 MobGUI 窗口中,选择IDE 中的 MobGUI 右键菜单选项。这将使您能够在以后编辑 MobGUI 控件行为。
-
使用卡片检查器,将此第一个卡片的名称设置为 Email。
-
将 TabBar 拖动到卡片窗口中。单击卡片窗口的底部对齐。它也会调整卡片宽度。
-
在 MobGUI 窗口中,将按钮拖动到卡片窗口顶部的 TabBar 上。通过按住 Alt/option 键并拖动来复制按钮 3 次。使用 LiveCode 的检查器调色板中的对齐工具对四个按钮进行对齐,并将它们分布在整个卡片上。
-
选择每个按钮,并将它们的名称和标签设置为
Email
、Browser
、DatePicker
和Picture
。然后调整按钮的大小,使它们适合其名称文本。 -
选择Email按钮,并从对象菜单中选择对象脚本或右键单击按钮并选择编辑脚本选项。脚本将看起来像以下截图:
-
向每个卡片添加以下
mouseUp
处理程序on mouseUp go card the short name of me end mouseUp
-
您可以将第一个按钮的
mouseUp
脚本复制并粘贴到其他三个按钮中。注意,MobGUI 在每个按钮的mouseUp
脚本之后创建了一个 preOpenControl 处理程序。不要更改它! -
我们需要在将要制作的四个卡片上使用这些元素,所以选择全选选项,然后从对象菜单中选择选择组。
-
确保组已选择并位于常规 LiveCode 检查器调色板中,然后勾选作为后台运行复选框。
-
创建另外三个卡片,并将它们的名称分别命名为
Browser
、DatePicker
和Picture
。 -
从 LiveCode 调色板中,为每个卡片拖动一个标签控件到卡片窗口中,并将名称设置为与卡片名称匹配。
-
在独立应用程序设置中,根据你想要测试的设备选择 iOS 或 Android。
-
将内部应用程序 ID或标识符设置为
com.yourname.MGTestBed
。 -
如果你正在 iOS 上执行相同的操作,请确保从“配置文件”下拉菜单中选择一个配置文件。
-
你现在可以从开发菜单进行测试,但首先你必须选择iPhone 模拟器或你的连接的 Android 设备。
刚才发生了什么?
看起来有很多步骤,但实际上并不需要花费太多时间。我们已经有四个卡片之间的导航和一个真实的 iOS 界面。
让我们以更原生、更集成的方式开始一些测试功能。
MobGUI 原生控件
MobGUI 的一个强大功能是它可以使用普通的 LiveCode 控件作为当你将应用运行在设备上时将成为本地控件的占位符。这不是你不能自己用代码做到的事情,但能够移动占位符控件,直到你满意布局,可以节省很多时间。
行动时间 - 使用 MobGUI 的本地控件
MobGUI 允许你在 iOS 和 Android 的原生控件主题之间切换,或者重新定义你自己的主题。
-
在 MobGUI 窗口中右键点击 iPhone 的小图标,确保你处于原生 iOS 控件集。
-
前往“电子邮件”卡片,从 MobGUI 窗口拖动 3 个输入文本控件和一个多行文本控件。
-
将输入控件命名为
To
、CC
和Subject
,将多行文本控件命名为Body
。你还可以在输入字段旁边添加一些常规 LiveCode 标签字段,作为输入指示。将 Body 字段设置得足够大,以便输入几行文本。此外,给字段或卡片添加一些背景颜色,以便正确显示字段。 -
在创建每个字段时,请注意,你可以设置键盘类型。将 To 和 CC 字段设置为电子邮件。
-
从 iOS 控件 1 集中,将两个按钮拖到卡片窗口。将一个命名为
完成
,另一个命名为发送
。完成此步骤后,你应该有一个这样的截图: -
当我们测试应用并触摸其中一个字段时,键盘覆盖层会出现。我们将使用“完成”按钮来隐藏键盘。向“完成”按钮脚本的
mouseUp
处理程序添加一个焦点线:on mouseUp focus on nothing end mouseUp
-
MobGUI 可以使用
mgText
属性从这些原生字段检索属性。将发送按钮的mouseUp
处理程序更改为使用此属性为每个字段,并调用revMail
函数:on mouseUp put the mgText of group "To"" into totext put the mgText of group "CC"" into cctext put the mgText of group "Subject"" into subjecttext put the mgText of group "Body"" into bodytext revMail totext,cctext,subjecttext,bodytext end mouseUp
-
前往浏览器卡片。
-
从 MobGUI 窗口,将一个输入控件拖到卡片窗口,并将其命名为
URL
。 -
将一个浏览器控件拖到卡片窗口,并将其命名为
Page
。 -
调整大小,使文本字段填满卡片宽度,浏览器控件填满文本字段和底部标签栏之间的区域。
-
选择 浏览器 控件,并在 MobGUI 窗口中输入 URL 的值或使用默认值。这将使浏览器控件将其作为第一个页面加载此 URL。
-
编辑 URL 文本字段的脚本,并添加此处理程序,该处理程序查找回车键以转到 URL:
on inputReturnKey mobileControlSet "Page",", "url", the mgText of me end inputReturnKey
-
尝试另一个测试,并转到“电子邮件”和“浏览器”卡片,看看它们在实际中的应用。
发生了什么?
我们重新创建了早期测试床应用程序中的前两个测试,但现在看起来好多了!此外,我们还利用了 MobGUI 在原生 iOS 控件中获取和设置数据的能力,在这种情况下,使用 mgText
属性和 mobileControlSet
。
注意,所有 MobGUI 控件在 LiveCode 检查器中显示为 组,在项目浏览器中显示为 自定义控件。这些组由自定义 LiveCode 控件(如按钮、字段等)组成。MobGUI 还会在您的堆栈末尾添加一个 MobGUI 卡片。此卡片包括具有定义行为的不可见按钮。行为是创建对象之间常见功能的方法,而不重复脚本。您可以通过在项目浏览器中显示 MobGUI 卡片时点击右侧的脚本按钮来查看这些行为脚本。除非您有特定的需求要更改这些,否则请保持它们不变。
英雄尝试 - 其他测试和漂亮的图标
按照本章前面“行动时间”部分中所述的方式,将其他两个测试添加到堆栈中。对于 DatePicker
示例,您可以检查 字典 中的 iPhonePickDate
定义,以查看如何使用选择日期数据的方式,例如,根据不同屏幕大小进行调整。
到目前为止,我们已使用纵向方向和仅 iPhone 测试了大小。您可能希望使用相同的堆栈用于 iPhone 和 iPad,或者可能是 iPad 和 Android 平板,它们的纵横比相当不同。
即使您只是坚持使用 iPhone,您也仍然需要考虑纵向和横向。因此,我们必须找到方法来安排卡片上的许多控件,以便它们在每个屏幕尺寸和方向上看起来都最好。
有几种方法可以实现这一点。首先,我们将看看如何使用调整大小处理程序。
使用调整大小处理程序进行布局
当堆栈的窗口大小改变时,LiveCode 会发送一个 resizeStack
消息,我们可以捕获它以重新排列控件以适应新的宽度和高度。
行动时间 - 简单的代码布局示例
如果您使用代码来布局卡片的全部控件,可能会变得相当复杂,所以我们只构建一个简单的案例来展示技术。您可以在以后为更复杂的情况进行增强。
-
创建一个新的主堆栈。
-
在卡片宽度上添加四个按钮。
-
将此处理程序放入卡片脚本中:
on resizeStack newWidth,newHeight put the width of button 1 into buttonWidth put (newWidth - 4 * buttonWidth)/5 into gap put the top of button 1 into buttonTop repeat with a = 1 to 4 set the top of button a to buttonTop set the left of button a to gap + (a-1) * (gap+buttonWidth) end repeat pass resizeStack end resizeStack
-
调整卡片窗口的大小。按钮应该在卡片上均匀分布。
-
前往 独立应用程序设置 并选择 iOS 选项。
-
确保支持的设备包括 iPad。
-
将方向选项设置为包括所有四种方向。
-
从开发菜单中,将测试目标设置为iPad 模拟器并执行测试。
-
在模拟器中,从硬件菜单中选择向左旋转或向右旋转。
-
按钮应该在纵向和横向两种方向上均匀分布在屏幕上。
发生了什么?
除了展示如何处理resizeStack
处理器的简单示例外,我们还看到方向的变化也会发送resizeStack
消息。
使用 LiveCode 几何管理器进行布局
当在卡片上选择一个控件时,检查器面板中有一个名为几何的条目。这是一个有些奇怪的界面!让我们看看:
这些微弱的水平和垂直条用于选择您是否希望控件通过固定量或相对量进行缩放或定位。也就是说,如果一个按钮距离卡片窗口的右侧 100 像素,并且您选择从固定量进行定位,那么当您调整卡片窗口大小时,按钮将保持在窗口右侧 100 像素的位置。另一方面,如果您使用相对设置,并且按钮占据卡片窗口的 80%,那么在调整大小后,它仍然占据窗口的 80%。
在这些条中点击第一个会使它变成实心红色,这表示它距离卡片边缘的固定量。如果您再次点击它,它将呈现红色波形形状,表示它将是相对的。
在截图中,您可以看到选定的按钮设置为从卡片底部固定量,从卡片右侧相对量。图像还显示了控件的缩放设置。
注意,一个对象也可以相对于其他对象进行定位。参考前面截图中的右侧对象和底部对象弹出选择器。
行动时间 - 使用几何管理器定位按钮
我们将向当前正在工作的堆栈中添加一些按钮:
-
取出前四个按钮并复制它们以获得另一组四个按钮,位于前面的按钮下方。
-
选择新按钮中的第一个,并在检查器面板的几何部分中,点击一次垂直条和两次水平条;您将得到前面截图中显示的状态。
-
对其他三个按钮也进行相同的操作。
-
尝试调整卡片窗口的大小。
发生了什么?
这是一次相当快的测试,如果一切顺利,你会发现调整卡片窗口大小包括使用我们添加的resizeStack
处理程序定位前四个按钮,以及使用几何管理器定位第二组四个按钮。使用我们使用的设置,结果应该非常相似,只是第二组四个按钮将保持与卡片窗口底部的固定距离。
几何管理器有很多功能,你应该查看本章末尾所示参考链接中的其他能力。然而,它并不是处理移动屏幕尺寸的最佳方式。
分辨率独立性
LiveCode 6.5,以及更远…
在第一章中列出的功能之一,LiveCode 基础知识,已经被开发出来,并存在于 LiveCode 6.5 中。新功能是分辨率独立性。
现在,在看到调整屏幕大小的两种复杂方法之后,你可能能够忘记所有这些。在 LiveCode 6.5 中,引入了一个名为“分辨率独立性”的新功能,正确使用此功能将使许多布局困难消失。
目前,为了帮助您处理不同的设备尺寸和纵横比,有两种方法可供选择:多密度支持和全屏缩放模式。其中一些概念有点棘手,但一些截图可能会希望使它们变得清晰!
多密度支持
到目前为止,在本章中,我们忽略了设备DPI(每英寸点数)的问题。对于 Android 设备,有数百种不同的分辨率和 DPI 值。对于 iOS,只有几种 DPI 和分辨率的变体。最简单的问题案例是,你希望同一个应用在 iPhone 3GS 和 iPhone 4 Retina 或更晚的 iPhone 版本上看起来和工作方式相同。它们都有相同大小的屏幕,但 iPhone 4 的视网膜显示屏的 DPI 是两倍。这个 URL 显示了所有当前 iPhone 之间的差异:www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
。
使用 MobGUI 和几何管理器解决方案,你实际上是在幕后存储布局值或指令,这些值或指令准备适应用户的设备屏幕大小。LiveCode 6.5 中的多密度支持是解决此问题的更简单方法。
像素和点
像素是图像或屏幕上的发光点,而点是在印刷中的度量单位,通常为 1/72 英寸。如果一个屏幕的 DPI 正好是 72,那么这两个就是相同的,在 Macintosh 计算机的早期日子里,这几乎是事实。更现代的 Mac 和 PC 以及大多数移动设备都比 72 DPI 详细得多。在 LiveCode 6.5 及其后续版本中,您现在可以创建一个以点为单位工作的堆栈,然后通过将每个卡片上的图像和缩放因子应用到它来填充设备屏幕。
在进行此类缩放时,必须假设某些内容为自然尺寸。对于 iOS,LiveCode 使用非 Retina 屏幕作为 1X 缩放因子,而 Retina 屏幕的缩放因子为 2X。iPhone 5 和 6 引入了更多尺寸。iPhone 6 Plus 需要 3X 缩放因子。对于 Android,事情更为复杂,因为它至少有七个缩放因子级别。
实际上,幕后正在进行无限多的缩放因子。然而,您通常不必担心它们,因为 LiveCode 自动为您提供根据所讨论设备的 DPI 显示不同图像版本的能力。
图像命名约定
LiveCode 将检查包含的图像文件名(在独立应用程序设置对话框的复制文件部分中添加的),并将加载相应命名的图像版本。在此示例中,已添加了两个图像,icon.png
和icon@2x.png
。为了更容易地识别您看到的是哪一个,512 和 1024 已添加到本应相同的图标两个分辨率:
此图像略有放大,以帮助您看到 512 版本的图像分辨率低于 1024 版本。
iOS 使用的名称是:
-
imagename.ext
(例如,flowers.png
) -
imagename@2x.ext
(例如,flowers@2x.png
) -
imagename@3x.ext
(例如,flowers@3x.png
)用于 iPhone 6 Plus
第一个被认为是 1X 缩放版本,而@2x
名称被认为是 2X 缩放版本,@3x
版本也是如此。
注意
注意,您还需要在 LiveCode独立应用程序设置中指定适当的启动屏幕文件。否则,iPhone 将使用较低分辨率的图像。这可以通过检查设备的screenRect
来验证。尽管 iPhone 6 Plus 的物理分辨率为 1080 x 1920,但应使用 1242 x 2208 的 3x 图像尺寸。手机会自动调整图像大小。2x 图像在 iPhone 6 上显示良好。
Android 使用的名称和缩放因子更为多样:
-
imagename@ultra-low.ext - 0.25X
-
imagename extra-low.ext - 0.5X
-
imagename low.ext - 0.75
-
imagename medium.ext - 1X
-
imagename high.ext - 1.5X
-
imagename@extra-high.ext - 2x
-
imagename@ultra-high.ext - 4x
在实际操作中,您可能会发现您只需要两三个版本的图像就能在广泛范围的 DPI 设备上使图像看起来足够好。
全屏缩放模式
在 LiveCode 6.5 及其多密度支持之前,您必须自己完成所有艰苦的工作!至少现在您可以为 iPhone 或 iPad 进行设计,并且 LiveCode 会负责这些设备的 Retina 版本。然而,对于 Android,您仍然需要拥有多种布局,或者有代码可以根据设备的宽高比和像素尺寸定位界面元素。
使用密度支持,您只需要注意宽高比,但仍有许多此类问题需要处理。对于类似工具的应用程序,您很可能会遇到这种麻烦,以便用户获得预期的体验。然而,有许多类型的应用程序更加图形化,可以利用全屏缩放模式:empty
、exactFit
、showAll
、noBorder
和noScale
。让我们看看这些是什么……
语法
顺便说一下,一般的语法是在您的堆栈脚本中输入以下内容:
on preopenstack
set the fullscreenmode of the current stack to "showAll"
end preopenstack
对于四个活动模式,需要使用引号。空模式不需要引号。
空模式
如果fullscreenmode是empty,则卡片区域将改变以匹配设备屏幕。也就是说,左上角的卡片位于设备屏幕的左上角,卡片的宽度和高度与设备的实际像素宽度和高度相匹配。嗯,除非您已经利用了前面讨论过的多密度支持!本质上,empty 是 LiveCode 早期版本中的现有行为。
showAll 模式
这种模式比其他模式稍晚出现,存在于 LiveCode 6.6 及其后续版本中。使用showAll,作为全屏模式,卡片的内容将被缩放,以便所有内容都显示在设备屏幕内。对于与您的卡片具有不同宽高比的设备,卡片区域外的元素将被显示出来。假设您创建了一个图形书应用,希望卡片的全部高度正好填满设备屏幕的高度,但您不希望在较宽的设备上出现黑色边框,那么您可以将背景图案扩展到卡片区域的左右两侧。在较窄的设备上,例如 iPad,您将看到 4:3 的卡片区域。在较宽的设备上,例如 iPhone 5,将显示额外的背景。以下插图显示了在不同设备上可以看到的背景图像区域:
信封模式
letterbox模式与showAll相同,除了卡片区域之外的区域被隐藏,并留下典型的电影信封效果,因此得名!
无边框模式
noBorder模式非常有用,但需要一些时间来适应。假设你正在制作一款图形冒险游戏,类似于 Myst,并且你希望所有设备都使用相同的图形。你可以创建一个宽高比为 14:9 的场景,并确保重要内容不要离边缘太近。当场景在 iPad 上的noBorder模式下查看时,你会看到场景的完整高度和大部分宽度。当在 iPhone 5 上查看时,你会看到场景的完整宽度和大部分高度。正如其名所示,卡片区域将被缩放,因此没有边框,就像信封模式中会有边框一样。以下插图显示了原始 14:9 照片的哪些区域对于 4:3 的 iPad 和 16:9 的 iPhone 是可见的:
exactFit模式
如其名所示,exactFit会将卡片内容挤压以填充设备的屏幕。很难想到这个模式的使用场景,但也许如果你执行某种艺术视觉化,挤压就不会很重要了!
注意
如前所述,几何管理器有很多强大的功能。如果你的兴趣也在桌面应用程序上,请查看以下课程:
lessons.runrev.com/s/lessons/m/4067/l/19026-Geometry-Manager
摘要
使用易于使用的工具,例如 LiveCode,的技巧是创建用户认为是用难以使用的原生工具,如 Xcode,制作的移动应用。你可以实现这一点,因为 LiveCode 能够调用原生功能,并且你可以制作看起来合适的界面。
在本章中,我们通过使用简单的 LiveCode 命令调用原生 OS 功能,介绍了实现这一目标的几种方法。我们准备了用于按钮状态的图像,并添加了这些图像来制作看起来具有 OS 特定风格的按钮。我们还使用 MobGUI 创建了看起来像 iOS 原生控件的控制,并使用代码和几何管理器布局了界面。
到目前为止,这些都是一些小测试堆栈,让我们热身!接下来,我们将查看通用应用程序结构,以制作一个完整的功能应用程序。
第四章:使用远程数据和媒体
在创建 LiveCode 应用程序时,我们需要考虑栈的结构、其代码以及它使用的数据。当所有支持数据都在应用程序内部时,可以创建应用程序,但很多时候,我们希望显示存在于现实世界中的数据,并且还想将信息(比如高分排行榜)保存到应用程序外部的文本文件中。你可能还想与他人共享信息或在不同应用程序或设备之间同步。
在本章中,我们将:
-
查看栈可能的结构方式
-
考虑代码应该放在哪里
-
写入和读取外部文本文件
-
创建一个类似剪贴簿的应用程序来记住有趣的基于互联网的媒体文件
小贴士
你想节省打字代码的时间吗?
本章有很多代码行。代码会与每个函数的解释一起展示,你可以使用这段代码构建与相应样本文件匹配的内容。然而,在转录脚本时,无论是脚本的内容还是脚本应该放置的位置,都很容易出错。可能更安全的方法是研究样本文件,并在这里阅读整体描述。你可以从 Packt Publishing 网站下载代码,网址为www.packtpub.com/books/content/support
。
栈结构
栈的结构有两个方面。一方面是关于用户界面元素的组织方式,另一方面是关于在栈的层次结构中你应该放置代码的位置。前者解决的是如何使应用程序易于理解、逻辑性强且易于使用。后者解决的是如何最小化开发时间、后续维护工作,以及如何最大化应用程序的性能。
代码驱动和手动创建的布局
当你想象一个典型的移动应用程序看起来像什么时,它可能大致是这样的:
有时,应用程序完全是代码驱动的,你看到的每个屏幕都是根据需要即时使用代码创建的。也许它已经布局了作为资源保存的元素,然后代码会加载这些资源。在任何情况下,整个应用程序都可以在一个 LiveCode 卡片上完成。
另一种方法是将每个可能的屏幕组合作为不同的卡片或甚至栈,并转到看起来像应用程序在那个时刻的样子。
在第一种情况下,你需要运行应用程序并执行用户操作,以检查布局是否正确。然后,你需要返回并更改代码或资源,然后再次尝试。在第二种情况下,你可能面临许多布局组合。
当我们开始在这里制作应用程序时,我们会尝试找到一个中间地带,在那里我们将使用卡片来设置我们需要的主体屏幕,然后我们将使用代码来显示和隐藏其他元素。我们的目标是尽量提高效率,不要编写复杂的代码来布局那些可以快速手动布局的项目。我们也不希望在代码可以取得相同结果的情况下使用大量图像。
代码位置
LiveCode 在如何构建你用它制作的事物方面非常灵活。除了可以包含代码的十几种不同类型的控件之外,你还可以控制前端脚本、组、当前卡片、主堆栈、正在使用的堆栈、后端脚本以及 LiveCode 本身。以下图表只显示了几个示例控件,但它给你了一个 LiveCode 层次结构有多少级别的概念:
你还可以有子堆栈,通常用于显示对话框窗口,添加前后脚本的能力,以及你可以将堆栈放入或移出使用。总的来说,可能会变得相当混乱!
这在很大程度上取决于个人风格,至于你将脚本放在哪里,通常你可能会有一个合理的理由来解释你为什么以某种方式做了。你可以争论说,所有发生的行为都应该在点击的按钮的脚本中。这将使得编辑所有涉及的处理器变得容易,如果你需要在另一个堆栈中具有相同的功能,你只需复制按钮即可。然而,如果你在屏幕上有许多这样的按钮并且需要做出更改,你必须对它们全部进行更改。
另一个有效的论点是可以说所有处理器都在堆栈级别。这样,你将有一个中央位置来做出更改,但你将不得不做出很多if
语句来检查哪个控件已被操作。
你可能希望重用你随着时间的推移开发出的例程,并会有一组你可以投入使用的堆栈,其中每个堆栈仅处理手头任务的特定方面。在面向对象编程(OOP)的世界里,将这种方法扩展到疯狂的程度是很常见的,有数百甚至数千个小文件,每个文件处理整体应用程序的一小部分。
我们不会走向这些极端。相反,我们将尝试将代码放在最低级别,这样它就不需要重复代码,正如你创建需要相同代码的额外控件时。在这个过程中,我们将尝试提前思考并发现我们可以使用的效率。让我们看看一个例子。
假设你有一个主菜单按钮,其功能是将用户带回到名为main
的卡片。将此作为按钮的脚本是有意义的:
on mouseUp
go card "main"
end mouseUp
这看起来像是代码可以到达的最低级别,我们不会重复它,因为只有一个主菜单按钮。然而,如果我们想跟踪用户的进度,主菜单按钮将对此一无所知。所以,我们可以这样做:
on mouseUp
navTo "main"
end mouseUp
在卡片脚本中,会有这个处理程序:
on navTo aCard
saveNavState
go card aCard
end navTo
saveNavState
函数会在某个地方保存用户的状态。唯一的问题是,对于我们所创建的每一张卡片,包括主菜单按钮,我们将在它们的脚本中都要有这个navTo
处理程序。因此,我们将处理程序放在主栈栈脚本中。由于它处于这个级别,它可以处理来自任何卡片上任何按钮的调用。帮助按钮的脚本可能是这样的:
on mouseUp
navTo "help"
end mouseUp
前往帮助卡片也会保存用户的状态。稍后,我们还可以添加一个视觉效果,当你从一个地方跳到另一个地方时,并在navTo
中而不是绕过使用navTo
处理程序的各个按钮中做出这种改变。
快速问答——命名这个结构
有一个常用的术语用来描述 LiveCode 的层次结构,有助于传达信息如何在层次结构中上下传递。这个术语叫什么?
-
事件视界
-
消息路径
-
调用栈
-
主栈
答案:2
对于进一步阅读,RunRev 有一个在线课程,描述了消息路径,你可以在以下位置找到:
lessons.runrev.com/s/lessons/m/4603/l/44036-the-livecode-message-path
加载和保存外部数据
在许多应用程序中,你可能想要跟踪用户所做的更改。LiveCode 有几种方法可以做到这一点,包括查询 URL、读取和写入文本文件以及保存堆栈内的数据。
查询 URL
很常见,基于 Web 的应用程序从服务器端脚本中加载和保存数据。这也适用于 LiveCode 应用程序。以下是一个示例,展示了昨天谷歌的收盘价:
put url "http://quote.yahoo.com/d/quotes.csv?s=GOOG&f=p"
在撰写本书时,这一行已经过测试,消息框中出现了609.46
,如下所示:
谁知道当你尝试时你会找到什么!实际上,在本书的第二版修订过程中,跳出的数字是 1172.9301。去谷歌搜索吧!
与任何此类对在线服务的调用一样,有可能需要一些时间才能返回值,在前面的例子中,LiveCode 在数据返回之前将无法执行其他任何操作。对于这种情况的一个替代方法是先加载 URL 以缓存它,然后在它被缓存后显示结果。在数据返回时,LiveCode 可以执行其他操作。按钮脚本可能看起来像这样:
on mouseUp
unload url "http://quote.yahoo.com/d/quotes.csv?s=GOOG&f=p"
load url "http://quote.yahoo.com/d/quotes.csv?s=GOOG&f=p" with message "gotit"
end mouseUp
on gotit addr, state
if state is "cached" or state is "downloaded" then
answer url addr
else
answer state
end if
end gotit
gotit
处理程序还会检查调用是否正常工作,如果没有,它将显示导致问题的错误。unload
行用于确保您没有读取之前缓存的值。如果这是一个只偶尔改变的价值,例如股票的收盘价,那么您通常只有在它可能改变时才清除缓存版本。对于这个例子,那可能就是第二天。
发布数据的工作方式相同。一个将您的分数发送到服务器的游戏可以这样操作:
on sendscore username,score
put url "http://www.mysite.com/hiscores/savescore.php?user=" & username & "&score=" & score into err
if err is not "ok" then answer err
end sendscore
如果username
或任何其他发布数据的部分包含空格字符,您应该首先在位置处使用URLEncode
。这样做会将空格和其他特殊字符转换为安全到达目标 URL 的代码。以下将是前面代码的一个更安全的变体:
on sendscore username,score
put "http://www.mysite.com/hiscores/savescore.php?user=" & username & "&score=" & score into tPostAddress
put url URLEncode(tPostAddress) into err
if err is not "ok" then answer err
end sendscore
读取和写入文本文件
在 HyperCard 的时代,保存和加载外部数据的唯一真正选择是编写一个文本文件。当然,LiveCode 也可以这样做,在某些情况下,这可能是最简单的解决方案。配置和首选项文件是几个很好的例子,其中一个小型文本文件可以用来以用户希望的方式设置应用程序。
例如,假设我们有一些配置文本文件名为englishstrings.txt
和frenchstrings.txt
,它们包含在独立应用程序设置对话框框的复制文件列表中,并且它们将被用来在您的应用程序中设置按钮的英文名称或法文名称。此外,我们还想编写一个首选项文件来记住用户的选择。当应用程序打开时,我们会检查首选项文件的内容,然后加载适当的字符串文件。
注意
在移动操作系统,尤其是 iOS 中,关于您允许保存数据的位置有严格的规则。随着我们向前发展,我们将使用苹果和谷歌批准用于此类用途的位置。
在移动应用程序中包含的文本文件将与应用程序本身位于同一位置,而您想要写入的文本文件应该位于应用程序的documents
文件夹中。因为这些路径在 iOS 和 Android 中看起来相当不同,我们应该使用 LiveCode 的specialFolderPath
函数来定位这些文件夹。以下是一个openStack
处理程序如何检查首选项是否已设置,如果没有,将用户带到初始语言选择屏幕的方法:
on openStack
global langstrings
put "file:" & specialFolderPath("documents") & "/prefs.txt" into prefsfile
put url prefsfile into prefstext
if prefstext is empty then
-- prefs have never been set, so go to the language choice card
go card "language choice"
else
-- language has previously been chosen, so we load up the right file
put "file:" & specialFolderPath("engine") & prefstext & "strings.txt" into langfile
put url langfile into langstrings
end if
end openStack
特殊引擎文件夹路径与应用程序文件以及您在独立应用程序设置对话框的复制文件部分中包含的支持文件位于同一位置(如第七章中的复制文件部分所述,将应用程序部署到您的设备),在保存独立应用程序时。在前面的例子中,会有名为englishstrings.txt
、frenchstrings.txt
、spanishstrings.txt
等文件。以下代码行将连接包含文件的路径、您希望使用的语言(存储在变量prefstext
中)以及这些文件名的结尾:
put "file:" & specialFolderPath("engine") & prefstext & "strings.txt" into langfile
这将为您提供与您选择的语言匹配的语言字符串文本文件的完整路径。
使用另一个堆栈存储数据
理想情况下,您只需保存您当时所在的堆栈中的更改即可,但 iOS 不允许您在应用程序目录中保存更改。我们必须通过在文档文件夹中保存堆栈来解决这个问题。要保存的堆栈可以是我们的应用程序堆栈,也可以是仅用于存储数据的堆栈。在堆栈中保存数据可能比在文本文件中保存更方便。例如,您可以有多个文本字段,用于存储下次运行应用程序时需要的信息片段。如果您使用文本文件,您可能需要很多个,或者您将不得不从单个文件中处理文本以提取个别信息片段。
您可以在不创建移动应用的情况下尝试在堆栈中保存数据,以检查基本技术是否可行。之后,您可以在实际设备上尝试相同的方法。首先在您的计算机上尝试此方法的优势是,您可以浏览到documents
文件夹,以便看到事情发生时的神奇效果!
行动时间 - 创建数据保存堆栈
我们将复制一个堆栈,但前提是那个堆栈没有其他副本。LiveCode 有一个很好的if there is a…
函数,它就是为了这种情况而设计的!
首先,我们将按照以下步骤创建所需的堆栈:
-
以名称
LaunchStack
开始一个新的主堆栈。将其保存在除您计算机的Documents
文件夹以外的其他位置。 -
以名称
AppStack
开始另一个新的主堆栈。将其保存在第一个堆栈相同的文件夹中。 -
在每个堆栈的卡片上放置一些数据,这样您就可以轻松地识别出您是否在该堆栈中。例如,将一个按钮拖放到
LaunchStack
堆栈的卡片上,并以一种使其非常容易识别的方式命名它。对AppStack
堆栈也做同样的操作。 -
将以下
openStack
处理程序放入LaunchStack
的堆栈脚本中:on openStack set the defaultFolder to specialFolderPath("Documents") if there is not a file "AppStack.livecode" then put the filename of this stack into masterfile set the itemdelimiter to "/" put "AppStack.livecode" into the last item of masterfile --put specialFolderPath("engine") & "/AppStack.livecode" into masterfile put specialFolderPath("Documents") & "/AppStack.livecode" into appfile put URL ("binfile:" & masterfile) into URL ("binfile:" & appfile) end if go stack specialFolderPath("Documents") & "/AppStack.livecode" answer the filename of this stack end openStack
-
保存堆栈并退出 LiveCode。
在尝试在设备或模拟器上尝试堆栈之前,我们将按照以下步骤将它们作为桌面堆栈尝试:
-
在你的
Documents
文件夹中查看;目前这个文件夹中不应该有AppStack.livecode
文件。 -
通过双击
LaunchStack.livecode
文件来启动 LiveCode。如果你发现 LiveCode 不能以这种方式启动,请确保你有与 LiveCode 关联的.livecode
文档。如果你使用多个 LiveCode 副本,比如说你正在尝试社区版和商业版,你可以将堆栈文件拖放到你打算使用的 LiveCode 副本上。 -
在你的
Documents
文件夹中查看;现在应该有一个创建时间与当前时间匹配的AppStack.livecode
文件。 -
你也应该看到,AppStack 的路径确实位于你的
Documents
文件夹中。
现在,按照以下步骤在移动设备或 iOS 模拟器上尝试我们的堆栈:
-
关闭 AppStack 堆栈,并取消注释步骤 4 中输入的
LaunchStack
堆栈脚本中的put specialFolderPath…
行。 -
前往独立应用程序设置并选择复制文件部分。
-
点击添加文件…并定位并添加原始的
AppStack.livecode
堆栈(不是之前测试中创建的那个)。 -
选择独立应用程序设置中的Android或iOS部分,并勾选复选框以使应用程序适用于该平台。
-
从开发菜单中选择你的测试目标。如果你选择 iOS,那将是 iOS 模拟器之一;如果你选择 Android,那将是连接的 Android 设备。
-
从开发菜单中选择测试。你现在应该能够查看 AppStack 以及显示堆栈路径的警告对话框。以下截图显示了 iOS 模拟器窗口和 Android 4 平板电脑上的结果对话框:
刚才发生了什么?
我们设置了应用程序以复制设备文档区域中的主应用程序堆栈,这样我们就能成功地进行更改并保存它们。如果你在 iOS 和 Android 上进行测试,你会看到堆栈的路径看起来相当不同。LiveCode 会为我们找到这些特殊文件夹。
快速问答 – 其他特殊位置
检查你是否偶然知道这个或使用这个问题作为借口去阅读发布说明和字典!以下哪个不是specialFolderPath
类型?
-
用户
-
主页
-
桌面
-
0x000e
答案:1
specialFolderPath
类型Home
和Desktop
在 Android 中不被使用,而Desktop
在 iOS 中也不被使用。0x000e
听起来可疑,但实际上是 Unix 下My Videos
的specialFolderPath
条目!系统中都没有Users
条目。
创建一个网络“抓取”应用程序
为了尝试各种原生移动控件,我们将制作一个可以读取网页并提取页面不同媒体链接的应用。该应用将包含一个显示网页浏览器的卡片、显示链接的卡片、网页文本和媒体以及一组用于记住所选项目的卡片。
动手实践 - 设置标签导航
在开始制作浏览器卡片的过程之前,我们需要设置应用中所有卡片共享的项目。以下步骤将帮助您完成此操作:
-
我们将再次使用 MobGUI 来简化操作。通过导航到开发 | 插件子菜单选择revMobGUI。此外,从 LiveCode 工具菜单打开项目浏览器以观察堆栈结构的发展。
-
创建一个新的 Mainstack,将其名称设置为
WebScraper
,并将其保存到某个位置。 -
在这些说明中,我们将使用纵向模式的 iPhone,但您也可以使用 iPad 或 Android 尺寸的卡片。您可以在 MobGUI 窗口中选择 iOS7 和 320x480,或者选择您喜欢的选项。
-
如同在第三章中“使用 MobGUI 记忆布局”部分所做的那样,使用 MobGUI 工具添加一个导航栏并点击卡片窗口的吸附到顶部,添加一个标签栏并点击卡片窗口的吸附到底部,以及两者的背景颜色。请注意,当将 MobGUI 控件添加到 Mainstack 时,项目会自动添加 MobGUI 卡片和行为控件。
-
将一个 LiveCode 字段控件拖到 NavBar 中并标记为
NavBar
。按您喜欢的格式进行格式化。 -
从 MobGUI 面板拖出一个 Button 控件并复制四次。选择所有五个按钮,并在 Inspector 中选择 Align Objects。将它们的顶部对齐并在卡片上分布它们。将五个按钮拖到您刚刚创建的标签栏上,并根据需要调整它们的大小和位置。
-
将五个按钮命名为
Browser
、Links
、Text
、Media
和Keepers
。通过在检查器调色板中设置标签条目来完成此操作。 -
编辑每个按钮的脚本,并在
mouseUp
处理程序中添加以下行,使处理程序看起来如下:on mouseUp put the short Name of me into tTabText set the Text of field "NavBar" to tTabText go card tTabText init end mouseUp
-
从编辑菜单中,选择选择全部 | 对象菜单中的 分组选择。
-
选择该组,在常规 LiveCode 对象检查器的基本设置菜单中,给该组命名为
Common
并勾选行为像背景按钮。 -
将卡片的名称设置为
Browser
。 -
创建一个新的卡片并将其命名为
Links
。请注意,分组按钮将出现在新卡片上。 -
对另外三个要命名的卡片
Text
、Media
和Keepers
也进行相同的操作。 -
前往独立应用程序设置,选择您想要尝试的平台iOS或Android,从开发菜单中选择适当的目标,并执行测试。
-
点击或触摸五个标签按钮,你应该会看到
NavBar
字段的名称已更改。
发生了什么?
通过将按钮和卡片命名为相同的名称,我们能够通过附加到组的脚本访问五个卡片。我们还使用了按钮脚本,将 NavBar 的名称设置为与我们跳转到的卡片名称相匹配。init
行将在我们编写卡片脚本时自动出现。
注意
不要在同一张卡片上使用相同类型的控件相同的名称。你的脚本可能会最终操作错误的控件。
浏览器卡片
现在,我们将向第一张卡片添加一些控件和脚本,以创建以下迷你网页浏览器:
原生浏览器控件具有许多与之相关的属性、动作和消息。你可以在以下网站上查看iOS 发布说明和Android 发布说明:
支持文档的额外更新可以在以下找到:
LiveCode 博客 - 6.1.2 带来 iOS 7 支持
尽管如此,对于我们这个应用来说,我们只需要 LiveCode 的少数几个功能。
是时候采取行动了——添加浏览器控件
返回堆栈的第一张卡片,找到 MobGUI 窗口中本机控件部分。以下步骤将引导你完成:
-
将浏览器控件拖拽到卡片窗口上。
-
调整控件大小以填充卡片宽度,并调整控件高度,使其介于标签栏和 NavBar 下方一点的位置。给它命名为
Page
。 -
在浏览器控件被选中时,确保 MobGUI 窗口中标题为自动删除的框被勾选。这将在你不在浏览器卡片上时帮助减少最终应用的内存使用。
-
从 MobGUI 窗口中,将一个输入控件拖拽到浏览器控件和 NavBar 之间的空隙中。将其命名为
url
,并调整大小,使其几乎与卡片一样宽,为右边的Go按钮留出空间。 -
将一个按钮控件拖拽到该空间,将其标签设置为
Go
,并调整大小以使其看起来更美观。 -
编辑Go按钮(你可能已经注意到,它实际上是一个组)的脚本,并在 mouseUp 处理程序中添加几行,如下所示:
on MouseUp mobileControlSet "Page", "url", the mgText of group "url" focus on nothing end mouseUp
-
之后,我们将向卡片发送一个
init
消息。对于浏览器卡片,我们可以使用这种方式来恢复之前选择的网页。在浏览器卡片脚本中添加以下内容:on init global gPageURL if gPageURL is not empty then set the pURL of group "Page" to gPageURL else set the pURL of group "Page" to "http://www.google.com/" end if end init
-
编辑浏览器(组
Page
)控件的脚本。我们将使用browserFinishedLoading
消息来知道何时更新一些变量和 URL 文本。 -
修改浏览器控制脚本中的此处理程序,如下所示:
on browserFinishedLoading pURL,pType global gPageURL,gPageHTML put pURL into gPageURL put url pURL into gPageHTML set the mgText of group "url" to pURL pass browserFinishedLoading end browserFinishedLoading
-
保存并执行另一个测试以查看浏览器卡片的效果。
刚刚发生了什么?
将浏览器控制的pURL
命令设置为mgText
就足以使浏览器正常工作,但刚刚所做的一些操作是为了准备我们在其他卡片中需要的内容。特别是,我们使用了常规的 LiveCode put url
命令将网页 HTML 代码的副本存储在一个全局变量中,当我们开始从页面中提取链接和媒体时,这将是有用的。
链接卡片
链接、文本和媒体卡片将使用存储在gPageHTML
全局变量中的页面源代码,并从中提取感兴趣的部分。它们将如何做到这一点呢?
在提取已知文本模式时,常用的方法是用正则表达式,通常被称为regex
或regexp
。在最简单的情况下,它很容易理解,但可能会变得相当复杂。
注意
如果你想深入了解正则表达式,请阅读维基百科上的文章:
en.wikipedia.org/wiki/Regular_expression
另一个有用的信息来源是 Packt Publishing 关于正则表达式的文章,您可以在www.packtpub.com/article/regular-expressions-python-26-text-processing
找到。
然而,使用正则表达式解析 HTML 内容是不被推荐的。网上有大量文章明确告诉你不要用正则表达式解析 HTML!这里有一个简短示例:
boingboing.net/2011/11/24/why-you-shouldnt-parse-html.html
.
现在,解析 HTML 源代码正是我们在这里想要做的事情,解决这个问题的方法之一是混合使用 LiveCode 的其他文本匹配和过滤能力来完成大部分工作。尽管这并不完全是正则表达式,但 LiveCode 可以在其匹配和过滤函数中使用正则表达式,并且它们比完整的正则表达式更容易理解。所以,让我们从使用这些功能开始。
在寻找链接时,我们将假设链接位于a href
标签内,但即使如此,它可能以很多不同的方式出现。href
标签的一般结构如下:
<a href="http://www.runrev.com/support/forum/">Link text that the user will see</a>
在网页文本中将会出现用户将看到的链接文本
。当鼠标指向它时,用户将看到指向的手指光标,当点击它时,页面将使用标签href
部分显示的 URL 重新加载。
上述示例显示了支持论坛的完整路径;以下是一些将完全相同的网络位置写入页面链接的方式:
http://www.runrev.com/support/forum/
/support/forum/
support/forum/
../support/forum/
第一个链接无论你在什么位置点击都会带你到那里。第二个链接如果你在runrev.com/
网站上其他地方点击,则会带你到那里。第三个链接在你位于runrev.com/
网站的根级别时是正确的,最后一个示例将从一个其他根级别目录在网站上工作。
使用正则表达式,你可能创建一个处理页面源代码中链接所有可能变体的复杂表达式,但即使如此,它也不会给我们需要的完整路径。
通过逐步处理,我们可以将整个页面源代码减少到一组“a href”条目,提取每行的 URL 部分,最后,将前面的变体转换为完整的路径 URL。
行动时间 - 创建一个链接提取函数
有时候,在单独的堆栈中创建测试然后将其中的函数应用到你的应用程序堆栈中是非常方便的。以下要点将帮助你创建一个链接提取函数:
-
创建一个新的主堆栈并保存它,以确保安全!
-
添加几个字段和一个按钮。
-
将按钮的脚本设置为以下内容:
on mouseUp put url "http://www.runrev.com/" into field 1 put getLinks(field 1) into field 2 end mouseUp
-
编辑堆栈脚本并创建一个
getLinks
函数。从返回它发送的内容开始:function getLinks pPageSource return pPageSource end getLinks
-
如果你现在尝试点击按钮,你会看到整个页面源代码出现在字段 2 中。
-
我们将使用过滤函数,并且它需要文本以单独的行存在。因此,我们希望每个链接都在一行中。
replace
函数可以很好地做到这一点。在“return”行之前添加这两行脚本:replace "/a>" with "/a>" & return in pPageSource replace "<a" with return & "<a" in pPageSource
-
现在尝试点击按钮。两个字段看起来几乎一样,但任何包含链接的行都将单独一行显示。
-
添加一行以过滤列表,使其只显示包含链接的行:
filter pPageSource with "*a href*/a>"
-
*
字符是通配符,它将列表减少到只包含同时具有a href
和/a>
的行。再次尝试按钮。 -
现在你将看到只有包含链接的行,但它们仍然包含链接本身的两侧的垃圾信息。我们需要的部分是在第一个和第二个引号之间,使用
itemdelimiter
我们可以获取这部分。添加以下行:set the itemdelimiter to quote repeat with a = 1 to the number of lines in pPageSource put item 2 of line a of pPageSource into line a of pPageSource end repeat
-
现在点击按钮,你应该得到一个只包含每行 URL 部分的列表。然而请注意,大多数链接以
/
开头而不是http
。 -
在堆栈脚本中再创建一个函数,用于将链接转换为完整路径:
function getPath pPageURL,pLinkURL end getPath
-
现在,添加处理 URL 变体的代码(到
getPath
函数),从它的完整路径开始:if pLinkURL contains "://" then return pLinkURL end if
-
如果你还记得之前的内容,我们已将主页面的 URL 保存在一个全局变量中,
gPageURL
。对于链接是根相对路径的情况(它以/
开头),我们想要组合主机位置和链接 URL:set the itemdelimiter to "/" if char 1 of pLinkURL is "/" then return item 1 to 3 of pPageURL & pLinkURL else
-
当第一个字符不是
/
时,它可能以../
开头,以在服务器结构中向上移动一级。删除页面 URL 的最后部分将给我们需要与链接 URL 组合的内容:if char 1 to 3 of pLinkURL is "../" then delete the last item of pPageURL delete the last item of pPageURL delete char 1 to 2 of pLinkURL return pPageURL & pLinkURL else For other cases we combine the page URL and the link URL: delete the last item of pPageURL return pPageURL & "/" & pLinkURL end if end if
-
最后,如果所有这些检查都失败了,我们将返回一个空字符串,这样这个奇怪的链接 URL 结构就不会在以后混淆我们:
return "" end getPath
-
要使
getLinks
函数使用getPath
函数,我们需要对步骤 9 中显示的脚本进行更改:repeat with a = 1 to the number of lines in pPageSource put getPath(gPageURL,item 2 of line a of pPageSource) into line a of pPageSource end repeat
发生了什么?
我们分阶段开发了一个函数,该函数可以在网页源文本中找到以一组完整路径 URL 结尾的链接,我们可以将这些链接呈现给用户。
缺失的链接
测试堆栈中缺失的一块是存储页面 URL 的全局变量。在应用堆栈的情况下,该值由浏览器控制的browserFinishedLoading
函数提供,但在这里,我们需要为测试目的插入一个值。
在按钮脚本和堆栈脚本中放置一个全局声明行。在按钮脚本中,用我们的测试用例值填写变量。脚本将如下所示:
global gPageURL
on mouseUp
put "http://www.runrev.com/" into gPageURL
put url gPageURL into field 1
put getLinks(field 1) into field 2
end mouseUp
现在尝试按钮,你应该能在第二个字段中看到完整的路径 URL 列表。如果它工作正常,复制两个堆栈函数和全局声明行,并将它们粘贴到 WebScraper 堆栈的堆栈脚本中。
还有一件事…
选项卡栏脚本包括一个初始化行。这将调用卡片脚本;在这种情况下,是链接卡片脚本,但它目前还不存在!让我们来创建它。
是时候添加链接卡片初始化处理程序了
在继续之前,请确保你对测试堆栈中的函数感到满意,并且已经使用以下步骤将它们复制到 WebScraper 堆栈脚本中:
-
前往 WebScraper 堆栈的链接卡片。
-
编辑卡片脚本并添加这些全局变量和
init
函数:global gPageHTML,gLinks on init if the platform is "iphone" or the platform is "android" then put getLinks(gPageHTML) into gLinks if the number of lines in gLinks = 0 then answer "There are no links in this page!" else mobilePick gLinks,0 if the result > 0 then put the result into tLinkLine put line tLinkLine of gLinks into tLink go card "Browser" set the mgText of group "url" to tLink set the Text of field "NavBar" to "Browser" mobileControlSet "Page", "url", the mgText of group "url" end if end if end if end init
-
对应用进行测试。
-
在 iPhone 模拟器或 Android 设备上(如果你使用的是这些设备),将 URL 更改为
www.runrev.com/
并选择前往按钮。 -
当页面加载时,选择链接选项卡按钮。
-
现在,你应该能看到来自 RunRev 页面的链接列表;但这次,它是以原生选择器列表的形式呈现的。
-
从列表中选择一个链接,然后完成。
-
你将被带回到带有加载的链接页面的浏览器卡片。
发生了什么?
我们输入的卡片脚本与测试堆栈中的按钮执行相同的任务;在那里,它调用堆栈函数以获取链接列表。在这里,我们不是将列表放入普通字段中,而是使用了 LiveCode 的能力,通过以下行打开原生选择器控件:
mobilePick gLinks,1
此函数所需的参数是要显示的项目列表和一个索引位置,该位置将被选中。通过输入1
,默认选中第一个项目。从选择器返回的结果是选中项目的索引,我们可以使用这个索引在gLinks
变量中查找匹配的行。
剩余的行将带我们回到浏览器卡片,设置要加载的 URL,并更改 NavBar 以反映卡片名称。
文本卡片
使文本卡片工作要简单得多,但包括一条难以置信的复杂正则表达式行,该行可以在以下位置找到:
动手时间 - 设置文本卡片
我们将从您制作的测试堆栈开始,这样我们就可以在将其添加到 WebScraper 堆栈之前在那里使函数工作。
-
复制你在提取链接时制作的按钮。将函数调用
getLinks
更改为getText
;其余的脚本可以保持不变。 -
编辑测试堆栈的脚本并添加此函数:
function getText pPageSource put replaceText(pPageSource,"(?:<(?P<tag>script|style)[\s\S]*?</(?P=tag)>)|(?:<!--[\s\S]*?-->)|(?:<[\s\S]*?>)","") into pPageSource replace lf with "" in pPageSource replace tab with " " in pPageSource return pPageSource end getText
-
尝试点击您刚刚制作的按钮。你应该看到您的第二个字段只填充了网页的文本部分。
-
复制函数并回到 WebScraper 堆栈脚本。将函数粘贴到那里。
-
前往堆栈的文本卡片,并从 MobGUI 窗口中,将多行文本控件拖到卡片上。将其名称设置为
PageText
。 -
调整控件大小以填充 NavBar 和 Tab-bar 之间的区域。如果文本无法填满字段,您可能需要使用 LiveCode 检查器来修改大小。
-
在控制器的 MobGUI 窗口属性中,取消勾选可编辑复选框。
-
编辑卡片脚本并添加此
init
函数:global gPageHTML on init if the platform is "iphone" or the platform is "android" then mobileControlSet "PageText","text",getText(gPageHTML) end if end init
-
尝试对应用进行测试。
-
在浏览器卡片中,将 URL 从
google.com/
更改为runrev.com/
并点击前往。 -
点击底部的文本标签按钮。
-
你现在应该处于文本卡片上,并且应该能够看到在原生滚动文本字段中显示的网页文本元素。
发生了什么?
这个非常长的正则表达式在网页源代码中运行,移除了任何脚本、样式或仅仅是标签信息,而文本部分则保持不变。然而,它会在文本中留下很多多余的换行符和制表符,我们继续使用 LiveCode 的replace
函数来移除它们。最终文本可能并不完美,但您可以使用标准的移动文本功能来复制文本的部分以在其他应用中使用。
媒体卡片
媒体卡片将非常类似于链接卡片,卡片脚本中有一个init
函数和一个堆栈脚本函数用于从页面中提取媒体链接。
动手时间 - 提取媒体链接列表
可能有一个正则表达式可以提取页面上的所有src
链接,但我们只对我们知道 LiveCode 能够显示或播放的内容感兴趣。因此,在这些步骤中,我们将使用更狡猾的方法来提取我们能够处理的链接:
-
你不妨去测试堆栈看看!
-
通过复制其他两个中的一个来创建第三个按钮,并在按钮脚本中将
getLinks
或getText
部分更改为调用getMedia
。 -
在堆栈脚本中输入所有这些:
global gPageURL function getMedia pPageSource put ".jpg,.png,.gif,.jpeg,.mov,.mp4,m4v,.mp3" into tExtensions repeat with a = 1 to the number of items in tExtensions put item a of tExtensions into tExtension replace tExtension with tExtension & "*" & return in pPageSource end repeat repeat with a = the number of lines in pPageSource down to 1 put line a of pPageSource into tLine if the last char of tLine is "*" then delete the last char of tLine put removeLeaders(gPageURL,tLine) into line a of pPageSource else delete line a of pPageSource end if end repeat return pPageSource end getMedia function removeLeaders pPageURL,pLinkURL put quote&"'()" into tDelimiters repeat with a = 1 to the number of chars in tDelimiters put char a of tDelimiters into tDelimiter set the itemdelimiter to tDelimiter put the last item of pLinkURL into pLinkURL end repeat return getPath(pPageURL,pLinkURL) end removeLeaders
-
点击按钮,你应该会看到网页中各种图片的完整路径列表。
刚才发生了什么?
这种狡猾的方法涉及找到感兴趣媒体被提及的任何地方,并添加一个星号和回车符,以确保链接容易被识别,并且位于独一无二的行尾。然后,将这些行中的每一行都发送到另一个函数removeLeaders
,以移除链接开始之前该行中的任何其他文本。最后,我们使用了在提取链接时使用的相同的getPath
函数,以提供媒体文件的完整路径。
现在我们有了媒体链接的列表,我们需要添加卡片级别的处理程序,以向用户展示列表并将他们选择的媒体项目加载到卡片窗口中。
行动时间 - 设置媒体卡片脚本
将你在测试堆栈脚本中证明可以工作的函数复制,粘贴到 WebScraper 堆栈脚本中。然后执行以下步骤:
-
前往媒体卡片。与链接卡片一样,我们不会向卡片添加任何控件,因为我们将通过脚本完成。所以,编辑卡片脚本。
-
这是媒体卡片的
init
函数和所需的全局变量:global gPageHTML,gMediaList on init if the platform is "iphone" or the platform is "android" then put getMedia(gPageHTML) into gMediaList if the number of lines in gMediaList = 0 then answer "There is no media in this page!" else set the itemdelimiter to "/" put empty into tMediaNames repeat with a = 1 to the number of lines in gMediaList put the last item of line a of gMediaList into line a of tMediaNames end repeat mobilePick tMediaNames,1 if the result > 0 then put the result into tMediaLine showMedia line tMediaLine of gMediaList end if end if end if end init
-
与链接的情况不同,我们建立了一个仅包含 URL 文件名部分的列表,将在本地选择器中显示,并且当我们选择某项内容时,将在堆栈脚本中调用
showMedia
函数。 -
编辑堆栈脚本。
-
创建
showMedia
函数:on showMedia pMediaFile if there is an image "mediaImage" then delete image "mediaImage" set the itemdelimiter to "." switch (the last item of pMediaFile) case "png" case "gif" case "jpg" case "jpeg" new image set the name of image the number of images to "mediaImage" set the filename of image "mediaImage" to pMediaFile break case "mp4" case "m4v" case "mov" case "mp3" set the showController of the templatePlayer to true play video pMediaFile break end switch end showMedia
-
测试应用。
-
你可以从 google.com 页面开始;点击媒体标签按钮查看该页面上使用的所有图片列表。
-
从列表中选择一个图片并点击完成。
-
图片应该出现在卡片上。
-
返回到浏览器卡片并将 URL 更改为
http://www.apple.com/
。 -
苹果通常在主页上包含一些视频链接缩略图。点击其中一个,以便看到大型的视频播放器。然而,不要播放它!
-
点击媒体标签按钮查看该页面上所有媒体的列表。
-
滚动列表并寻找一个名字较长的项目,看起来它肯定是一个视频。
-
选择该项并按完成。视频应该在卡片上加载并播放。
-
在观看完视频后,使用视频控制器的完成按钮返回到媒体卡片。
-
然后,你可以再次点击媒体标签按钮,使选择器重新出现。
-
返回到浏览器卡片,并输入包含 MP3 文件示例的 URL。
http://www.ntonyx.com/mp3_songs.htm
就是这样一个例子。 -
点击媒体标签按钮返回到包含该页面上所有媒体列表的媒体卡片,在这种情况下,主要是 MP3 文件。
-
从列表中选择一个 MP3 文件,然后点击 完成。MP3 应该在播放视频的相同播放器中播放。
发生了什么?
在这个示例中,我们使用了标准 LiveCode 控件,图像,以及原生控件,视频播放器。LiveCode 处理播放器的设置,并且使用非常简单的 "play video videoname" 语法,我们能够调用原生播放器。它能够播放视频和音频文件。
Keepers 卡
实际上,这应该是 Keepers 卡片。这些卡片是你可以存放找到的有趣媒体的地方。由于文件大小原因,我们实际上只是存储媒体的 URL;毕竟,一个长的视频很快就会耗尽你的设备存储空间!
行动时间 – 设置 Keepers 卡
-
前往 Keepers 卡并创建一个用于 Prev、Next 和 Play Media 的 MobGUI 按钮。创建一个 MobGUI 多行 字段并命名为
mediaURL
。确保取消选中 自动删除 选项,以便在更改卡片时保留 URL 数据。还要取消选中 可编辑 选项。你现在应该有一个类似于以下截图的内容: -
将以下行添加到 Prev 按钮的
mouseUp
处理程序中:if the number of this card is > 5 then go previous end if
-
将以下行添加到 Next 按钮的
mouseUp
处理程序中。注意,使用- 1
是因为最后一张卡片是 MobGUI 卡:if the number of this card < the number of cards - 1 then go next end if
-
将此行添加到 Play Media 按钮的
mouseUp
处理程序中:showMedia the mgText of group "mediaURL"
-
选择四个控件并将它们分组。勾选表示 像背景一样行为 的复选框。将组命名为
keeperbuttons
。 -
编辑新组的脚本。添加此
refresh
处理程序:on refresh set the itemdelimiter to "." if char 1 of the last item of the mgText of group "mediaURL" is "m" then show group "Play Media" else hide group "Play Media" showMedia the mgText of group "mediaURL" end if end refresh
-
我们需要回到并添加内容到 Media 卡。
-
前往 Media 卡并添加一个 MobGUI 按钮。设置名称和标签为
Keep Media
。 -
一个棘手的问题是,媒体将在小屏幕上全屏播放,并且在你看到 Keep Media 按钮的时候,视频已经消失了。我们可以通过在全局变量中存储最后显示的媒体的 URL 来解决这个问题。
-
在 Media 卡脚本中,更改
init
函数,以便后续行如下所示:if the result > 0 then put the result into tMediaLine put line tMediaLine of gMediaList into gLastMedia showMedia gLastMedia end if
-
将全局变量声明行修改为包含
gLastMedia
变量。 -
将 Keep Media 按钮的
mouseUp
处理程序设置为以下内容:on mouseUp global gLastMedia go card (the number of cards -1) if the mgText of group "mediaURL" is not empty then new card end if set the mgText of group "mediaURL" to gLastMedia save stack "WebScaper" as (specialFolderPath("documents") & "/WebScraper.livecode") send "refresh" to group "keeperButtons" end mouseUp
-
现在,堆栈保存媒体只需要最后一步。我们需要创建一个类似于本章前面所做的那样启动应用程序。创建一个名为
LaunchScraper
的堆栈,其堆栈脚本如下:on openStack set the defaultFolder to specialFolderPath("Documents") if there is not a file "WebScraper.livecode" then put the filename of this stack into masterfile set the itemdelimiter to "/" put "WebScraper.livecode" into the last item of masterfile put specialFolderPath("engine") & "/WebScraper.livecode" into masterfile put specialFolderPath("Documents") & "/WebScraper.livecode" into appfile put URL ("binfile:" & masterfile) into URL ("binfile:" & appfile) end if go stack specialFolderPath("Documents") & "/WebScraper.livecode" answer the filename of this stack end openStack
-
确保 Launch Scraper 和 Web Scraper 应用程序位于同一文件夹中。只打开 Launch Scraper 应用程序,并确保 Web Scraper 应用程序包含在 独立应用程序设置 的 复制文件 中。
-
选择你的 测试目标 设备,然后 测试。注意,最后一个答案语句将显示主应用存储在你设备上的路径和文件名。一旦你确信它正在正常工作,可以将其注释掉。
-
使用浏览器卡片加载一个包含大量图片、视频或声音的页面,然后转到媒体卡片查看这些列表。
-
选择任何项目,然后点击完成。
-
如果你喜欢图片、声音或视频,使用保留媒体按钮将媒体推到堆栈的底部以保存媒体 URL。
-
选择更多媒体片段并保留它们。
-
前往保留者部分,并使用下一页和上一页按钮浏览你保留的项目。
-
图片应自动显示,视频和音频可以通过播放媒体按钮开始播放。
刚才发生了什么?
我们添加了我们应用程序的最后一个功能,一组卡片,我们可以通过它们查看我们选择保留的媒体片段。
尝试一下英雄般的操作——添加一些预设位置
如果你真的制作了 Web Scraper 应用并开始觉得它有用,很可能会有一些网页你希望反复访问。每次都输入 URL 会很麻烦。所以,为什么不在浏览器卡片上创建一个隐藏字段并输入你喜欢的网页列表。在卡片上添加一个按钮,这样你就可以选择这些页面。你选择的页面可以加载到所需的浏览器控件。所有完成这些步骤的步骤都在链接卡片部分中进行了介绍。
很可能,如果你仔细遵循了本章的所有步骤,并且确实所有步骤都完美无缺,你仍然不会有一个可以提交到应用商店的应用程序!你需要一个启动画面、主菜单、标签按钮上的图标,以及图形设计师的一些创意!从功能上讲,如果保留的图片可以缩放和平移会很好。
摘要
在这里我们讨论的一些主题可能不那么引人注目,主要是关于处理 HTML 文本的,但我们也使用了一些移动功能。我们展示了原生应用如何存储数据以供后续使用,以及如何创建和控制网页浏览器。我们还涵盖了使用原生选择器来展示列表的方法。我们还创建了一个具有所有正常操作系统特定功能的原生滚动字段,并使用原生媒体播放器播放视频和音频。
下一章几乎完全关于处理图形,所以我们会确保使用一些图像处理手势,并且你可以稍后重新访问 Web Scraper 应用,为 Keepers 卡片添加相同的特性。
第五章。制作拼图应用
想象一下…
到目前为止,我们一直在处理大量文本或调用移动操作系统功能。这些事情很整洁,但它们并不那么直观。如果你渴望玩弄图片和图像数据,你的时机到了!
LiveCode 并非天生的图形 powerhouse,它处理图像数据(其他工具通常称为“位图数据”)的方式有些不寻常。它有效地将图像的像素存储为一系列单字节字符,以表示每个像素的红色、绿色和蓝色值。处理最终图像相当灵活,但为了创建类似拼图的东西,我们需要了解 LiveCode 属性 imageData
的格式。
在本章中,我们将:
-
检查 LiveCode 在图像对象中存储位图数据的方式
-
找一种方法使用单个位图代替 50 个按钮
-
制作一个碰撞检测图
-
创建一个利用多个移动设备功能的拼图应用
图像数据格式
在其他作者工具中,例如 Adobe Director 和 Adobe Flash,位图数据以 24 位或 32 位的值矩阵形式存储。如果你想知道图像顶部第 15 行从左侧数第 20 个像素的颜色,你将不得不使用一个 getPixel
函数并填入这些数字。在 Flash 中,它为所有变量类型使用零起始点,你必须编写以下代码:
pixelcolor = bitmapvariable.getPixel(19,14);
实际上,你必须以 var pixelcolor:uint
开始这一行,但在这里我们关注的是主要差异,而不是强类型编程语言的怪癖!在 Director 中,它像 LiveCode 一样使用基于 1 的变量,你必须编写以下代码:
pixelcolor = imagevariable.getPixel(20,15)
同样,没有必要进行变量类型定义,甚至行尾也不需要分号。当我们分心时,Flash 也不需要行尾的分号,或者至少,你不必自己输入它。Flash 知道你的意图!回到正题…
在 LiveCode 中,图像的每个像素由四个字节表示,你可以像访问单字节字符一样访问它们。字节的值范围是 0-255,并且存储这些值,特别是值 0
,在字符变量中效果不佳。因此,在利用它之前,你必须将字符值转换为数值。基本问题是,尽管数值存储在变量中,但当你开始对其执行计算时,LiveCode 希望使用十进制算术而不是变量内的二进制形式。你必须将变量转换为可以使用 charToNum
函数处理的东西。
注意
那么,为什么字符变量不喜欢零呢?好吧,在个人电脑的早期阶段,主要的编程语言是 Pascal。在 Pascal 中,包含字面字符串的变量需要一种方式来知道字符串的长度。Pascal 字符串的第一个字节存储字符串的长度,这对于 255 个字符来说是足够的,而且在当时,人们可能认为这已经足够了,而且比任何人需要的都多!然而,在现实生活中,字符串可以比 255 个字符长。这个段落本身就有超过 900 个字符长。为了解决这个问题,C 编程语言使用零来表示C 字符串的结尾。你可以有一行一百万个字符;然而,只有最后一个字符是零。RGB 值不关心 C 字符串的限制,到处都是零,这就是为什么我们尽可能快地将它转换为数值值。
除了每个像素以四个字节的信息存储的奇特之处外,也没有办法指定行和列。图像中的所有像素的四个字节都是连续存储的;你必须进行计算才能知道你正在寻找的像素在数据中的位置。如果你之前使用过位图编辑器,比如 Photoshop 或 Gimp,你肯定知道你选择内容是基于一个对应的X和Y坐标值,这个坐标值对应于像素所在的列和行。LiveCode 不让你以这种方式访问位图。因此,我们需要进行计算。
在 LiveCode 中,如果你想将前一个示例中的像素值作为 24 位值检索,可以这样操作:
put getPixel(""test image"",20,15) into pixelcolor
function getPixel pImage,pX,pY
put the imageData of image pImage into tImageData
put the width of image pImage into tWidth
put ((pY-1)*tWidth + (pX-1)) * 4 into tStartChar
put charToNum(char tStartChar+2 of tImageData) into tRed
put charToNum(char tStartChar+3 of tImageData) into tGreen
put charToNum(char tStartChar+4 of tImageData) into tBlue
return tRed*65536+tGreen*256+tBlue
end getPixel
表面上看,这是 LiveCode 中实现方式比其他语言长得多的情况之一。然而,相当常见的是,你确实需要像素中的红色、绿色和蓝色值,而在其他语言中,你必须采取额外步骤来提取这些值。
将返回的数字转换为 24 位 RGB 值的额外步骤并不麻烦,因为 LiveCode 可以通过你自己的函数轻松扩展。如果你需要 24 位值,使用前面的函数,你将为 LiveCode 语言添加一个getPixel
函数。即使只是获取红色值,你仍然需要进行计算。也许有一天,LiveCode 将有一个内置的getPixel
函数,它的工作速度比你的函数更快。这里返回的 24 位数字实际上是以三个十进制数字表示的,而不是 24 位二进制值,但它通常仍被称为24 位。
神秘字节…
表示一个像素的四个字符中的第一个字符是不使用的。LiveCode 有关于如何使用imageData
的教程,其中那个字节被称为 Alpha。这很有道理,因为即使提供 32 位数的其他工具也将值拆分为 Alpha、红色、绿色和蓝色。为什么 RunRev 称为 Alpha 的字节不包含 alpha 值?谁知道呢!
一种可能性是值没有很好地发挥其作用。当谈到 alpha 透明度时,你有时可能是指图像是透明的,就像 GIF 图像中可能的情况一样。有时,你可能是指它是半透明的,即它只有部分透明。
为了解决问题的模糊性,LiveCode 有两个图像的其他属性,maskData
和 alphaData
:
put the maskData of image "test image" into tMaskData
put the alphaData of image "test image" into tAlphaData
这些图像属性仍然有所有行连在一起,你必须进行计算以找到给定像素的 alpha 值存储的位置。
使用 maskData
,你可以得到每个像素的一系列值。对于除了 0 以外的每个值,像素都是可见的。
使用 alphaData
,你可以得到像素不透明度的一系列值。0 将是完全透明的,255 将是完全不透明的,介于两者之间的值将是半透明的。128 将是 50% 不透明的。
在本章的后面,我们将使用 maskData
和 alphaData
,我们将把 0-255 的 alphaData
值称为其 透明度,把零或非零的 maskData
值称为其 遮罩。
imageData 的误用
LiveCode 在线教程中的主题包括 imageData
的操作,将彩色图像转换为灰度图像(这个将彩色图像转换为灰度图像的特定示例位于 lessons.runrev.com/s/lessons/m/4071/l/25371-vision-how-do-i-convert-a-color-image-to-grayscale
)。我们在这里不会做这个。相反,我们将使用图像、遮罩和 alpha 中的值来实现一些不会改变图像的巧妙功能。实际上,在某些情况下,我们甚至可能看不到图像!
行动时间 – 测试 getPixel 函数
在到达有用的示例之前,让我们创建一个 getPixel
函数来获取图像中某点的颜色分量,然后完成一个快速测试用例。以下步骤将帮助你完成这个过程:
-
创建一个新的 Mainstack。点击 保存 将其保存为 ImageDataTests。
注意
我们将使用同一个堆栈来展示几个方面,最后,我们可能会尝试在移动设备上尝试它!
-
将堆栈的分辨率设置为你的最大测试设备的大小,或者如果你将使用 iPad 模拟器,就尝试 1024 x 768。
-
从 文件 菜单中,导航到 导入为控件 | 图像 并选择你拥有的任何小图像文件,将其放置在卡片窗口的左上角。下一个示例将使用可以从任何 LiveCode 网页轻松获得的 LiveCode 标志图像。
-
在图像旁边放置一个新的
Graphic
对象。它将显示单色,所以只需让它足够大,以便你可以轻松地看到颜色。将其命名为swatch
。 -
将图形设置为默认显示一个空框,所以在消息框中输入以下内容:
set the filled of graphic 1 to true
-
编辑图像的脚本,并输入以下行:
on mouseMove pMx,pMy --put getPixel(the short name of me,pMx - the left of me,pMy - the top of me) into tPixelColor --set the backgroundColor of graphic "swatch" to tPixelColor end mouseMove
-
注意,这两行已被注释掉。如果我们在创建该函数之前不断请求
getPixel
,LiveCode 只会抱怨! -
编辑堆栈脚本。添加
getPixel
函数,它与我们在前面步骤中讨论的图像数据格式非常相似:function getPixel pImage,pX,pY put the imageData of image pImage into tImageData put the width of image pImage into tWidth put ((pY-1)*tWidth + (pX-1)) * 4 into tStartChar put charToNum(char tStartChar+2 of tImageData) into tRed put charToNum(char tStartChar+3 of tImageData) into tGreen put charToNum(char tStartChar+4 of tImageData) into tBlue return tRed,tGreen,tBlue end getPixel
-
在图像脚本中,取消注释两行。开始指向图像,你应该看到色板图形的颜色改变以匹配光标下的像素。
发生了什么?
我们做了一个非常简单的例子,说明了如何使用图像中像素的颜色;在这种情况下,如何着色色板。由于设置图形的backgroundColor
需要redvalue
、greenvalue
和bluevalue
,我们不需要将图像中的值转换为 24 比特数,getPixel
函数能够返回tRed,tGreen,tBlue
。
现在,与我们使用的方法相比,与内置的mouseColor
函数相比,并没有真正的好处。然而,至少我们尝试了getPixel
函数!
快速问答——一个字节中有多少比特?
字节在本章中提到了几次,你很可能已经知道关于比特深度的信息,因为我们已经讨论了数字照片。那么,告诉我,一个字节中有多少比特?
-
32
-
24
-
8
-
取决于你有多饿
答案:8
在本章的其余部分,我们甚至不会提及比特或字节;然而,仅为了满足数学家的兴趣,了解一个字节由 8 比特组成是好的。比特是一个二进制数字,当你开始用这种方式思考比特时,你会发现一个字节可以存储 2 的 8 次方个值(二进制是基数 2)。这一点在查看 Pascal 字符串的长度时就会显现出来(2 的 8 次方是 256,因此 Pascal 字符串中字符的范围是 0-255),这有助于你意识到,如果一张图片由一个字节组成,对于每个像素的红色、绿色和蓝色值,它就是一个 24 比特的图片。一旦你为 alpha 通道添加另一个字节的数据,你就得到了一个 32 比特的图片。
模拟许多按钮
在某些应用程序中,你需要确切知道用户指向图像的哪个区域。例如,当有一个地图,你想要显示与用户点击的区域相关的信息时,这可以通过很多矩形按钮来完成,或者你可以将区域分解成图形并使用mouseEnter
处理程序来检测它是哪个区域。相反,你可以使用单个图像来表示所有区域。
是时候行动了——制作美国地图
在网上有很多地方可以获取公共领域图像用于你的应用程序。搜索public domain images
,你会看到指向维基百科文章、政府网站和其他允许你下载免费使用图像的网站的链接。以下步骤中显示的地图来自以下文件:
upload.wikimedia.org/wikipedia/commons/3/32/Blank_US_Map.svg
.
-
创建一个名为
states
的新字段。找到一个包含 50 个美国州的字母顺序列表,将其粘贴到字段中,或者你也可以手动输入它们! -
创建另一个字段,将文本大小设置为 24,并将字段宽度设置得足够容纳 New Hampshire(仅限单词,不包括整个州!)的大小。将字段命名为
state
。小贴士
下载完成的地图
注意,你可以通过从本书的支持文件部分下载
us-map.png
文件来节省大量工作,你可以在 www.PacktPub.com 找到它。 -
如果你拥有 Adobe Illustrator,用其打开 SVG 文件。如果没有,则用 GIMP 打开。在 Macintosh OS X 上,Pixelmator 是一个低成本的选择。
-
按字母顺序,在每个州上填入一个颜色,其中红色、绿色和蓝色的值与该州的行号加 100 相匹配。我们添加 100 是为了让我们将看到的灰色阴影不那么暗。
-
对所有州重复相同的操作。以下是 Illustrator 中的开始外观,爱达荷州即将被着色为
112
,112
,112
: -
改变地图的大小,使其大约填充堆栈窗口的三分之一,然后选择 导出。
小贴士
颜色配置文件设置
LiveCode 以一种忽略图像中颜色配置信息的方式处理位图,这会破坏我们试图做的事情。在导出图像时,检查是否有选项将颜色配置文件设置为
genericRGB
。如果没有,则使用 Color Sync 等工具应用genericRGB
颜色配置文件。一旦图像保存,你可以做一些事情来确保它能够正确导入到 LiveCode 中。在导入之前,在消息框中输入并将屏幕伽玛设置为2.23
,然后按 Enter。这将设置 LiveCode 为正确的设置,以确保颜色值正确显示。 -
如果你使用 Illustrator,将背景设置为 白色,并将抗锯齿设置为 无。在使用 GIMP 时,确保 PNG 文件没有保存 alpha 通道。
-
在消息框中输入此行,然后按 Enter 键:
set the screengamma to 2.23
-
将 PNG 图像导入到你的
ImageDataTests
栈中。 -
将图像的脚本设置为以下内容:
on mouseMove pMx,pMy put getPixel(the short name of me,pMx - the left of me,pMy - the top of me) into tStateColor set the itemdelimiter to comma put item 1 of tStateColor - 100 into tLine put line tLine of field "states" into field "state" end mouseMove
-
尝试指向不同的州,至少指向那些你已经着色的州。州名应该出现在
state
字段中。
刚才发生了什么?
对于这个案例,我们只需要查看光标下像素的红色通道值(绿色和蓝色值相同,因为我们使用了灰色的颜色值)。而不是编写另一个函数来仅获取数据的红色部分,我们重用了现有的 getPixel
函数,但只关注该函数返回的第一个项目。这个数字,在减去我们添加的 100(为了让阴影不那么暗)之后,被用作查找值来获取相应的州名。
突击测验 – 获取整体概念
示例地图图像是一个 SVG 文件。对于给定的图像,SVG 文件比 PNG 文件小吗?(进行一点维基百科研究并决定答案。)
-
是的
-
否
-
取决于图像的性质
答案:3
SVG 是描述如何绘制图像的方式,而 PNG 是描述图像像素的方式。在 PNG 中,这些信息也被以无损方式压缩。对于示例地图,在其原始大小下,24 位的 PNG 文件大小是 SVG 文件的一半。描述美国各州轮廓需要大量的数据!如果需要放大图像,PNG 文件会变成更大的文件,而 SVG 文件大小将保持不变。另一方面,如果图像是一个对角渐变的矩形块,SVG 文件会非常小,而 PNG 文件会非常大,因为数据压缩无法很好地工作,因为没有相同颜色的像素长串。
使用 maskData 进行碰撞检测
在古老的二维迷宫冒险游戏中,你的角色会以明显的块状移动,而在检查是否有墙壁或空隙时,程序只需要检查相对较少的位置。占据的位置可以存储在数组中,占用很少的内存。
对于其他迷宫游戏,例如那些弹珠迷宫倾斜板游戏,你必须以更精细的程度检测碰撞。一个完整的物理引擎可以处理这个问题,但通过将迷宫存储为图像并检查角色或弹珠前面的像素,可以得到一些有趣的结果。
在一个功能齐全的游戏中,最好使用imageData
或可能alphaData
,这样你就可以知道你将要撞到什么,并且从你读取的值中,你还可以知道你撞到了什么。例如,在弹珠迷宫游戏中,你需要知道你是否已经越过了洞口。
然而,对于接下来的测试,我们将只使用maskData
并看看我们能否避免撞到我们前面的东西。
行动时间 - 制作赛道
我们将制作一个小汽车的赛道,我们将使用我们构建的堆栈来制作它!首先,我们需要将卡片上的内容转换为表示墙壁和空间的图像:
-
使用 LiveCode 的绘图工具,向
ImageDataTest
堆栈中添加一些对象。这些将成为赛道上的障碍物。 -
要创建我们需要的图像,在消息框中输入以下内容:
import snapshot from rect the rect of this stack
-
前面的命令将截取卡片窗口的屏幕截图并将其放置在卡片上作为新的图像控件。新的图像将覆盖整个卡片,因此不会引起注意。你可以通过项目浏览器确认图像已创建并选择它。
-
右键单击创建的图像并选择启动编辑器。这将打开你在首选项/常规中设置的位图编辑器。如果你之前没有这样做,LiveCode 会提示你选择一个编辑器。
-
在你的图像编辑器的图层窗口中,复制初始的单个图层。
-
在复制图像图层下方创建一个新的透明图层。
-
删除原始图层。
-
使用编辑器的魔术棒选择包含图像的图层中的卡片图像的空白区域(不是透明图层)。删除所选区域以显示透明图层。
-
反转选择并填充一个深色(颜色不重要,因为我们只是用它来看到洞的位置)。
-
花一些时间填补任何小缝隙。还要在图像的外围放置一个粗边框。这显示了卡片的外观以及现在快照图像应该看起来像什么:
-
合并文档的图层,然后选择保存。
-
返回 LiveCode 并点击更新按钮,快照图像将更新以反映您所做的更改。
-
给图像命名为
backdrop
。稍后,我们将设置图像在其它对象之后,但现在我们将让它位于所有其他对象之上。
刚才发生了什么?
我们刚刚制作了一个看起来相当奇怪的赛道!在一个真正的俯视赛车游戏中,你必须仔细设计一个看起来很棒的赛道,并为碰撞检测制作图像的副本。在副本中,你必须擦除表示汽车可以驾驶的部分,然后,你必须用单色填充图像的其余部分。玩家将看到看起来很棒的赛道,而在下面则是用于检测碰撞的副本单色版本。
我们现在需要一个能在我们制作的赛道上自行驾驶的汽车。
是时候行动了——制作一辆赛车
花尽可能多的时间来创建汽车图像。让它面向右边。然后,一旦它在堆栈中,我们将开始向它的脚本添加所需的函数。大约 40 像素的宽度应该是合适的。我们的示例汽车也可在www.PacktPub.com找到。以下是我们正在讨论的近距离图像,如 Photoshop 中所示:
如果你喜欢,你的作品甚至可以更好!保存为具有透明度的 24 位 PNG。好的,发动引擎…:
-
将图像作为控件导入,并将其放置在
ImageDataTests
堆栈的白色区域中。命名为car1
。 -
如您所愿复制图像(以下脚本可以处理多达 100 辆汽车),并按顺序命名每个,例如
car2
、car3
等。 -
争论来说,正确的面向对象的方式是将一些函数放在图像上,一些放在卡片或堆栈脚本中,但出于性能原因,我们将一切放在堆栈脚本中。打开堆栈脚本。
-
添加一个用于全局变量的行:
global gBackdropMaskData,gMaskWidth,gSpeeds,gMovingCars,gMaskWidth
-
我们很快将添加一个启动/停止按钮,该按钮将调用一个函数来切换汽车是否移动。将切换函数添加到堆栈脚本中:
on startStopCars if gMovingCars is true then put false into gMovingCars else put the maskData of image "backdrop" into gBackdropMaskData put the width of image "backdrop" into gMaskWidth setSpeeds put true into gMovingCars send moveCars to this card in 2 ticks end if end startStopCars
-
由
startStopCars
调用的setSpeeds
处理器将为每辆汽车图像初始化gSpeeds
变量,并将初始方向设置为零,并将汽车定位在白色区域的一个已知位置(在本例中为200, 200
)。将setSpeeds
处理器添加到startStopCars
处理器下面的堆栈脚本中:on setSpeeds put empty into gSpeeds repeat with a = 1 to 100 put "car" & a into carname if there is a image carname then put (random(10)+10)/10 into item 1 of line a of gSpeeds put 0 into item 2 of line a of gSpeeds set the loc of image carname to 200,200 else exit repeat end if end repeat end setSpeeds
-
在
moveCars
处理器中,如第 8 步所示,我们将查看gBackdropMaskData
变量以检查汽车是否会撞到坚固的物体。添加此hitBarrier
函数:function hitBarrier pX,pY put (pY-1)*gMaskWidth + pX into tStartChar put charToNum(char tStartChar of gBackdropMaskData) into tMaskValue if tMaskValue = 255 then return true else return false end hitBarrier
-
moveCars
处理器最初由startStopCars
处理器调用,然后,每经过两个计时周期后,它会调用自己,直到gMovingCars
变量被设置为false
。将长的moveCars
处理器输入到堆栈脚本中:on moveCars put the long time lock screen repeat with a = 1 to 100 put "car" & a into carname put .1 into anglechange if there is a image carname then put 0 into counter repeat while counter < 20 add 1 to counter put item 1 of line a of gSpeeds into tCarSpeed put item 2 of line a of gSpeeds into tCarDirection put item 1 of the loc of image carname into tCarX put item 2 of the loc of image carname into tCarY put the round of ((cos(tCarDirection)*tCarSpeed)*20 + tCarX) into tLookAheadX put the round of ((sin(tCarDirection)*tCarSpeed)*20 + tCarY) into tLookAheadY if hitBarrier(tLookAheadX,tLookAheadY) then put tCarDirection + anglechange into item 2 of line a of gSpeeds put anglechange * -1 * ((20 - random(10))/10) into anglechange put max(1,tCarSpeed - .1) into item 1 of line a of gSpeeds else put min(3,tCarSpeed + .05) into item 1 of line a of gSpeeds exit repeat end if end repeat set the loc of image carname to item 1 of the loc of image carname + (tLookAheadX-item 1 of the loc of image carname)/10,item 2 of the loc of image carname + (tLookAheadY-item 2 of the loc of image carname)/10 set the angle of image carname to 360 - item 2 of line a of gSpeeds / PI * 180 else exit repeat end if end repeat unlock screen if gMovingCars is true then send moveCars to this card in 2 ticks end moveCars
小贴士
避免碰撞
抽取一段时间来查看
moveCars
处理器;它在做什么?你无疑已经听说过碰撞检测;这就是你拥有代码来识别一个物体与另一个物体或墙壁发生碰撞的地方。当这种情况发生时,你可以触发一个爆炸或碰撞声音。然而,对于我们的示例,我们实际上不希望发生碰撞,因为我们希望汽车在碰撞前转向。对于每辆汽车,最多 100 辆,我们将查看汽车前方以检查它是否会撞到赛道的边缘。如果它会这样做,我们将反复改变汽车行驶的方向,直到找到一个安全的前进方向。 -
在卡片窗口中添加一个启动/停止汽车按钮,并设置其脚本为:
on mouseUp startStopCars end mouseUp
-
选择背景图像,并从 对象 菜单中选择 发送到后台。
-
现在保存它是个好主意!
-
点击运行/浏览工具,然后点击启动/停止汽车按钮,以查看你的汽车在界面周围行驶。这里有 20 辆汽车移动的样子:
-
注意,你可以继续指向你最初加载的图像的部分(前一个示例中的 LiveCode 标志)以查看右侧的色卡改变颜色。此外,如果你指向不同的美国州,你创建的
state
字段中的文本会改变。
刚才发生了什么?
我们已经使用 imageData 实现了颜色选择器,并作为多个按钮区域使用,然后继续使用图像的 maskData 作为碰撞图。让汽车以智能方式移动背后有很多算术,你可以改变一些数字以获得不同的汽车行为,或者你可以休息一下,准备制作一个拼图!
快速问答 – 计算这个!
对于美国地图,我们只需要模拟 50 个按钮。如果你使用红色、绿色和蓝色值,你能模拟多少个按钮?
-
一个巨大的按钮
-
65,536 个按钮
-
16,777,216 个按钮
答案:3
就像关于位和字节的讨论一样(嘿,我确信我们不会在本章的其余部分看到这些词了!),红色、绿色和蓝色值组合起来给我们 2 的 24 次方可能的值。如果你只使用了两种颜色,那么答案将是 65,536。
本章中我们尝试的内容使用的技术在任何 LiveCode 应用中都很有用,并不特定于移动应用。你可以尝试你构建的堆栈;它将在屏幕上有 20 辆车行驶的移动设备上运行得很好!当触摸屏幕时,颜色选择器和状态图在移动设备上工作。然而,这些测试并没有真正利用到移动设备的功能。
制作拼图游戏
本章的剩余部分将基于关于imageData
的前面信息,并利用一些移动设备的功能。我们将制作一个拼图游戏应用。
分解成碎片…
我们将要使用的一般技术是,取一组具有良好 alpha 通道的 PNG 图片(这创建了拼图块的边缘),然后我们将用我们自己的图片替换实际的像素数据。因此,我们首先需要一些 PNG 图片。
如果你想要制作一个商业移动应用,要么创建你自己的拼图形状,要么购买一个免版税的图片。对于原型设计,你可以从网上抓取任何图片来开始基本操作,然后你可以用你购买的高质量图片替换它们。在这里,我们使用的是来自depositphotos.com/
的预览图片,它也销售高质量版本。
当你拥有高质量版本时,你可能希望创建每个拼图块,以便它们完美地相互接触。在这里,我们使用预览图片,并将每个拼图块的内部部分选择出来,然后从这些部分创建 PNG 图片。拼图块之间会有小缝隙,但至少这样我们可以快速准备所需的图片。
动手时间 – 创建拼图块和选择图片
如果你希望跟随这里显示的完全相同的图片,要知道它是从以下文件的上左部分拍摄的:
static3.depositphotos.com/1004551/191/v/950/depositphotos_1914748-Jigsaw-puzzle-blank-templates.jpg
。
图片如下所示:
以下步骤将帮助创建拼图块和选择图片:
-
创建一个大小为 1024 x 768(或你的平板设备大小)的新主堆栈。将堆栈命名为
jigsaw
,设置标题为Jigsaw Puzzle
,并保存。 -
在你的图像编辑器中打开整个拼图图片。
-
使用魔棒工具选择拼图左上角拼图块的内部部分。
-
用一种颜色填充它,以便容易发现任何剩余的缝隙。
-
将内容复制并粘贴到一个新的文档中(该文档具有透明背景,大小与复制的碎片相同)。
-
使用设置为相同填充颜色的画笔工具修复任何缺口。
-
保存为 PNG 文件(使用 Photoshop,这将是在 Web 和设备上保存,24 位,具有透明度)。使用可能有助于你轻松识别图片的命名方案。例如,
tlcorner.png
、p1.png
、trcorner.png
等等。 -
通过所有不同形状的区域进行操作。在示例图片中,可能会有多达 14 种独特的形状。不需要保存与你已经拥有的形状和方向相同的其他碎片。
-
图片集将与以下屏幕截图中的类似:
-
将所有 14 张图片作为Control/Image导入。
-
将拼图布局在覆盖大部分卡片窗口的区域。在下面的屏幕截图中,拼图大小为 900 x 622 像素,由 11 x 8 个碎片组成。通过选择键盘上的箭头键,你可以选择一个碎片后准确放置。
-
以网格状方式命名图片。左上角的碎片将被命名为
p 1 1
,右上角的边缘碎片将被命名为p 11 1
,而右下角的碎片将被命名为p 11 8
。 -
选择所有碎片并将它们分组。将组命名为
pieces
。 -
创建一个名为
fromcamera
的按钮和一个名为Take a Photo
的标签。将按钮脚本设置为以下内容:on mouseUp loadimage "camera" end mouseUp Make another button, named "fromlibrary" and labeled "Load a Picture", with this script: on mouseUp loadimage "library" end mouseUp
-
将按钮设置为获得阴影效果;使用检查器面板中的图形效果选项。
-
编辑卡片脚本并添加以下全局变量和函数,它们将初始化其他我们将制作的函数所需的价值:
global originalimage, puzzlewidth, puzzleheight, snapdistance, hcount, vcount on opencard setvalues end opencard on setvalues put 900 into puzzlewidth put 662 into puzzleheight put 50 into snapdistance put 11 into hcount put 8 into vcount end setvalues
-
现在,添加
loadImage
处理程序,这两个按钮将调用它以从用户的相机或相册中获取图片:on loadImage cameratype if puzzlewidth is empty then setvalues if there is an image "original" then delete image "original" mobilePickPhoto cameratype,puzzlewidth,puzzleheight if the result is empty then lock screen set the name of image the number of images to "original" set the width of image "original" to puzzlewidth set the height of image "original" to puzzleheight put the imageData of image "original" into originalImage delete image "original" --makepuzzle --scatter unlock screen else answer the result end if end loadImage
-
makepuzzle
和scatter
行目前被注释掉,这样你可以测试到目前为止的功能。
发生了什么?
拼图碎片现在已就位,并且以我们可以利用的方式命名。如果你转到独立应用程序设置并选择iOS或Android,你可以尝试该应用程序。
小贴士
设置一些测试图片
如果你使用 iPad 模拟器,你将无法测试从相机获取图片的功能,最初你将只有相册中的默认图片。要添加自己的照片,将图片从Finder拖动到模拟器窗口,图片将被添加到照片库中。你可以切换到模拟器的首页,使用cmd + Shift + H键组合重新选择拼图应用。这样,你可以添加一些图片到库中,以便选择一个作为拼图的图片。
当 LiveCode 从移动设备获取图片时,无论是从相机还是从库或相册中获取,它都会将图片放置为一个图像控件,这是卡片上最顶层的对象。我们不需要图片本身,只需要它的imageData
。在loadImage
处理程序中,图片被制作成与拼图块组相同的大小,imageData
存储在全局变量originalimage
中,而图片本身则被删除。
接下来,我们将选定的图片传输到拼图块上。
行动时间 – 转移 imageData
通过将选定的图像设置为与包含拼图块的组具有相同的宽度和高度(这就是 900 和 662 数字的来源),我们就可以将整个图像中匹配的矩形数据传输到相关的拼图块中。以下步骤将指导您传输 imageData:
-
再次打开卡片脚本。添加
makepuzzle
处理程序:on makepuzzle resetpuzzle put the number of images in group "pieces" into imagecount repeat with a = 1 to imagecount makepiece the short name of image a of group "pieces" end repeat end makepuzzle
-
makepuzzle
处理程序将遍历每个拼图块并调用另一个处理程序来为该块传输数据。以下是makepiece
处理程序:on makepiece piecename put the width of image piecename into piecewidth put the height of image piecename into pieceheight put empty into tempimage put the left of image piecename - the left of group "pieces" into dx put the top of image piecename - the top of group "pieces" into dy repeat with y = 1 to pieceheight put ((y+dy-1) * puzzlewidth + dx)*4 into sourcestart put char sourcestart+1 to sourcestart+piecewidth*4 of originalimage after tempimage end repeat set the imageData of image piecename to tempimage end makepiece
-
在早期的
imageData
测试中,我们一次只对一个像素感兴趣,但在这里,我们想要很多行数据。算术运算,*((y+dy-1) * puzzlewidth…*
,等等,可以快速一次提取一整行的像素。这些行被构建成一个新的变量tempimage
,最终被传输到实际的拼图块中。 -
在拼图块有了
imageData
的矩形之后,我们接下来需要将拼图块移动到随机位置,使游戏准备好供用户玩耍。这是通过一个scatter
处理程序来完成的:on scatter repeat with a = 1 to the number of images in group "pieces" set the myloc of image a of group "pieces" to the loc of image a of group "pieces" put the short name of image a of group "pieces" into n if edgepiece(n) then set the loc of image a of group "pieces" to 40 + random(400),300 + random(400) else set the loc of image a of group "pieces" to 500 + random(500),300 + random(400) end if end repeat end scatter
-
大多数拼图游戏玩家首先做的事情是分离直边拼图块。我们可以以节省他们时间的方式编写代码。我们可以使用一个函数将边缘拼图块放置在非边缘拼图块之外。从先前的
scatter
处理程序中调用的edgepiece
函数如下:function edgepiece pName return word 2 of pName = 1 or word 3 of pName = 1 or word 2 of pName = hcount or word 3 of pName = vcount end edgepiece
-
我们为每个拼图块精心设置的名称被检查以验证该拼图块是否位于拼图的左、右、上或下边缘。换句话说,它是一个位于拼图外边缘的拼图块。散布将直边拼图块放置在屏幕的左侧,其他拼图块则放置在屏幕的右侧,如图所示:
-
makepuzzle
处理程序的开始调用一个resetpuzzle
处理程序,该处理程序用于确保拼图块回到起始位置,准备好加载新图片。这是通过在每个拼图块上使用名为myloc
的属性变量来实现的,它记录了拼图块的初始位置。以下是resetpuzzle
处理程序:on resetpuzzle repeat with a = 1 to the number of images in group "pieces" if the myloc of image a of group "pieces" is not empty then set the loc of image a of group "pieces" to the myloc of image a of group "pieces" else set the myloc of image a of group "pieces" to the loc of image a of group "pieces" end if end repeat end resetpuzzle
-
您可以看到,如果
myloc
尚未设置,则拼图块必须在起始位置,因此resetpuzzle
处理程序会继续并在myloc
属性中记录该位置。 -
取消注释在行动时间 - 创建拼图块和选择图像步骤 17 的行(
makepuzzle
和 scatter 行)并尝试再次测试应用程序。现在你应该能够选择一张图片,并在展开的拼图块中看到它。希望你会看到类似这样的东西:
发生了什么?
如前所述,正确的算术运算使得我们从大图中提取所需矩形imageData
相对容易,并将其存储在大小与该矩形相同的小图像中。然而,有一个魔法般的细节并未被指出,即拼图保持了其形状!尽管我们已经完全替换了图像的imageData
,这是如何发生的呢?设置imageData
不会干扰图像的alphaData
。我们导入的 PNG 图像保留了其原始的 alpha 通道,因此仍然保持了相同的形状,只是图像不同。
添加交互性
我们的拼图游戏已经准备好发货了!好吧,除了它完全没有交互性之外!让我们添加一些。
行动时间 – 设置触摸事件
到目前为止的处理程序都在卡片脚本中,计划是让不同的卡片有不同的拼图类型。交互处理程序可以放在所有卡片都适用的堆栈脚本中。
-
打开堆栈脚本。在堆栈脚本中,我们还需要一个全局变量,但有一些初始化项需要处理。用以下这些行开始堆栈脚本:
global snapdistance on preopenstack if the platform contains "iphone" then iphoneUseDeviceResolution true end preopenstack on openstack set the compositorType of this stack to "Static OpenGL" end openstack
-
preopenstack
处理程序检查应用程序是否在 iPhone 上,并请求使用设备的原生分辨率。这将确保 Retina 显示屏显示最佳质量。将compositorType
设置为"Static OpenGL"
将有助于性能。 -
我们将使用的交互性将利用触摸事件。每个触摸都带有相关的 ID 值。以下是检测触摸事件开始的处理器:
on touchStart touchid put the short name of the target into n if word 1 of n is "p" then set the dropShadow of image n to the dropShadow of button "fromlibrary" set the relayerGroupedControls to true set the layer of the target to the number of images in group "pieces" end if end touchstart
-
目标名称的检查是一种快速的方法,以确保我们除了拼图块之外不会拖动任何东西。当拼图块被触摸时,我们使用
relayerGroupedControls
和层函数使该拼图块出现在其他拼图块之上。 -
你还记得我们是如何给两个按钮添加阴影效果的吗?除了使它们看起来更美观之外,我们在这里也使用了它。通过给拼图块添加相同的
dropShadow
,我们创造了一种错觉,即拼图块似乎漂浮在屏幕上方。 -
接下来要注意的是运动,我们可以通过
touchMove
事件来实现:on touchMove touchid,touchx,touchy put the short name of the target into n if word 1 of n is "p" then set the loc of the target to touchx,touchy end if end touchMove
-
再次,有一个快速的双重检查,以确保它是拼图块;如果不是,那么就是一个简单的将拼图块位置设置为用户手指位置的情况。
-
当用户释放拼图块时,我们检查它是否靠近其起始位置,如果是,我们将拼图块移动到其位置并移除 dropShadow 效果:
on touchEnd touchid put the short name of the target into n if word 1 of n is "p" then checkdistance the short name of the target set the dropShadow of the target to empty checkfinished end if end touchEnd
-
这是
checkdistance
处理程序和它调用的distance
函数:on checkdistance dt if snapdistance is empty then put 100 into snapdistance put distance(item 1 of the loc of image dt - item 1 of the myloc of image dt,item 2 of the loc of image dt - item 2 of the myloc of image dt) into d if d<snapdistance then put max(.1,min(.2,d/200)) into t move image dt to the myloc of image dt in t seconds set the relayerGroupedControls to true set the layer of image dt to 2 end if end checkdistance function distance dx,dy return sqrt(dx*dx+dy*dy) end distance
-
distance
函数基于勾股定理,返回拼图块与其原始myloc
值之间的像素数。snapdistance
是一个全局变量,用于确定拼图块是否足够接近其起始位置,从而被认为是目标位置。 -
move
行使用 LiveCode 的移动函数,将拼图块动画化到其位置。 -
最后一点,让我们检查一下拼图是否完成。将以下处理程序添加到堆栈脚本中:
on checkfinished repeat with a = 1 to the number of images in group "pieces" if the myloc of image a of group "pieces" <> the loc of image a of group "pieces" then exit checkfinished end repeat answer "You've done it!" end checkfinished
刚才发生了什么?
拼图现在应该完全工作。从我们添加的触摸功能中难以轻易猜测的是,它支持多点触控。你可以同时拖动多达 10 个拼图块(或你的设备多点触控的限制)。在这里,每个拼图块都会显示一个阴影,当你放手时,所有拼图块都会动画化到它们的位置。
尝试一下英雄之旅——这是为孩子们准备的
与拼图本身相关的函数位于卡片脚本中。尝试制作一张新卡片,其中包含更大的拼图块和更高的snapdistance
值(值越高,将拼图块放置到位就越容易)。你可以为堆栈制作一张包含难度级别按钮的起始卡,其中一个按钮会跳转到更简单的拼图。这对年轻玩家来说将是理想的。
添加一些引导图形将帮助玩家知道完成拼图的边缘在哪里,对于更简单的难度级别,甚至可以包括单个拼图块的轮廓。
摘要
在使用imageData
于绘图程序、图像处理应用等场景时,有许多其他可能性,并且与前面的示例相同。在本章中,我们回顾并理解了imageData
、alphaData
和maskData
的格式,以及如何将imageData
的一个区域复制到另一个图像中。这里还涵盖了读取图像的单独像素并寻找像素值的新用途。我们还看到了如何使用多点触控交互,将这些imageData
块以拼图的形式激活。
与图形一起工作可以非常有趣,希望这仅仅是您将要创造的起点。然而,在下一章中,我们将回到制作实用应用程序。唉……
第六章. 制作提醒应用
自我提醒…
待办事项、闹钟、生日提醒、笔记、购物清单,等等。应该有一个应用来保存所有保存列表的应用!在撰写这本书的时候,已经有超过 8000 个 iOS 应用是列表、计划或闹钟。或许,还有空间再增加一个…
探索所有现有的提醒应用可能需要大量的研究和资金。大多数应用都会有你永远不会使用的许多功能,以及至少一个缺失的必要功能。如果你很幸运,一些应用组合可能能够完成你想要的提醒功能。然而,不要忘记你可以使用 LiveCode 并创建自己的提醒应用!
在本章中,我们将:
-
讨论一下“提醒”的含义
-
创建一些时间测量实用函数
-
定义一个数据结构来存储关于活动的信息
-
利用移动设备的“通知”
-
创建一个灵活的提醒应用
不同类型的提醒
这里是一些你可能称之为“提醒”的东西的列表:
-
购物清单
-
圣诞礼物清单
-
待办事项列表
-
闹钟
-
计时器
-
生日提醒
现在,有没有一种方法可以描述所有这些事情?嗯,可能会有些冗长,但提醒可以被描述为自动出现或在你查找时显示的通知消息或声音。它用于让你知道已经过去了一定时间,某个时刻已经到来,或者一个未完成的任务尚未完成。
看起来有点冗长。这样分解可以帮助我们看到提醒应用需要具备哪些功能。在深入探讨之前,让我们将这个定义与前面的例子进行对比:
购物清单:在这种情况下,你需要寻找提醒。尽管,我们可以设置它在你靠近商店时自动显示!除此之外,这实际上是一个尚未完成的任务。
圣诞礼物清单:这和购物清单差不多,但它可以使用一个定时消息来告诉你还有多少天可以购买圣诞礼物给你的亲人。
待办事项列表:再次强调,这仅仅是一个尚未完成的任务列表。
闹钟:这会给你一个通知,表明时间已经到达。
计时器:这是关于一定时间已经过去的通知,这可以用于烹饪伙伴应用中可能用到的此类事件的序列。
生日提醒:这显示了是否已经达到某个特定时刻。实际上,你希望设置提醒,以便在事件实际发生之前通知你。
至少作为一个起点,我们可以使用这个定义来指导我们概述应用需要具备的能力。
通知的时间安排
使用 LiveCode 可以创建的移动通知将在您请求发送的那一刻发送。奇怪的是,这个值是基于 1970 年 1 月 1 日午夜以来的秒数,具体来说,部分位于伦敦!嗯,它是以伦敦的一个地区命名的,称为格林威治。
格林威治标准时间,通常简称为GMT,已被用作测量时间的标准。它已被UTC(协调世界时)所取代,但无论如何,它至少代表格林威治所在时区的确切当前时间。我们其他人会从这个值中加上或减去一些时间。
为了适应地球围绕太阳转动的天数或四分之一天数的精确数,日历每四年调整一天,但不是在 100 年边界上,除非每 400 年(例如,2000 年是闰年)。这些调整仍然不足以保持时钟准确!时钟每年会慢大约 0.6 秒,因此会添加“闰秒”来补偿。理论上,闰秒可以用来减去一秒,但到目前为止,这还没有必要,因为它们只被用来添加一秒。
这一切都不会影响自 1970 年 1 月 1 日午夜以来的秒数,但这确实意味着使用您自己的算术将 LiveCode 的秒转换为时间和日期不会得到正确的时间。然而,它仍然用作通知的基础。这个值通常被称为 Unix 时间。
虽然如果您提前 25 秒发送生日祝福信息也不是很重要!不用担心,我们将计算通知时间的方式会处理这种异常。
日期和时间选择器
如前所述,移动通知使用自 1970 年 1 月 1 日午夜以来的秒数,并且不会添加自那时以来的 25 秒或闰秒。当我们向用户展示日期和时间选择器时,用户所做的选择将返回为实际当前或未来的时间。我们稍后会进行调整。
行动时间 - 创建日期和时间选择器
让我们再做一个测试堆栈,我们将使用它来尝试一些日期和时间选择器:
-
创建一个新的 Mainstack,命名为
ReminderFunctions
,并保存堆栈。 -
添加两个字段和两个新的按钮。
-
命名一个字段为
dateinseconds
,另一个为timeinseconds
。 -
将按钮命名为
Pick Date
和Pick Time
。 -
将选择日期按钮的脚本设置为以下内容:
on mouseUp mobilePickDate date put the result into tDate convert tDate to seconds put tDate into field "dateinseconds" end mouseUp
-
将选择时间按钮的脚本设置为以下内容:
on mouseUp mobilePickDate "time" put the result into tTime convert tTime to seconds put tTime into field timeinseconds end mouseUp
-
设置独立应用程序设置,以便您可以在 iOS 或 Android 上进行测试。
-
选择您的测试目标(在以下步骤中,您可以看到在这种情况下选择了 iPhone 模拟器)并执行测试。
-
点击选择日期按钮。
-
选择
2012 年 12 月 25 日
并点击完成。 -
从 1970 年 1 月 1 日午夜到 2012 年圣诞节午夜的总秒数将显示在您创建的第一个字段中。
-
点击选择时间按钮,将时间设置为
凌晨 1 点
。以下图像显示了 iOS 和 Android 模拟器上选择器的外观不同: -
点击完成,您将在右侧字段中看到从 1970 年 1 月 1 日午夜到您进行此测试当天凌晨 1 点的秒数。
刚才发生了什么?
我们刚刚创建了两个简单的脚本,这些脚本调用原生的日期或时间选择器,并将结果转换为秒,然后在字段中显示它们。值得注意的是,对于选择时间的情况,它不会返回当前天的秒数,即自 1970 年 1 月 1 日午夜以来的所有秒数。为了设置特定日期特定时间的提醒时间,我们必须进行一些算术运算。我们将在本章的制作提醒应用部分稍后进行介绍。
快速测验 – OA(奇数缩写!)
您可能已经注意到,“协调世界时”的缩写是 UTC 而不是 CUT。为什么是这样?
-
CUT 是一个过于常见的词。
-
为了不冒犯法国人。
-
缩写委员会成员是阅读障碍者。
答案:2
法国可能没有积极反对,但确实,UTC 的缩写是为了不与英语版本的短语具体匹配。它也与 UT0、UT1 等其他缩写很好地结合在一起。
在哪里?
在移动提醒应用中,我们可以做些在纸笔版提醒中永远无法做到的事情;我们可以根据您检查提醒时的位置来展示提醒列表!为了使用位置,您需要知道您现在在哪里以及您的位置与与提醒相关的地方有多远。
在撰写本书时,LiveCode 没有直接拉入地图的能力,以便您可以选择除您现在所在位置之外的其他位置。因此,我们将在这种限制下工作。
注意
话虽如此,有一个名为mergMK
的外部工具(更多信息,请参阅mergext.com
),它可以与 7.0 之前的 iOS 版本一起使用,并且在撰写本书时正在更新。您还可以使用文章中描述的 HTML 和 JavaScript 的组合,该文章位于stackoverflow.com/questions/25629786/fetch-data-from-html-file-in-livecode
。然而,这些都不在本初学者的书籍范围之内。
在读取移动设备传感器时的一般技术是开始跟踪一个给定的传感器,检测何时发生变化,并停止跟踪该传感器。您可以在开始和停止跟踪命令之间的任何时间从传感器读取数据。您还可以指定您想要的报告的详细程度以及是否需要精确读取。位置的精确读取将决定是否使用了 GPS。使用 GPS 的优点是您可以获得更高的精度(假设当时信号清晰),缺点是它消耗更多的电量,并且没有 GPS 的设备无法使用此功能。当使用位置作为提醒的一部分时,我们主要关心的是您是否在家、办公室,或者可能在超市。因此,我们将使用不太精确的读取,GPS 的读取可能会过度。
是时候动手实践了——尝试原生位置跟踪
在本章的后面部分,我们将添加一个功能,允许应用程序用户添加一组收藏位置。目前,我们只是尝试基本功能。位置服务在模拟器中不起作用;您必须在真实设备上尝试此操作:
-
使用前一步骤中的测试架栈,添加一个
Get Location
按钮和一个location
字段。确保location
字段与卡片窗口一样宽;它将显示三个长数字。 -
将按钮的脚本设置为以下内容:
on mouseUp mobileStartTrackingSensor "location", true put mobileSensorReading("location", false) into field "location" mobileStopTrackingSensor "location" end mouseUp
-
第二行中的
true
值定义了一个 松散 的值,表示我们不需要 GPS 的精度。第三行中的false
值表示我们不需要返回详细的信息。 -
前往 独立应用程序设置 并选择您的目标设备为 iOS 或 Android。
-
对于 iOS,设置 显示名称、内部应用程序 ID 和 配置文件。选择您的设备和 SDK 版本):
-
此外,在 iOS 的 要求和限制 部分中,选择 位置服务 和 GPS 作为所需服务。在应用中,当 iOS 提示时,您也必须接受位置服务。
-
对于 Android,设置 标签、标识符 和 最低 Android 版本 字段:
-
此外,在 Android 设置的 应用程序权限 部分,确保您已请求获取 粗略位置 权限:
-
选择 保存独立应用程序 并将应用安装到您的设备上。如果您需要关于如何操作的提醒,请参考 第二章,LiveCode Mobile 入门。
-
在应用中,尝试点击选择日期和选择时间按钮,看看它们如何弹出原生控件,然后点击获取位置按钮。三个长数字应该出现在
location
字段中:
刚才发生了什么?
如你所见,读取位置所需的代码非常少!如果这是一个跟踪应用,你需要保持跟踪开启,并拥有响应位置变化消息的功能,但对我们这个应用来说,我们只需要知道你在查看提醒列表时的位置。
位置字段中显示的数字是设备的纬度、经度和海拔。然而,我们将如何使用这些数字…?
计算地球上两点之间的距离
计划是使你的应用能够根据你现在的位置对提醒列表进行排序。假设你真的经常使用这个应用,并且有几十个提醒。你创建的关于购买面包的提醒可能位于列表底部,但如果你已经为那个提醒分配了超市的位置,当你在外面超市时排序列表应该会将购物清单项目带到顶部。
面对像这样的问题时,你将如何知道地球上两点之间的距离;Google 是你找到答案的好起点!只需进行很少的研究和时间就能找到:
www.movable-type.co.uk/scripts/latlong.html
这个网址上的文章讨论了计算这个值的原始公式,然后展示了一个 JavaScript 函数。如果你发现将方程转换为 LiveCode 处理程序很困难,你应该能够逐行将 JavaScript 转换为 LiveCode 的等效代码。
目前无需输入此代码,我们稍后会将其集成;然而,如果你想试一试,请将这些行放入堆栈脚本中:
function distance lat1,lon1,lat2,lon2
put 6371 into r
put toRad((lat2-lat1)) into dLat
put toRad((lon2-lon1)) into dLon
put toRad(lat1) into lat1
put toRad(lat2) into lat2
put sin(dLat/2) * sin(dLat/2) + sin(dLon/2)*sin(dLon/2) * cos(lat1)*cos(lat2) into a
put 2*atan2(sqrt(a),sqrt(1-a)) into c
put r*c into d
return d
end distance
function toRad pAngle
return pAngle/180*PI
end toRad
在消息框中尝试以下操作:
put distance(40,-74,51,0)
如下截图所示:
如前一个截图所示,你应该看到一个值为5645.48065。这两个位置位于纽约和伦敦附近,这个值将是地球表面上两点之间的距离(千米)。
快速问答 - 我的公寓在几楼?
查看截图(时间标记为“下午 6:53”,在之前的截图之前),考虑到我住的建筑离海平面不高,我住在哪一层?
-
40 楼
-
地下 73 楼
-
11 楼
-
我无家可归
答案:3
来自位置传感器的数字以纬度、经度和海拔高度返回。这将使设备当时的海拔高度约为 37.5 米,这太低了,不可能是 40 层。截图中有足够的信息让您知道它是在何时何地拍摄的!
提醒中需要的信息
我们已经知道了如何设置提醒通知的时间和时间,并且我们能够根据我们所在的位置对提醒进行排序。然而,提醒本身需要哪些具体信息?
如果这是一个生日提醒应用,你只需要询问人的名字和他们生日日期。如果是一个购物清单应用,你需要物品的名称和数量。对于计时器,你需要询问事件名称并设置事件的时间。
然而,我们在这里尝试制作一个完全灵活的提醒应用;用户可以以他们希望的方式描述项目。因此,我们只需要求用户提供标题和简要描述。我们还需要提供设置日期、时间、相关位置以及是否播放警报声音的选项。
另一件需要考虑的事情是;我们将把提醒列表的信息存储在哪里?在制作第四章中的 WebScraper 应用时,我们在“使用远程数据和媒体”中选择了将主应用程序堆栈复制到文档文件夹中,然后跳转到该堆栈的副本。这使得能够保存对堆栈的更改。提醒应用是一个更简单的情况;我们只是试图存储一些文本字符串来定义每个提醒,而使用这个应用直接写入文本文件会更简单。
我们希望允许用户创建位置列表,以便将提醒与该位置关联。而不是编写不同的文本文件,我们将每个条目中的第一条信息作为该条目的功能。目前,只有两个功能,即位置
和提醒
。以下是一个文本文件可能看起来像的示例:
Location Home 40.692636 -73.978376
Location Office 40.745194 -73.985199
Reminder Packt Ask for more time! 1334548800 Home false
Reminder Boss Buy lunch 1334592000 Office true
每行中的项目之间有一个制表符,它将被用来分隔条目的各个部分。位置的格式如下:
-
功能:
位置
-
位置标题
-
纬度
-
经度
对于提醒来说:
-
功能:
提醒
-
标题
-
简要描述
-
自 1970 年 1 月 1 日午夜以来的通知时间(以秒为单位)
-
与此提醒关联的位置
-
是否播放警报声音(
true
或false
)
制作提醒应用
好的,基础工作已经足够了!让我们开始制作提醒应用。我们不会在添加功能的同时添加任何脚本,而是首先制作创建应用GUI(图形用户界面)所需的各个卡片,然后再回去添加脚本。
布局卡片
我们将使堆栈的第一个卡片成为一个您可以查看当前提醒、按时间或位置排序以及添加新提醒和位置的地方。然后,我们将创建第二个卡片来输入位置详情,以及第三个卡片来输入新提醒的详情。
行动时间 – 创建提醒应用屏幕
这里显示的步骤将使用标准的 LiveCode 字段和按钮,但请随意使您的版本更具吸引力!
-
创建一个新的 Mainstack,将其命名为
EasyReminder
并保存。其他名称,如Simple Reminders
可能更具体,但如果您使用的是较旧的 iPhone,名称可能会太长。 -
将卡片大小设置为您的设备大小。本节中显示的截图是基于较旧的 iPhone 大小的堆栈。
-
前往 独立应用程序设置 并以我们在测试 位置 功能时相同的方式设置值。
-
将第一个卡片的名称设置为
home
。 -
创建一个 按时间排序 按钮、一个 按位置排序 按钮、一个名为
reminders
的字段、另一个名为data
的字段,以及两个名为Create Reminder…
和Create Location…
的按钮。 -
添加一个名为
Delete Location or Reminder
的按钮。 -
确保这两个字段都勾选了 锁定文本 和 不换行 复选框。
-
您现在应该有一个看起来像以下截图的屏幕:
-
创建一张新卡片,并将其命名为
location
。 -
添加一个字段并设置其内容为:
输入此位置的纬度和经度
。 -
添加两个名为
latitude
和longitude
的输入字段。 -
创建一个名为
Set to Current Location
的按钮。小贴士
避免拼写错误
虽然我们为您提供了一个手动输入位置的字段,但如果可能的话,请使用 设置为当前位置 按钮,或者至少在您当前的位置使用它,以查看所需的格式。
-
添加另一个指示字段,内容为:
为此位置输入名称:
。 -
添加一个名为
location name
的第三个输入字段。请注意,在屏幕较小的旧手机上,此字段位置需要靠近屏幕顶部,以免被键盘弹出窗口覆盖。 -
最后,添加一个名为
Add Location
和Cancel
的按钮。 -
对于这张卡片,所有三个字段都需要取消勾选 锁定文本 复选框。
-
此卡片应看起来像以下截图:
-
创建第三个卡片并将其命名为
reminder
。 -
添加两个指示字段,内容分别为:
为此提醒输入标题:
和输入简要描述:
。 -
创建两个名为
title
的输入字段。 -
创建三个按钮,分别命名为
Set Related Location
、Set Date
和Set Time
。 -
在这些按钮旁边添加三个字段,这些字段将用于向用户显示他们所做的选择已发生。将字段命名为
location field
、date field
和time field
。 -
创建一个名为
Play Alert Sound
的复选框按钮。 -
最后,创建两个名为
Add Reminder
和Cancel
的按钮。 -
将所有这些元素排列成以下截图所示的样子:
发生了什么?
我们已经为应用功能制作了所有必要的屏幕。这是简单的一步。只需等待你看到将要进行的输入量!
栈级别脚本
前面有一大段代码。逐个功能描述会让我们四处跳跃,这可能会在某些情况下增加现有脚本的复杂性,我们很容易在这种情况中迷失方向。所以,我们不会那样做,而是每次查看一个卡片的代码,以及进入栈脚本的处理器。这主要在 开始行动 部分展示,主要是为了给你提供休息的机会!现在,我们不再拖延,直接展示栈脚本…
开始行动 - 添加栈级别函数
对于这个应用,我们将在卡片本身的按钮中放置一些逻辑,但这仍然留下了一大堆需要放入栈脚本中的内容。为了减少压力,我们将一次展示一个或两个函数,并在接下来的步骤中解释任何有趣之处:
-
打开栈脚本。
-
输入以下处理程序:
on openstack if the platform is "iphone" then iPhoneSetKeyboardReturnKey "done" readdata showdata end openstack on returnInField focus on nothing end returnInField
注意
Android 操作系统的键盘通常有一个专门的按钮用于关闭键盘。在 iOS 上,情况并非如此,因为原本应该放置 Return 键的按钮可能显示一个特殊词,例如 发送 或 完成。不幸的是,我们正在输入能够接受回车字符的字段。为了解决这个问题,我们将回车按钮设置为显示 完成,这样当按下该按钮时,用户就会期待键盘消失。我们还将捕获
returnInField
消息,并利用它来实际关闭键盘。 -
接下来,输入将读取和写入设备文档文件夹中提醒列表文本文件的函数:
on writedata global gReminderData put specialFolderPath("documents") & "/reminders.txt" into tRemindersPath if gReminderData is empty then put "no entries yet" into gReminderData open file tRemindersPath write gReminderData to file tRemindersPath close file tRemindersPath clearnotifiers setupnotifiers end writedata on readdata global gReminderData put specialFolderPath("documents") & "/reminders.txt" into tRemindersPath if there is a file tRemindersPath then open file tRemindersPath read from file tRemindersPath until eof close file tRemindersPath put it into gReminderData else open file tRemindersPath write "no entries yet" to file tRemindersPath close file tRemindersPath put "no entries yet" into gReminderData end if end readdata
注意
这两个函数正在使用 LiveCode 直接读取和写入文本文件的能力。请注意,
specialFolderPath
正在被用来帮助确定文件将保存的位置。即使在桌面机器上进行测试,这也同样有效。LiveCode 字典显示了所有特殊文件夹路径的完整列表,包括许多不适用于移动应用的情况。 -
你可以将以下
showdata
函数放入主卡片脚本中,但将其放在栈级别可以使其靠近与之相关的其他函数。现在就输入它:on showdata global gReminderData go card "home" put empty into field "reminders" put gReminderData into field "data" if gReminderData = "no entries yet" then exit showdata end if set the itemdelimiter to tab put 1 into tLineNumber repeat with a = 1 to the number of lines in gReminderData put line a of gReminderData into tEntry if item 1 of tEntry = "Reminder" then put item 2 of tEntry into tTitle put item 3 of tEntry into tDescription put item 4 of tEntry into tNotificationTime convert tNotificationTime from seconds to abbreviated time and long date put item 5 of tEntry into tLocationName put tTitle & ":" && tDescription && tNotificationTime && tLocationName into line tLineNumber of field "reminders" add 1 to tLineNumber end if end repeat end showdata
注意
如果你还记得之前的示例文本文件,
showdata
函数会取每一行,并将制表符分隔的项拆分成信息块以呈现给用户。一个巧妙的技巧是将通知时间,即一个长秒数,转换为可读形式,显示通知的日期和时间。data
字段用于显示已保存的原始数据。在最终应用程序中,你不会显示这个,但检查提醒信息是否正确是很有用的。 -
Stack 脚本中的最后几个函数用于设置通知本身:
on clearnotifiers mobileCancelAllLocalNotifications end clearnotifiers on setupnotifiers global gReminderData if gReminderData = "no entries yet" then exit setupnotifiers set the itemdelimiter to tab repeat with a = 1 to the number of lines in gReminderData put line a of gReminderData into tEntryDetails if item 1 of tEntryDetails = "Reminder" then put item 2 of tEntryDetails && "-" && item 3 of tEntryDetails into alertBody put "OK" into alertButtonMessage put tEntryDetails into alertPayload put item 4 of tEntryDetails into alertTime put item 6 of tEntryDetails into playSound mobileCreateLocalNotification alertBody, alertButtonMessage, alertPayload, alertTime, playSound end if end repeat end setupnotifiers on localNotificationReceived pMsg answer "Local Notification:" && pMsg end localNotificationReceived
注意
许多使用通知的移动应用永远不会清除它们。一般来说,可能不需要清除。一旦它们过去,它们就会永远消失!好吧,并不总是这样。有时,你会在通知到来之前进入一个应用,然后完成任务,但随后会因你已完成的任务而受到通知的打扰!在我们的应用中,我们会清除所有到期的通知,并重新创建整个列表。这样,你删除的任何内容都不会在以后回来困扰你。为了帮助调试,
alertPayload
会被填充整个提醒条目,并在通知到来时显示给你。
刚才发生了什么?
除了让你的手指得到很好的预热外,你还输入了所有读取和写入提醒数据以及创建和接收通知消息的函数。
主页卡片脚本
我们不会在卡片级别中放入任何脚本;它们可以仅位于各种按钮内部。从第一张卡片上的按钮开始。
行动时间 - 使主页卡片按钮工作
按位置排序按钮的脚本相当有特色。你应该期待那个!首先,我们将从按时间排序按钮开始:
-
编辑第一张卡片上按时间排序按钮的脚本。
-
输入以下简短的处理器:
on mouseUp global gReminderData set the itemdelimiter to tab sort gReminderData numeric by item 4 of each showdata writedata end mouseUp
注意
LiveCode 的排序命令功能强大,在前面的例子中,它是根据通知秒数值对提醒列表进行排序。一旦行排序完成,列表就会为用户重新创建,并且文本文件将被重写。
-
在心理上做好准备,然后编辑按位置排序按钮的脚本。
-
输入以下所有代码行:
on mouseUp global gReminderData mobileStartTrackingSensor "location", true put mobileSensorReading("location", false) into tLocation mobileStopTrackingSensor "location" set the itemdelimiter to comma put item 1 of tLocation into tLat put item 2 of tLocation into tLong set the itemdelimiter to tab sort gReminderData numeric by getdistance(tLat,tLong,item 5 of each) showdata writedata end mouseUp function getdistance pLat,pLong,pLocName if pLocName is empty then return 1000000 global gReminderData put empty into tLat put empty into tLong repeat with a = 1 to the number of lines in gReminderData if item 1 of tEntryDetails = "Location" then if item 2 of tEntryDetails = pLocName then put item 3 of tEntryDetails into tLat put item 4 of tEntryDetails into tLong end if end if end repeat if tLat is empty then return 1000000000 return distance(tLat,tLong,pLat,pLong) end getdistance function distance lat1,lon1,lat2,lon2 put 6371 into r put toRad((lat2-lat1)) into dLat put toRad((lon2-lon1)) into dLon put toRad(lat1) into lat1 put toRad(lat2) into lat2 put sin(dLat/2) * sin(dLat/2) + sin(dLon/2)*sin(dLon/2) * cos(lat1)*cos(lat2) into a put 2*atan2(sqrt(a),sqrt(1-a)) into c put r*c into d return d end distance function toRad pAngle return pAngle/180*PI end toRad
注意
mouseUp
处理器的第一部分只是获取你的当前位置。distance
和toRad
函数是我们之前看过的相同函数。魔法在于排序行使用一个函数来确定排序顺序。通过将你与每个提醒关联的位置传递给getdistance
函数,可以遍历位置列表以找到匹配项,然后使用该位置的纬度和经度来测量与当前位置的距离。这个距离随后被排序命令用来决定行的顺序。 -
为了短暂的放松,编辑创建提醒…按钮的脚本,并设置为以下内容:
on mouseUp go to card "reminder" end mouseUp
-
同样,将创建位置…按钮的脚本设置为以下内容:
on mouseUp go to card "location" end mouseUp
-
对于这张卡片的最后一个脚本,编辑删除位置或提醒按钮的脚本,并输入以下内容:
on mouseUp global gReminderData mobilePick gReminderData,1,"checkmark","cancelDone","picker" put the result into tItemsToDelete if tItemsToDelete = "0" then exit mouseUp set the itemdelimiter to comma repeat with a = the number of items in tItemsToDelete down to 1 delete line (item a of tItemsToDelete) of gReminderData end repeat if gReminderData is empty then put "no entries yet" into gReminderData showdata writedata end mouseUp
注意
删除处理程序使用mobilePick
和一组特定的参数。一个有趣的参数是checkmark
。请求这种类型的选择器会在 iPad 或 Android 上显示带有复选框的列表。这将使您能够一次性选择多个条目进行删除。因此,重复循环会遍历您选择的每个项目。
发生了什么?
如果一切顺利,您现在应该已经理解了按位置排序的功能!至少您可以看到,如果所有这些代码都放在一个地方,Stack 脚本会多么困难。让我们继续到下一张卡片…
创建位置卡片
接下来,我们将创建当用户在第一张卡片上触摸创建一个位置…按钮时显示的卡片。
行动时间 – 使位置卡片生效
位置卡片中有三个字段,用于纬度、经度和位置的标题。用户可以手动输入详细信息,但如果他们恰好在相关位置,那里有一个按钮可以抓取位置并自动填写数字。以下步骤将指导您使位置卡片生效:
-
编辑设置为当前位置按钮的脚本,并输入以下代码行:
on mouseUp mobileStartTrackingSensor "location", true put mobileSensorReading("location", false) into tLocation mobileStopTrackingSensor "location" set the itemdelimiter to comma if the number of items in tLocation = 3 then put item 1 of tLocation into field "latitude" put item 2 of tLocation into field "longitude" end if end mouseUp
-
这里没有什么太复杂的;我们只是捕获了位置,并将纬度和经度条目存储在两个字段中。
-
编辑取消按钮的脚本,并将其更改为以下简单的脚本:
on mouseUp go to card "home" end mouseUp
-
对于这张卡片最后的条目,编辑添加位置按钮的脚本,并输入以下代码:
on mouseUp global gReminderData if field "location name" is empty then answer "Please enter a name for this location." exit mouseUp end if if field "latitude" is empty or field "longitude" is empty then answer "Please enter location values, or press the 'Set to Current Location' button." exit mouseUp end if put "Location" & tab & field "location name" & tab & field "latitude" & tab & field "longitude" into tLocationDetails if gReminderData = "no entries yet" then put tLocationDetails into gReminderData else put return & tLocationDetails after gReminderData end if go to card "home" showdata writedata end mouseUp
大多数处理程序只是检查用户是否输入了所需的信息。
发生了什么?
这里发生的事情比第一张卡片上发生的事情要少得多!然而,它同样重要。现在,我们有一种方法可以让用户为创建的提醒设置一个位置。这就是我们现在要去的方向…
提醒输入表单
最后这张卡片本质上是一个输入表单;我们只想询问用户提醒是为了什么。尽管如此,它也有一些棘手的地方和一两个较长的函数来处理这些问题。
行动时间 – 输入提醒信息
提醒卡片很好地利用了选择器。用户几乎不需要输入,因为他们会从我们提供的列表中选择一个条目,所以信息中不太可能出现任何错误!按照以下步骤输入提醒的信息:
-
编辑设置相关位置按钮的脚本,并输入以下代码行:
on mouseUp global gReminderData put empty into tLocations set the itemdelimiter to tab put 1 into tLineNumber repeat with a = 1 to the number of lines in gReminderData if item 1 of line a of gReminderData = "Location" then put item 2 to 4 of line a of gReminderData into line tLineNumber of tLocations add 1 to tLineNumber end if end repeat if tLocations is empty then answer "You need to add a location." else mobilePick tLocations,1 put the result into tChosenLocation if tChosenLocation >0 then put item 1 of line tChosenLocation of tLocations into field "location field" end if end if end mouseUp
注意
我们将提醒数据中每行的第一个单词设置为位置或提醒。这里是我们可以利用的一个地方。一旦我们提取出“位置”行,在选择器中呈现它们就很容易了。
-
编辑设置日期按钮的脚本,并将其更改为以下易于理解的脚本:
on mouseUp mobilePickDate "date" put the result into tDate convert tDate to seconds put tDate into field "date field" end mouseUp
-
将设置时间按钮的脚本设置为以下内容,这几乎是一个完全相同的脚本:
on mouseUp mobilePickDate "time" put the result into tTime convert tTime to seconds put tTime into field "time field" end mouseUp
-
取消按钮的脚本与这里给出的位置卡片上的脚本相同:
on mouseUp go to card "home" end mouseUp
-
最后,但同样重要的是,添加提醒按钮的脚本做了所有艰苦的工作:
on mouseUp global gReminderData if field "title" is empty or field "description" is empty then answer "Please enter both a title and a description." exit mouseUp end if put "false" into tDoAlert if the hilite of button "Play Alert Sound" then put "true" into tDoAlert put field "date field" into tDateValue put field "time field" into tTimeValue convert tTimeValue from seconds to short date convert tTimeValue to seconds put field "time field" - tTimeValue into tTimeValue add tTimeValue to tDateValue put "Reminder" & tab & field "title" & tab & field "description" into tReminderDetails put tReminderDetails & tab & tDateValue & tab & field "location field" & tab into tReminderDetails put tReminderDetails & tab & tDoAlert into tReminderDetails if gReminderData = "no entries yet" then put tReminderDetails into gReminderData else put return & tReminderDetails after gReminderData end if go to card "home" showdata writedata end mouseUp
注意
上述脚本的大部分只是将不同的信息片段组合成一个带有制表符分隔的提醒条目。然而,其中也有一些有趣的算术操作。在本章的开头,我们探讨了 Unix 时间与实际时间在每年 0.6 秒的速率上的差异。如果你想设置五年后的早上 8 点的提醒,你不能直接使用设置时间按钮给出的值,因为那是指今天的早上 8 点。你也不能使用设置日期给出的值,因为那将是午夜。所以,通过将时间值转换为短日期格式,然后再转换回秒格式,你可以找出当前天午夜时的 Unix 时间。从设置时间给出的值中减去这个值,你就可以知道自午夜以来经过的秒数,无论 Unix 时间落后多少。将这个值加到设置日期给出的值上,将给出通知发生的精确 Unix 时间(秒)。在 iOS 中,有一个选择器类型允许你同时设置日期和时间,但由于 Android 上没有这个功能,我们使用了适用于两者的方法。
刚才发生了什么?
呼吁!我们终于到达了终点!尝试在你的设备上运行应用。如果你的手指不太麻木的话!说实话,你可以打赌它第一次可能不会工作,但如果它足够好,能够在第一张卡片的数据字段中显示原始文本,那么希望你能追踪到代码中的任何错误。你还可以在你的电脑上的堆栈中输入一些测试数据,至少测试不需要特定设备功能的函数。
勇敢的尝试者——流畅的过渡
真的,如果你已经成功通过并输入了所有这些代码,使得应用开始工作,那么你已经是一个英雄了!然而,请阅读 iOS 和 Android 发布说明中关于 LiveCode 的视觉效果支持的部分。检查你是否可以在进入和离开不同卡片时实现一些典型的移动操作系统过渡效果。
摘要
这一章比预期的要激动人心得多!提醒应用绝对没有愤怒的小鸟那么令人印象深刻,但利用移动设备的地理位置功能使其变得稍微新颖一些。在这个过程中,我们介绍了读取和写入特殊文档文件夹中的数据以及使用选择器来处理简单的列表、日期和时间的方法。我们还展示了如何读取设备的当前位置以及如何设置本地通知事件。
在最好的情况下,你可以在几小时或几天内制作出一个移动应用,但在你能够将应用提交到各个应用商店之前,还有很多事情要做。这听起来像是下一章的好主题!
第七章 部署到您的设备
不要把所有东西都留给自己!
LiveCode 等工具可以完全用于个人生产力应用,并且它每天可以节省大量时间,从而完全值得。然而,为什么不让大家都能从您的创作中受益呢!
到目前为止,我们已经创建了几个小型的测试平台应用和一些内容较为丰富的应用。然而,在所有情况下,我们只是测试了位于模拟器或个人设备中的应用程序。现在是时候将这个应用推广给更多人进行初步的 beta 测试,以便我们随后可以将其上传到不同的应用商店。
在本章中,我们将:
-
检查所有与创建移动应用程序过程相关的独立应用程序设置选项
-
创建应用的构建版本以便发送给 beta 测试者
-
测试服务替代方案
-
构建应用的最终分发版本
-
回顾如何将应用上传到 iOS 应用商店、Google Play、Amazon 应用商店和三星应用商店
注意
在为 App Store 创建 iOS 应用时,有一些阶段应该在 Mac 上执行;这里描述的所有 iOS 步骤都应该使用 Mac 来遵循。Android 步骤可以应用于 Mac 或 Windows。请注意,本章更像是参考而不是实际操作指南。当您有一个几乎完成并准备提交给应用商店的应用程序,如果在任何点上遇到困难,希望您能回忆起在本章中某处阅读过关于该问题的内容!
独立应用程序设置
我们现在已经调整了设置几次,但我们只做了测试应用所需的最小改动。这里有很多选项需要在您的应用准备在应用商店销售之前填写。我们将简要介绍其他独立应用程序部分,然后深入探讨 Android 和 iOS 部分。
常规部分
独立设置中的常规部分主要用于控制要包含在桌面独立应用程序中的 LiveCode 功能。这些选项不能应用于移动应用程序,但在常规部分中,您可以设置应用程序文件的名称和构建文件夹:
堆栈部分
堆栈部分将显示您项目中已包含的堆栈列表。这当然包括当前的 Mainstack 以及您可能之前使用过的插件添加的堆栈。如您所见,所有选项都是灰色的。
复制文件部分
复制文件部分用于添加应用需要使用的额外文件和文件夹。这些是只读文件;如果您需要可更改的文件,您仍然可以包含这些文件,然后将文件的副本写入特殊的Documents
文件夹。以下是包含图像和声音文件夹的对话框外观。这些文件夹与 LC 应用所在的文件夹相同:
iOS 部分
在制作 iOS 和 Android 应用时,Mac、Windows、Linux、Web 和 错误报告 部分不使用,所以现在,我们将逐步仔细查看 iOS 部分…
构建部分
构建部分 设置确定应用将在哪些 iOS 设备上运行以及应使用哪个最低 iOS 版本。在决定选择什么时,有些事情很明显,而有些则不那么明显。如果你制作的应用确实需要一个大的工作区域,那么在 iPod 或 iPhone 屏幕上可能不太成功。如果它是一个针对手持设备使用的轻量级工具,可能你不需要有一个 iPad 版本。你可以从本部分选择 iPod、iPhone 和 iPad,或者只选择 iPod 和 iPhone,甚至只选择 iPad。
你选择的最低 iOS 版本可能取决于你之前使用的特定功能。你不想用户购买你的应用后,发现某些功能在较旧的 iOS 版本下无法正常工作。你可能需要设置并保留一些设备用于测试,以便在这些设备上使用旧版本的操作系统,从而确保你的设置是正确的。此外,Xcode 允许你下载各种版本的模拟器,在 LiveCode 中,你可以选择特定的版本进行测试。
你现在可以始终将这些选项保留在较低值,在你听到你的测试者如何与该应用互动后,再做出决定。
这里是设置中的 构建部分 以及你可以选择的菜单:
基本应用设置
我们已经使用了一些这些设置几次。以下是完整的选项集:
-
显示名称:这是将在实际设备上的图标下显示的名称。
-
版本:这是将在应用的 iTunes 描述中出现的版本号。
-
内部应用 ID:这是在开发或分发配置文件时可以在 iOS 开发者门户中使用的应用 ID。
-
配置文件:这是与该应用匹配的配置文件。
-
外部命令文件:这是一组你可能已在应用中使用过的可选外部命令文件。
你应该尝试不同的显示名称,看看它在不同设备上的外观如何。iOS 会截断名称长度,在文本中间放置省略号,名称长度有一个限制。对于 iPhone,这个限制大约是 11 或 12 个字符。
确保你提交的应用更新版本号晚于现有应用的版本号很重要。从 1.0.0 开始是有意义的;只是记得在更新时增加数字。如果你忘记了,你会在上传到 App Store 的过程中发现失败!一般来说,应用商店要求更新版本晚于被替换的版本。
在开发目的上,您可以使用包含通配符的内部应用程序 ID 的配置文件。当您提交应用程序到 iOS 应用商店时,请确保配置文件是分发配置文件,并且它使用的 App ID 与内部 App ID完全匹配。同时,请确保 ID 与商店中的任何其他应用程序都不同。请注意,ID,如您的开发者账户页面所示,在其开头将显示额外的数字,例如,31415926.com.yourname.yourappname
。匹配的内部 App ID将是com.yourname.yourappname
。
在这个示例截图中,选择了开发配置文件,并且没有使用外部命令:
图标
您可以为 iOS 和 iTunes 要求的每种设备类型选择不同的图标。图标部分很简单;您点击…按钮,然后从您的文件系统中选择文件。LiveCode 可以为您创建各种尺寸的图标,但这并不是一个选项!就其价值而言,您可能有自己的理由为每种情况显示不同的图标。例如,您可以为 Retina 显示屏创建一个图标,其中包含比非 Retina 显示屏更多的细节。既然您没有选择,那就享受这种灵活性带来的便利吧!
注意以下截图中的预渲染图标复选框。在这里,您可以选择创建一个与设备上显示的图标完全相同的图标。您还可以创建一个没有阴影的方形图标,让系统通过高亮效果使其看起来像按钮。看看您自己的设备上的各种应用;您会发现有些人乐于使用苹果的斜面高亮外观,而有些人则更喜欢自己动手。预渲染图标功能允许您自己动手。在这个截图中,您可以看到所有已选择的设备类型的图标,包括 iPad Retina,并且它们是预渲染的:
在这种情况下,icons/
文件夹与应用程序在同一文件夹中,因此您不需要包含完整路径。icons/
条目也包含在复制文件部分中。
苹果 iOS 7+图标和图像尺寸的良好参考资料可在以下网址找到:
developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html
此图表不包括旧尺寸 57 和 72,这些尺寸适用于较旧的 iPhone 和 iPad。
图标工具
有许多工具可以帮助您创建 Mac 应用商店中所有可用的图标尺寸。在我最后一次检查时,搜索icon ios
的结果大约有 40 个图标。我使用的一个免费工具是Icon Set Creator,它可在以下网址找到
itunes.apple.com/us/app/icon-set-creator/id939343785?mt=12
启动画面
从第一代 iPhone 开始,iOS 就有在用户触摸应用图标时立即加载并显示启动画面的能力。这让他们在应用加载时有所观看。那些日子里只需要一个默认图像和一个名为Default.png
的名称。当 iPad 出现时,就需要更多的启动画面。至少,您需要一个更高分辨率的默认图像,但您还需要为横向设置自定义图像,根据主页按钮是在左侧还是右侧,可能需要不同的横向图像。
LiveCode 不提供访问该级别的灵活性,但一个应用需要两种变体有不同的横向是非常罕见的;通常只需要一个即可。对于颠倒的纵向变体,常规的默认纵向图像也可以使用。
Retina 显示屏有自己设置启动画面的条目,并且按照惯例,这些文件名将包含@2x
。
启动画面的哪些选项被启用取决于下一节中描述的朝向选项。在此屏幕截图中,横向选项被灰色显示,因为应用被设置为纵向。在此处,还选定了正确的尺寸横向图像文件,供您参考:
您可能会注意到这里没有 iPhone 的纵向或横向选项。这是因为Default.png
同时用于这两种情况。如果您的应用仅支持横向,那么请设计为横向的启动画面,但将图像顺时针旋转 90 度以创建 320 x 480 或 640 x 960 的Default.png
或Default@2x.png
图像。列表中的一个重要条目是用于 iPhone 5 的4 英寸 iPhone条目。这里不使用Default.png
文件名,因为只要不包含空格,图像文件名可以是任何名称。
朝向选项
如前所述,您可以为您的应用指定支持的朝向。如果应用仅用于 iPod 和 iPhone,那么您只能设置初始朝向。选项包括纵向、颠倒纵向、横向左和横向右。如果应用在 iPad 上使用,那么您还可以设置应用使用时支持的朝向。您所做的选择将影响哪些图标可以被导入。所有朝向都通过一个下拉菜单和四个复选框来设置:
自定义 URL 方案
有时候在使用 iOS 设备时,你会在网页中触摸一个 URL,突然你会发现自己在邮件中或查看 App Store 中的页面。这是通过自定义 URL 方案实现的。在 App Store 的情况下,链接以itms-apps://
开头,iOS 知道该链接应该在 App Store 应用中打开。你可以用你的应用做同样的事情。通过设置类似的自定义字符串,你可以让 iOS 在用户触摸 URL 中以相同字符串开头的链接时打开你的应用。更多信息可以在lessons.runrev.com/m/4069/l/58672-using-custom-url-schemes
的教程中找到。
字符串的值通过一个简单的文本输入字段输入,如下所示:
要求和限制
之前,我们讨论了如何设置设备、处理器指令集和 iOS 版本,这是确保用户能够使用你应用中的功能的一种方法。要求和限制选项让你可以非常详细地指定你的设备应该具备的能力。至少,如果你有一个涉及拍照的应用,那么设备中有一个摄像头是必要的!如果是一个视频聊天应用,那么设备中有一个前置摄像头是有意义的。我们在上一章中制作的通知应用应该选择位置服务选项,以确保按距离排序的功能正常工作。以下是需要设置的要求和限制的完整列表:
状态栏
iOS 设置中的最后一个选项控制状态栏是否可见以及它应该具有默认状态栏外观还是黑色外观。对于黑色外观,你可以设置它应该是完全不透明的还是半透明的:
Android
如你所见,需要为 Android 设置的选择项比 iOS 少。这并不是因为 Android 更简单,而是因为 LiveCode 几乎暴露了 iOS 的所有可能设置,包括你很可能不需要的大量设置。iOS 还有 Android 中没有的启动画面变化。
在 Android 世界中,有一些设置是你必须设置的,特别是权限设置。iOS 确实会要求用户在使用某些功能时给予权限,但不是在你应用调用该功能时。你可能见过要求“Fancy App 想要知道你的位置”的对话框。另一方面,Android 会在应用安装时请求使用这些功能的权限。
让我们看看 Android 的选项...
基本应用设置
在 Android OS 中,一些 iOS 选项被赋予了不同的名称。而不是显示名称,使用标签,内部应用 ID被称为标识符,并且没有配置文件,但在 Android 中有一个签名密钥。本质上,它们与 iOS 中的选项相同。
图标被设置为基本设置的一部分,因为只需要一个图标,所以我们不需要一组选项。对于这个图标,您需要选择一个 512 x 512 像素大小的图像版本,LiveCode 会为您生成其他尺寸。
Android 应用没有像 iOS 那样的启动画面,但 LiveCode 可以提供一个启动画面,它将在应用加载后用户看到的第一个屏幕上显示。
您可以选择应用安装的位置,有仅内部存储、允许外部存储和优先外部存储的选项。这里所指的外部存储是指大多数 Android 设备都有的 SD 内存。Android 用户要么不在乎应用安装在哪里,要么非常执着于将其存储在 SD 内存中!您可以选择允许外部存储并预期很多人会这样做,或者您可以选择优先外部存储,知道只有少数人会更改选项以强制安装到内部存储。总的来说,使用优先外部存储设置可以减少对人们的困扰。
在 Android 中,应用内购买和推送通知的处理方式与 iOS 不同。如果您想使用应用内购买,请查看 RunRev 在线课程以及developer.android.com
上的信息。苹果、谷歌、亚马逊和三星的课程位于lessons.runrev.com/m/4069
。
关于应用内计费的开发者信息可以在以下链接找到:
developer.android.com/guide/market/billing/billing_overview.html
与 iOS 一样,Android OS 可以接收外部命令,并且也有自定义 URL 方案。iOS 中没有的一个功能是能够设置用于任务栏的图标。
下面是如何展示基本应用设置选项的:
需求和限制
在这个选项集中,您可以设置最低 Android 操作系统版本,并设置所需的硬件功能。在 iOS 中,单选按钮的列有不同的名称。而不是声明一个功能是必需的或禁止的,按钮会说明该功能是必需的还是使用的。这成为 Android 用户能够阅读的信息,并且可能在他们是否选择购买您的应用中发挥作用。因此,尽量选择适用于您应用的任何选项。
应用权限
当 iOS 应用使用某些功能,例如你的位置时,首次使用该功能时会弹出一个警告对话框。在 Android 上,任何此类功能都会在应用安装过程中列出,并且用户一次性授予所有功能的权限。
这里是你可以选择的权限列表:
用户界面选项
用户 界面 选项 执行与 iOS 中的方向和状态栏选项相同的功能。如果你正在提交一个横屏的 iPad 应用,你必须支持两种横屏变体。Android 应用商店没有这样的要求,因此选项要简单得多。你只需选择初始方向应该是 纵向 还是 横向,以及状态栏应该是 可见 还是 隐藏:
为 Beta 测试者构建应用
你可能在整个开发过程中已经将测试版本发送给了朋友和同事,但即使你没有,随着你接近必须上传应用到应用商店的时间,这样做变得更加重要。Beta 测试者可以告诉你关于技术和非技术问题。信用部分有错别字吗?图标看起来好吗?安装体验中有任何奇怪的地方吗?当然,应用在众多设备和操作系统上是否按预期工作?
将应用制作并发送给测试者的过程在 Android 和 iOS 上有所不同。实际上,在 Android 上做这件事非常简单!让我们首先看看 Android 的做法。
将 Android 应用发送给测试者
当点击 Android 的 另存为独立应用程序… 选项时,你会创建一个 APK 文件。你可以通过电子邮件将此文件发送给你的测试者,他们可以在他们的设备上执行所谓的“侧载”操作。在 第二章 中,我们看到了如何连接 Android 设备进行测试可能会多么棘手,这可能会超出一些测试者的技术能力。
幸运的是,有一个更简单的方法来做这件事。将 APK 文件上传到某个地方。它可以是 Dropbox 共享位置、Google Drive,或者可能是你办公室的服务器。无论你需要做什么,只要你能得到一个包含文件链接的 URL。现在,将这个 URL 通过电子邮件发送给你的测试者,确保他们可以在他们的设备上阅读。然后,只需点击电子邮件中的链接一次,你就可以开始下载和安装你的应用。
在 Android 设备设置中有一个开发部分,测试者可能需要访问以启用允许以这种方式安装应用的特性,但进行此更改非常简单。
准备 iOS 应用以便在他人设备上运行
对于 iOS 来说,事情并不那么简单!首先,您需要为每位测试者的设备添加唯一的设备 ID(UDID)到您的 iOS 开发者账户中。您的测试者可以通过将设备连接到他们的电脑并在 iTunes 中查看其信息来获取该数字。当您查看摘要部分时,您将看到相应设备的序列号。点击该数字将使其变为一个更长的数字,即所需的 UDID。一旦该数字显示出来,您可以使用键盘快捷键将其复制到剪贴板(Mac 上的command + C,Windows 上的Ctrl + C)。让您的测试者执行这些操作,然后将数字粘贴到发给您的电子邮件中。您必须确保获取正确的数字,因为它将消耗您 iOS 开发者账户中分配的 100 个设备中的一个。
前往developer.apple.com/account/ios/device/deviceList.action
以将设备添加到您的账户中。点击您姓名下方位置的正下方的+按钮,您就可以将设备添加到您的账户中:
接下来,转到配置文件部分,创建一个新的开发配置文件或选择一个现有的配置文件并点击编辑按钮。在选择了 App ID 和签名证书后,您将看到与您的账户关联的设备列表。您可以选择任何组合的设备与该配置文件一起使用。在这个屏幕截图中,您会看到测试设备池非常短:
点击生成按钮,几分钟后,您将能够点击下载按钮来下载文件。
下载新的配置文件并将其添加到 Xcode 中(双击下载的文件)。在 LiveCode 中打开您的应用的主栈,转到独立应用程序设置…/iOS,并确保从配置文件菜单中选择配置文件。再次点击另存为独立应用程序…选项,以确保新设备被应用所识别。
到现在为止,您将有一个“APP”文件,这是 iOS 对 Android 的“APK”文件的等价物。与 Android 一样,您可以随附此文件和配置文件通过电子邮件发送给您的测试者,并让测试者将它们“侧载”到他们的设备上。在这种情况下,这并不是一个很难的任务,因为测试者可以使用 iTunes 来完成同样的操作。如果您选择这条路,让您的测试者将“APP”和配置文件拖放到 iTunes 的库中,连接设备,查看应用标签页,确保新应用被选中,然后执行同步。然而,您可以大大简化用户的使用,就像 Android 用户一样简单。
使用 iOS 的"over the air"安装程序
自从 iOS 4.0 以来,我们就可以从网页中的链接安装应用程序了。不过,创建使其工作的文件结构有点棘手,但幸运的是,至少有几种工具你可以购买来简化这个过程。
AirLaunch
HyperActive Software 开发了一个 LiveCode 插件,可以将你的"APP"文件转换为"over the air"安装所需的文件结构。你只需要在一个对话框中填写所需的信息:
选择"APP"文件后,你只需要输入文件夹在线时的 URL,然后点击创建文件按钮。在线应用程序的 URL 链接将在窗口底部确认。点击 URL 以复制它,然后通过电子邮件发送给你的测试人员。当他们在自己的设备上访问网页时,将有一个单独的链接可以触摸,iOS 将提示你批准安装应用程序。如果你查看主页上的下一个可用位置,你会看到它正在安装,或者如果你不够快,它已经安装了。
注意
有关 AirLaunch 的更多信息,请参阅:
www.hyperactivesw.com/airlaunch/index.html
注意,苹果要求使用一个安全的服务器才能实现这一功能,并且 URL 必须以 HTTPS 开头。最简单的来源是使用 Dropbox 公共文件夹,尽管如果你是在 2012 年 10 月 4 日之后注册的 Dropbox,你需要将其设置为安全。有关更多信息,请参阅 AirLaunch 常见问题解答:
hyperactivesw.com/airlaunch/airlaunchtips.html
提示
AirLaunch 开发中的工作流程
AirLaunch 可以作为 LiveCode 插件安装,并在创建应用程序的独立版本后立即运行。你可以在 iOS 设备上保存安装网页,并点击它以启动安装程序。这种方法在开发过程中测试应用程序比连接电缆并将应用程序拖入 Xcode 要容易得多。
BetaBuilder
你可以在 Mac App Store 中找到 BetaBuilder:
itunes.apple.com/us/app/betabuilder-for-ios-apps/id415348946?mt=12
它并不是专门为 LiveCode 设计的,它支持"IPA"文件而不是"APP"文件。将 LiveCode APP 文件转换为 IPA 文件的一个简单方法是将 APP 文件拖入 iTunes,并右键单击库中的应用程序选择"显示在 Finder 中"。这将显示可以拖入 BetaBuilder 窗口的 IPA 文件。
这个过程与 AirLaunch 的过程非常相似,其中你选择要使用的文件,输入在线文件夹的 URL,程序为你生成文件。同样,这一切都在一个对话框窗口中完成:
这两款产品创建的文件与以下 Dropbox 公共文件夹中所示类似:
这两款产品都让测试者的生活变得简单。AirLaunch 作为一个插件,可以在 LiveCode 中运行,而 LiveCode 你很可能已经打开了,并且可以直接与 LiveCode 创建的 APP 文件进行工作。BetaBuilder 是一个独立的 Mac 应用程序,需要你使用其他 Mac 应用程序将文件传输到你的服务器。AirTouch 内置了 FTP,以简化你的工作流程。
BetaBuilder 的主要优势是它极其便宜!它还生成一个比 AirLaunch 更详细的信息网页,AirLaunch 只显示一个带有应用名称的简单链接。然而,AirLaunch 允许你导出模板并编辑或将其集成到你的网站上。
TestFlight
在我撰写这本书的第一版时,有一个名为 TestFlight 的服务,其工作方式类似于 AirLaunch 和 Beta Builder。2014 年,苹果收购了 TestFlight 并将其与用于向苹果 App Store 提交应用的iTunes Connect(iTC)合并。TestFlight 不仅仅是你向几个测试者发送个人应用所需的东西,但在处理可能发送给多达 1000 个测试者的应用时是必需的。一个重大变化是,你还需要一个分发配置文件和证书才能开始本章中进一步描述的提交过程。
TestFlight 有两个测试级别:内部和外部。内部测试是针对你的开发团队成员的。你可以使用 iTC 的用户和角色部分添加最多 25 个内部测试者,并分配给他们技术角色。他们将收到一封电子邮件邀请,并需要激活一个 iTC 账户。当你开始测试你的应用时,他们会收到另一封电子邮件通知,并需要在运行 iOS 8 或更高版本的设备上下载 TestFlight 应用。然后 TestFlight 应用会安装你的应用以进行测试。测试只持续 30 天,除非你更新它并提交新版本。TestFlight 应用还可以用于错误报告和反馈。
外部测试与此类似,但需要在测试开始前进行 Beta App Review,并必须遵守完整的 App Store Review Guidelines。对于包含重大更改的新版本的应用,需要进行审查。一次可以测试多达 10 个应用,无论是内部还是外部。你可以通过提供他们的电子邮件地址列表并检查你是否得到了他们的批准来添加最多 1000 个外部测试者。发布后,测试将以与内部测试者相同的方式进行。在撰写这本书的时候,一个测试者不能同时出现在内部和外部列表中。有关更多信息,请参阅developer.apple.com/testflight/
。
注意
缺少推送通知权限
在 2015 年初,当您向 iTC 提交应用程序时,您会收到这封电子邮件警告信息:“您的应用程序似乎包含用于注册 Apple 推送通知服务的 API,但应用程序签名的权限不包括 "aps-environment" 权限。”这是 LC 中的一个问题,不会影响任何东西。Apple 的推送通知服务是内置在 LC 引擎中的,如果不用它,LC 不会费心将其删除。这在 RunRev 质量系统中的错误报告 10979 中有记录。quality.runrev.com/process_bug.cgi
。
使用“空中”安装程序进行 Android 安装
在使用 Android 模拟器或直接连接进行测试时,应该足以学习 LiveCode 开发,但现实世界要复杂得多。在过去的几年里,出现了多种测试替代方案,以帮助您在其他 Android 设备上测试您的应用程序。由于有众多 Android 设备,这确实是必需的。在最后一次统计中,Google Play 商店列出了 8614 个,而且现在当您阅读这篇文章时,肯定还有更多被列出。在亚马逊、三星和其他地方也有 Android 操作系统的变体。希望通过 Google 测试资源进行测试能够满足您的需求。
Google 测试
Google 也在他们的 Google Play 商店内置了测试功能。与 Apple 的 iTC 和 TestFlight 类似;对于 Google 来说,您需要准备您的商店列表并上传您的 APK,就像您发布它时一样。为了向测试者分发,您需要创建并选择一个测试者可以加入的 Google Group 或 Google+ Community。Google 有 alpha 和 beta 测试,这与 Apple 的内部和外部测试类似。测试通知电子邮件会发送给测试者,其中包含 Google Play 测试部分的链接。因为您的测试者不能在 Google Play 上为 alpha/beta 应用程序留下公开评论,所以让它们知道在哪里可以提供反馈(电子邮件地址、网站等)是个好主意。更多详细信息可以在以下找到:
support.google.com/googleplay/android-developer/answer/3131213?hl=en
亚马逊测试
亚马逊有一个名为 Live App Testing 的工具,允许开发者通过亚马逊应用商店进行应用程序的公测。开发者可以通过电子邮件邀请最多 500 名特定用户测试应用程序。除此之外,A/B 测试服务允许在应用程序内进行实验,尝试与不同用户群体的不同 UI 交互。据说它还支持 iOS,但需要开发 LiveCode 外部特定的 API。
更多信息请参考:
三星测试
为了方便测试应用,三星开发了远程测试实验室(RTL)设施。这些实验室包含真实设备,允许开发者上传和测试他们的应用。要使用这些设备,你需要下载并运行一个 Java 小程序,该小程序将你的 APK 连接到三星实验室中的实时设备,并提供一个与该设备交互的界面。这可能在将来有一些潜在的应用,但这里包括它以供可能的调查。有关三星测试的更多信息,请参阅developer.samsung.com/remotetestlab/rtlAboutRTL.action
。
小贴士
之前的测试替代方案是与 iOS 和 Android 设备制造商相关的主要替代方案。由于苹果收购了TestFlight,其他几个跨平台测试解决方案已经填补了空缺。在互联网上快速搜索显示HockeyApp、Crashlytics、Ubertesters、TestFairy和其他一些可能有潜力的解决方案。
创建应用商店提交文件
为了制作一个可以提交到应用商店的应用版本,你需要克服的最大障碍是获取一个分发证书。对于 Android 来说,这个过程更快,但确实需要在命令行中输入一些文本,如果你使用的是 Windows 而不是 Mac,那么会有一些细微的差别。iOS 的过程有很多步骤,但至少它们不涉及输入难以理解的命令。我们首先来看 Android。
查找和使用 Android Keytool 应用程序
当你添加 Java 开发工具包时,安装的一个工具是用来创建“密钥库”文件的,这是一个自签名的证书。这个工具就是用来创建你分发 Android 应用所需的证书。
在 Mac 上,你不需要寻找这个应用程序,你只需在终端中输入命令,你就能找到这个工具。在 Windows 上,你首先需要导航到 Keytool 所在文件夹。在做到这一步之前,你必须首先以管理员身份打开命令行。
在 Windows 上,CMD 应用程序位于C:\Windows\System32\
。在 Windows 资源管理器中转到该目录,右键单击文件,并选择以管理员身份运行。Keytool 应用程序将在 Java JDK 目录的 bin 文件夹中。一旦你到达命令提示符,更改目录以到达该位置,这将是类似于C:\Program Files\Java\jdkx.x.x_xx\bin\
的路径,其中jdkx.x.x_xx
部分实际上是已安装的 JDK 版本。你应该能够通过以下类似命令到达那里,其中 cd 是用于更改目录的命令:
C:\> cd \Program Files\Java\jdk1.7.0_01\bin\
在 Mac 上,你会使用位于/Application/Utilites
的终端。只需打开终端,你就能立即使用 Keytool 应用程序。
在任何情况下,您现在将输入一条相对简短的命令行,然后回答出现的各种问题。为了更好地理解正在发生的事情,请访问:
developer.android.com/guide/publishing/app-signing.html
对于我们的目的,我们只需输入正确的命令,一切应该都会顺利,即使我们不理解我们输入了什么!
这是您需要输入的行,将密钥库和别名名称更改为与您希望用于此证书的名称匹配:
keytool -genkey -v -keystore my-release-key.keystore
-alias alias_name -keyalg RSA -keysize 2048 -validity 10000
当您按下 Enter 或 Return 键时,您将开始看到一系列问题,这些问题从您希望用于密钥库的密码开始。后续问题将询问您的全名、公司、城市和国家详情。这是一组可以编码到具有独特性和足够准确信息以供用户决定是否信任证书的密钥库中的数据。
当工具完成时,您将拥有 LiveCode 所需的密钥库文件。在 Mac 上它将很容易在您的家目录中找到,而在 Windows 上则可能隐藏在 JDK bin 文件夹中。
前往 Mainstack 的独立应用程序设置的基本应用程序设置,然后从密钥条目导航到文件。一旦选择,此部分将看起来像这样:
如果您已经选择了图标、启动画面以及要求和权限,您应该能够构建一个可以上传到应用商店的 APK 文件版本。
为 iOS 创建分发证书
如前所述,获取 iOS 分发证书不需要涉及命令行输入,但涉及许多步骤。获取证书的第一站是 iOS 开发者门户,以确保您已经为这个特定的应用程序设置了一个专门的 App ID 和配置文件。
以下截图展示了为即将命名的名为EasyReminder
的应用程序获取证书和配置文件的步骤,这是我们之前制作的通知应用程序。
在门户的App IDs部分,有一个+按钮,它将新的 App ID 添加到您的账户中,并要求为该 ID 提供一个名称。在这里,您可以看到 ID 被命名为EasyReminder和一个包标识符com.gerdeen.easyreminder
。这需要与 LiveCode 中设置的内部 App ID相匹配。如果您不是多个开发团队的成员,您将不会看到以下截图中显示的 App ID 前缀:
现在有了 App ID,它可以在配置部分设置一个分发配置文件。如果您还没有创建分发证书,您将看到一个按钮告诉您创建一个。点击该按钮将向您提出一个问题,询问您想要创建哪种类型的证书:
点击继续按钮会带你去一个长描述,说明你必须如何向证书颁发机构提出请求以及如何上传 Keychain Access 生成的文件。当你遇到这种情况时,请仔细遵循以下截图所示的步骤:
在上传证书请求文件后,你将能够创建一个使用专用 App ID 和分发证书的分发配置文件。最后的条目将看起来像这样,你可以使用下载按钮来获取本地副本的配置文件:
你现在有了 LiveCode 需要的文件,但你不需要在 LiveCode 设置中选择它。相反,你双击该文件,它将使用 Xcode 自动安装。一旦它在 Xcode 中,你就可以从 LiveCode 的基本应用程序设置中的配置文件菜单中选择它:
与 Android 一样,确保添加图标、启动画面、设置要求等,你将能够保存一个准备好的 APP 文件,上传到 iOS 应用商店。
上传到应用商店
每个应用商店都会指导你如何上传新应用,并且涉及到的步骤相当多!可能需要另一本书来展示你必须浏览的所有截图。在这里展示这些截图不会非常有价值,主要是因为它们的数量庞大,而且流程会不时发生变化。例如,谷歌将他们的服务名称从 Android Market 更改为 Google Play。
每个商店要求的内容之间有一些相似之处,所以我们将看看在前往商店之前你可能需要做哪些准备。当你准备好上传时,你需要从以下页面开始为相应的应用商店进行操作:
-
iTunes Connect:
itunesconnect.apple.com
-
Google Play:
play.google.com/apps/publish/
-
Amazon Appstore:
developer.amazon.com/home.html
-
Samsung Apps:
seller.samsungapps.com/
相似之处
所有三个应用商店都会要求你描述应用的功能、评分信息、价格、支持网站或电子邮件地址以及分类信息。如果你要设置除了免费以外的价格,你必须设置一个商户账户。在苹果的情况下,你必须提供一个支持网页地址。谷歌只要求提供联系信息,而亚马逊将支持作为可选项。所有三个都要求截图,并允许你上传演示视频。
不同之处
Apple 要求提供大量信息,但这些信息分布在多个屏幕上。当你输入数据时,你需要截图和其他你尚未收集的信息。你可以 保存 你已经输入的内容,稍后再回来。确保在点击 提交审核 之前正确无误,因为 Apple 不允许在没有上传应用新版本的情况下更改信息。
实际应用文件的上传由 Xcode 集成开发工具包中的 Application Loader 工具处理。要从 Xcode 开发者工具包访问 Application Loader,请选择菜单 Xcode | 打开开发者工具 | Application Loader。你还可以按照 iTunes Connect 支持文档中所述,在你的应用程序文件夹中下载它:
itunesconnect.apple.com/docs/UsingApplicationLoader.pdf
Google 要求提供大量信息,但这些信息都在他们的开发者控制台中。有部分用于上传 APK 文件,用于完成 商店列表、定价与分发以及其他操作。如果你将价格设置为免费,请注意你不能更改它,并且它将立即永久性地被标记为免费应用。要更改它,你需要创建一个新的应用,使用新的包名并设置新应用的价格。
Amazon 要求提供的信息与 Apple 和 Google 大致相同。你可以通过简单地将其拖到他们的开发者网页上来检查你的应用是否与 Amazon 兼容。他们进行快速兼容性测试,然后在 Android Nexus 7 和他们的 Fire 手机和平板电脑上进行更多测试。你可以直接从测试结果页面开始提交你的应用,但那时你需要建立一个开发者账户并提供之前相同的信息。
Samsung Apps 是一个专为三星手机定制的应用商店。它是开发者和三星手机用户关注的焦点。不实际注册,很难了解该商店对非三星设备的工作细节。如需更多信息,请参阅www.pivoteast.com/guide-how-to-register-and-submit-apps-to-samsung-apps/
上的文章。
核心内容
提交过程几乎是开发移动应用中最有压力的部分!它让你对自己的其他阶段感到更加安心;也许那些阶段并没有那么糟糕…
希望你有一个合作伙伴,可以成为你的第二双眼睛,帮助你理解所有问题,以免错过将来会困扰你的重要信息。
摘要
我不知道你们的情况如何,但我是筋疲力尽了!移动应用开发业务可能会让人感到压倒性。即使是行政方面的事情也可能相当复杂。在本章中,我们介绍了一些不太程序化的任务,例如检查独立应用程序设置中的所有选项,通过命令行和繁琐的程序来获得应用程序认证,以及心理上准备将我们的应用程序提交到应用商店。
就利用 LiveCode 堆栈中的移动功能并将其转化为真正的移动应用而言,我们已经走到了尽头。接下来,我们将探讨一些 LiveCode 的附加组件,这些组件将使您能够使用更多的移动功能。
附录 A. 扩展 LiveCode
到目前为止的故事…
“漫长的道路”是披头士乐队发布的最后一首单曲,它也可以作为描述在移动设备上使 LiveCode 运作所需努力的书籍的好标题!iPhone 上出现应用程序后,RunRev 就在开发从 LiveCode 发布 iPhone 应用程序的方法。然后,在 2010 年 4 月,史蒂夫·乔布斯撰写了这篇臭名昭著的文章,您可以在以下链接找到:
www.apple.com/hotnews/thoughts-on-flash/
Adobe 也正在开发一种从 Flash Professional 发布 iPhone 应用的方法,但由于苹果决定不允许基于 Flash 的应用程序在 iPhone 上使用,App Store 的提交规则发生了变化,禁止开发者使用除 Xcode 之外的其他工具发布应用程序。
一些工具因为使用 Xcode 进行最终发布而继续处于灰色地带。GameSalad 和 Unity 应用程序继续发布并在 App Store 中表现良好。RunRev 试图说服苹果允许 LiveCode(当时仍被称为Runtime Revolution)作为 iPhone 的发布工具,甚至承诺只发布 iPhone 应用程序,并且不追求在 Android 上的发布。苹果坚持立场并拒绝了这一提议。
对于 Adobe 来说,这并不是世界末日,它开始着手 Android 发布。然而,RunRev 已经计划了一个围绕将应用程序发布到 iOS 的想法的会议,但那次会议不得不推迟。
在 2010 年夏天,苹果对开发者进行了一次调查,其中提到的几个问题给了像我这样的人一个机会,请求苹果允许开发者使用他们首选的开发工具,这样他们就不必被迫使用 Xcode。很难确定这是否是造成差异的原因,但 2010 年 9 月 9 日,苹果改变了其在该问题上的立场。以下是那天早上我们醒来看到的帖子:
www.apple.com/pr/library/2010/09/09Statement-by-Apple-on-App-Store-Review-Guidelines.html
Colin Holgate(本书的合著者)迅速在 Revolution 电子邮件列表上发布了一条消息,标题为“如何彻底让 Kevin 感到高兴”;“Kevin”是 RunRev 的首席执行官 Kevin Miller。它产生了预期的效果,您仍然可以阅读后续的消息:
runtime-revolution.278305.n4.nabble.com/how-to-totally-make-Kevin-s-day-td2532866.html
这让 RunRev 重新回到了正轨,实现了开发“发布到 iOS”功能的目标;那时,iPhone OS 已经更名为 iOS。推迟的会议最终在 2011 年 4 月底在圣何塞举行。到那时,RunRev 不仅使 iOS 功能运行良好,而且还发布了“发布到 Android”功能的第一个版本。
有趣的是,如果你打算从 LiveCode 发布 Android 应用,你可以感谢苹果公司如此固执!
扩展 LiveCode
LiveCode 的发展速度相当快,到 2012 年 4 月,RunRev 已经实现了 Android 的所有 iOS 功能,并为 iOS 添加了许多功能。
即使到现在,并非所有功能都得到了覆盖,并且存在一个第三方市场,提供 LiveCode 的附加组件,这些组件要么使 LiveCode 的开发更加容易,要么提供标准版本中尚未提供的功能。以下是一些附加组件,其中大部分可以在 LiveCode 市场购买:
MobGUI
我们已经在早期章节中使用了 MobGUI。它以插件的形式存在。你可以将 MobGUI 文件放置在你的 plugins
文件夹中。LiveCode 课程 lessons.runrev.com/s/lessons/m/4071/l/21341-how-to-install-custom-user-plugins
描述了如何添加插件。
MobGUI 的工作方式是允许你将常规 LiveCode 控件放置到你的堆栈卡片上,然后当应用程序运行时,标准控件会被本地控件替换。这比仅仅制作看起来像 iOS 控件的标准控件有优势,因为控件看起来也会正确。
MobGUI 并没有做任何你不能用你自己的脚本做到的事情,但它确实使布局和使用移动操作系统本地控件变得容易得多。它有一个选项可以在 iOS 和 Android 主题之间切换。有一个 MobGUI 的 YouTube 频道,它会展示你可以使用这个工具完成的一些事情,你可以在以下位置找到:
tmControl
tmControl 是由 Tactile Media 开发的一系列主题,它可以让你的 LiveCode 程序堆栈拥有更艺术化的外观。除了科幻和其他主题之外,tmControl
中还包含一个 iOS 主题。以下是它的样子:
实际上并不太令人惊讶!计划中还包括 Android 主题以及 iOS 主题的补充。你可以在以下位置找到目前可用的主题:
tmtools.tactilemedia.com/tmcontrol/themes.html
DropTools 调板
由雷霆之子软件公司制作的 DropTools 调板是 LiveCode 的免费附加组件,它作为一个外壳来托管多种自定义 LiveCode 控件。除了作为雷霆之子自定义控件的支持者之外,它还被其他开发者用作将他们自己的自定义控件推向市场的一种简单方式。DropTools 网站包括如何开发与 DropTools 兼容的自定义控件的详细说明。
网站还充当自定义 LiveCode 控件的聚合器,包括到 DropTools 和非 DropTools 兼容的附加程序的链接。DropTools 的主页位于:
许多自定义控件与移动应用程序无关,但其中有一些确实相关,并且这个数字无疑会随着时间的推移而增加。尽管他们正在努力扭转局势,但 DropTools 不与 LiveCode 社区版本兼容。
mergExt
mergExt
扩展是 LiveCode 的外部命令套件。在撰写本书时,没有可用的 LiveCode Android SDK,因此目前这些仅适用于 iOS。以下是当前列表,包括从 LiveCode 市场页面mergext.com
摘录的描述:
-
mergAccessory
: 这是一个 iOS 外部插件,用于通过外部配件框架连接和与配件硬件通信。 -
mergAES
: 这提供了易于使用的 AES 128 和 256 位加密,在 CBC 或 ECB 模式下。 -
mergAnswerColor
: 这是一个 iOS 外部插件,它提供了一个模态颜色选择器。 -
mergAV
: 这是一个 iOS 外部插件,它增加了与AVFoundation 框架相关的功能和命令。这目前包括选择、录制、保存和编辑视频。 -
mergAWS
: 这是一个 iOS 和 MacOS X 的外部插件,它增加了使用亚马逊网络服务的功能和命令。 -
mergBanner
: 这是一个 iOS 外部插件,它将一个iAd 横幅添加到您的应用程序屏幕底部。 -
mergBgTask
: 这是一个 iOS 外部插件,它添加了在 iOS 上启动和停止后台任务的命令。后台任务允许您的应用程序在后台继续执行代码。 -
mergBonjour
: 这是一个 iOS 外部插件,实现了 Bonjour 服务;搜索和注册。 -
mergCL
: 这实现了显著的位置变化和区域监控。外部插件将允许 iOS 在后台唤醒您的应用程序,并在用户进入或退出区域或移动到显著距离时接收消息。 -
mergDoc
: 这是一个 iOS 外部插件,它增加了与文档交互相关的功能和命令。这目前包括提供模态预览、在应用程序菜单中打开、文档选项菜单以及请求 PNG 格式的文档图标。打印功能也在这里提供。 -
mergDropbox
: 这是一个 iOS 外部插件,用于与用户的 Dropbox 账户交互。该外部插件使您能够上传和下载文件、创建文件夹以及管理用户 Dropbox 账户上的文件。Dropbox 同步 SDK 为您处理所有文件同步,并允许您像本地文件系统一样与您的应用程序目录交互。
-
mergFTPD
: 这为您的应用程序添加了一个 FTP 守护进程,允许 FTP 客户端连接。使用mergFTPD
从桌面版本管理您的应用程序文件。 -
mergGK
: 这是一个 iOS 外部插件,它为 LiveCode 添加了 GameKit/Game Center 命令和功能。 -
mergJSON
: 这是一个支持 LiveCode 支持的所有平台的 JSON 编码/解码外部插件。 -
mergLA
: 这是一个 iOS 外部插件,它添加了一个命令,如果用户已设置生物识别触摸 ID 认证,则向用户展示本地认证对话框。 -
mergMK
s: 这是一个 LiveCode MapKit 外部插件,它添加了一个地图控件,支持并显示带有航向的用户位置,添加注释标记和多段线。 -
mergMP
: 这是一个 iOS 外部插件,它添加了与 MediaPlayer 框架相关的函数和命令。这目前包括查询 iPod 库和访问找到的媒体集合属性等功能。 -
mergNIC
: 这是一个 iOS 外部插件,用于获取设备上活动的网络接口信息。 -
mergNotify
: 这是一个 iOS 外部插件,它添加了一个命令,每当 iOS 通知中心接收到事件通知时,都会请求通知回调。 -
mergPop
: 这是一个 iOS 外部插件,它添加了用于展示操作表(iPad 上的弹出)和上下文菜单以供用户交互的功能。 -
mergReader
: 这是一个 iOS 外部插件,使用开源的vfrReader
项目展示模态 PDF 阅读器。 -
mergSettings
: 这是一个 iOS 外部插件,它将 LiveCode 应用程序与设置应用程序集成,并包括InAppSettingsKit
以在您的应用程序内展示匹配的对话框。 -
mergSocial
: 这是一个 iOS 外部插件,它添加了命令以展示 Twitter、Facebook 和微博帖子模态视图。 -
mergSocket
: 这是一个 iOS 外部插件,它提供 TCP 和 UDP(数据报)客户端和服务器套接字。 -
mergXattr
: 这是一个 iOS 外部插件,它添加了命令以设置文件的do not backup
和protection
属性。 -
mergZXing
: 这是一个 LiveCode 外部插件,它使用ZXing
库通过移动设备的后置摄像头读取广泛的条码类型。
animationEngine
这允许您创建平滑的动画并检测对象之间的碰撞。它非常适合创建游戏和制作演示应用程序。您可以在 LiveCode Marketplace 网站上找到其信息页面 livecode.com/store/marketplace/animation-engine-5/
。
尽管不是专门用于移动设备,但animationEngine
已经调整以符合 iOS App Store 的要求,因此它仍然可以用于制作 iOS 应用程序。它也适用于 Android 应用程序。
AirLaunch
如上一章中“为 iOS 创建空中安装程序”部分所示,AirLaunch 是一个附加组件,可以轻松创建 iOS 的空中安装程序文件。有关详细信息,请参阅:
www.hyperactivesw.com/airlaunch/index.html
The ControlManager IDE
The Flexible Learning Company 的 ControlManager 是一个 IDE 面板,旨在提供轻松查看项目结构、属性和布局的访问权限。它与 LiveCode 的免费版以及 Windows、Mac 和 Linux 平台的商业版兼容。它随着你在 IDE 中的操作而同步,并在你工作时自动更新。
ControlManager 设计了三个标签显示,旨在支持 IDE,以直观的方式展示结构、属性和几何形状。
-
控件浏览器:这是一个可导航的结构层次结构,具有洗牌选项和控制特定图标识别,从深层嵌套的组到所有可用堆栈、子堆栈和卡片的总览。
-
属性编辑器:它允许你在一个易于查看的列表中预览、比较和编辑任何控件、组、卡片、子堆栈或堆栈的任何属性。这些可以按字母顺序或按类型列出,包括访问基本或多维自定义属性。你可以应用从
dropShadows
到colorOverlays
的任何视觉效果,并使用内置的拖动控件为fillGradient
和strokeGradient
应用。 -
几何编辑器:它包含用于 3 方向调整大小、4 方向微调、9 方向对齐、6 方向分布和 5 方向层叠的点击功能,以及 7 种图像处理选项。使用 LiveCode 的前端脚本层,面板会自动与你同步,在你切换对象、卡片和堆栈时刷新。有关 ControlManager 的更多信息,请参阅
www.flexiblelearning.com/controlmanager/
。
创建你自己的附加组件
你可能感兴趣的两种主要附加组件类型是自定义控件和外部命令及函数(通常称为外部组件)。
自定义控件
自定义控件通常由一个包含许多标准控件和一组管理这些控件外观和交互的脚本组成。自定义控件的功能完全封装在其内部,不会以任何方式影响其环境。有关如何制作此类自定义控件的教程,请参阅:
lessons.runrev.com/m/4071/l/22272-custom-controls
如果你打算制作一个优秀的自定义面板,以便轻松地将自定义控件拖放到卡片窗口中,请考虑使其与 DropTools 兼容。这样你就可以节省大量时间解决 DropTools 已经解决的问题,并且你的自定义控件将与其他 DropTools 控件相匹配,使屏幕上的自定义面板不那么拥挤!有关如何开发与 DropTools 兼容的控件的信息,请参阅:
droptools.sonsothunder.com/developer/
外部组件
在之前提到的“课程”页面的左侧有一长串教程列表,其中一些与创建外部组件的主题相关。这些特定的教程旨在开发桌面应用程序的外部组件。要开发移动外部组件,你应该查看:
livecode.com/developers/guides/externals/
在撰写本文时,此页面仅涵盖 iOS 外部组件,但仍有理由相信,在你阅读这本书的时候,将会有关于如何创建 Android 外部组件的信息。这个页面相当长,甚至还包括一个 17 分钟的视频!视频也可以在 YouTube 上观看:
www.youtube.com/watch?feature=player_embedded&v=lqduyQkhigg
创建外部组件并不简单。如果你有一个有用的外部组件的想法,但觉得它超出了你的能力或兴趣,可以创建,那么请查看 mergExt
网站:
在这里,你可以提出你希望创建的外部组件的建议。
如果你确实认为自己可以创建外部组件,为什么不将它们作为产品提供呢?这些附加组件的现行价格在 30-100 美元之间——你所做的任何销售都将抵消你的开发成本。
开源
LiveCode 社区是一个开源应用程序。这意味着你可以查看和编辑运行它所用的所有代码,包括引擎代码。
使用 LiveCode 社区创建的任何应用程序都必须是开源的。你可以出售你制作的内容,但你必须根据 GPL 许可证公开你的源代码。你可以将其包含在你的分发应用程序中,或者包含一个用户可以点击以查看你的代码的链接。如果你在任何时候想创建一个专业应用程序并保护你的代码,你可以购买 LiveCode 的商业许可证,这允许你构建一个封闭源代码应用程序。
如果你了解 C++,你可以直接进入代码并添加你自己的功能、修复和增强。经过筛选过程后,你的新功能可以被整合到 LiveCode 本身,使其对每个人来说都更好。以下链接显示了你可以如何为此贡献力量:
livecode.com/community/contribute-to-livecode/
想要贡献代码的用户需要签署一份可以在以下位置找到的贡献者协议:
livecode.com/store/account/contributor-agreement-signup
RunRev 使用GitHub托管构成 LiveCode 的源文件。这是所有与 LiveCode 源文件交互的地方。如果你想对 LiveCode 进行修改,你需要一个 GitHub 账户并了解如何使用它。如果你只对获取 LiveCode 文件的开源副本感兴趣,你可以从 GitHub 下载压缩包,而无需在github.com/runrev/livecode
注册。
质量控制
如果你不太熟悉 C++并且遇到了一个错误,你可以以传统方式报告它并请求功能。你可以通过参与错误管理过程来帮助 RunRev 提高 LiveCode 的质量。特别是,你有充足的机会帮助重现已报告的错误并在源代码中修复错误。
质量控制中心对所有人均开放。你可以报告错误,请求将错误分配给你,并监视正在解决的错误进度。在质量控制中心屏幕底部提供了一个有用的搜索栏。这让你可以访问你提出的错误、分配给你的错误、需要调查的错误以及为下一个版本准备好的修复。你可以通过访问以下链接来创建自己的质量控制中心账户:
一旦你设置了账户,你可以继续使用此链接来未来访问质量控制中心。在提交新的错误之前,你应该在数据库中搜索类似的问题。
新的扩展世界
到目前为止,我们讨论的所有内容都是可用的。然而,LiveCode 8.0 的开发中即将迎来一个新世界。以下文本是 2014 年 9 月 RunRev14 会议和 2015 年初 Benjamin Beaumont 在 LiveCode 早期通讯状态报告中展示的未来的展望。我们一直在听说开放语言和小部件。一些术语和细节可能与我们所展示的不同。确实,开放语言已经看到了 LiveCodish、模块化 LiveCode 和现在的 LiveCode Builder 等术语。
虽然所有之前的附加组件都是扩展,但这个术语正在获得更广泛的意义。扩展是以某种方式扩展引擎的黑色盒子,导出执行特定功能的处理程序。它们与引擎的其余部分和其他扩展隔离。
新的扩展可以是库或小部件。库是外部组件的替代品,添加命令和类似于内置的函数,它们不在消息路径中。参数可以类型化,消除了对代码重复类型检查的需要。它们还支持无缝使用外部代码。库的编写方式与小部件完全相同,只是库中的任何“公共”处理程序都作为 LiveCode 脚本中的语法提供。
在 LiveCode 中,小部件是一个可以直接访问 2D 绘图库并在其上绘图的脚本。小部件就像你从工具调色板中选择的标准内置控件。特别是,小部件可以完全控制它们的响应方式以及 LiveCode 脚本看到的哪些消息。
小部件作为一系列事件处理程序实现,例如mouseEnter
、mouseLeave
、mouseMove
、mouseDown
、mouseUp
、mouseRelease
、keyPress
、save
、load
,最后是paint
。paint
事件用于使用 2D 画布语法渲染小部件。所有操作都使用浮点坐标,因此我们将有亚像素定位。小部件将能够内部拥有一个子小部件树,这样就可以用简单的小部件构建复杂的小部件。
扩展内部
扩展作为包含编译后的 LiveCode Builder、原始 LiveCode Builder 源代码(如果是一个开源扩展则非可选)、编译后的外部代码(如果需要)以及仅对扩展私有的基于文件的资源的单个文件存档进行构建和分发。
扩展将被版本化,这样你就可以发布维护更新和功能更新。对于维护更新,LiveCode 用户无需采取任何行动,但用户需要选择何时更新 LiveCode 以获取功能更新。
扩展可能需要安装其他扩展,IDE 会无缝处理这一点。如果你加载了一个需要你尚未安装的扩展的堆栈,IDE 会去寻找它们,但你可能需要为其中的一些付费!
LiveCode Builder
LiveCode Builder是现有 LiveCode 语言的变体,旨在成为一种“系统构建”语言。它是一种最小化语言,其所有功能理论上都由库提供。外部代码绑定内置其中,并以字节码形式静态编译。
LiveCode Builder 的设计目标之一是易于转换为基于 Web 的技术(JavaScript 和 HTML5)。随着 LiveCode 8 的成熟,计划是将现有引擎功能的一部分移入用 LiveCode Builder 编写的库中,这样大多数引擎功能就可以在 HTML5 和传统平台之间共享。这是实现 HTML5 支持的关键里程碑。
LiveCode Builder 的代码与当前的脚本语言相比如何?对于所有基本操作,如repeat/if/switch/put
,它们几乎相同,如果不是完全相同。主要区别在于你必须指定变量的类型并实例化它们。以下是一个示例:
variable tArray as array
put the empty array into tArray
put "ben" into tArray["name"]
if tArray["name"] is "Ben" then
answer "I found" && tArray["name"]
end if
另一个区别是,有许多新的语法可以完成以前不可能完成的事情。例如,在屏幕上绘制小部件会访问画布 API。你还必须添加一些默认设置来告诉 LiveCode 如何处理源文件以及使用哪些库。以下是一个简单的粉红色圆形小部件示例:
widget com.livecode.extensions.beaumont.pinkCircle
metadata title is "My Pink Circle"
metadata author is "Benjamin Beaumont"
metadata version is "1.0.0"
use com.livecode.canvas
public handler OnPaint()
// Create a path with a radius of half the width of the canvas
variable tCirclePath as Path
put rounded rectangle path of my bounds with radius my height / 2 into tCirclePath
// Set the paint to a solid pink color
set the paint of this canvas to solid paint with color [1, 0, 1]
// Fill the path
fill tCirclePath on this canvas
end handler
end widget
其他构造
包
包通过一个具有良好定义语法的文本文件定义了扩展的内容。此描述传递给 LiveCode Builder 编译器。
-
模块化 LiveCode 源文件(部分)
-
预编译的外部代码(代码)
-
任意基于文件的资源(文件/文件夹)
模块
模块是一组由多个针对特定平台专门化的源文件组成的处理程序集合。模块可以是小部件或由部分的第一行指定的库...
-
小部件<名称> [基于<名称>]
-
库<名称> [对于<平台>]
路线图
RunRev 大约每年更新一次 LiveCode 路线图。您可以在以下位置找到最新的路线图:
livecode.com/community/roadmap/
LiveCode 版本 8.0 将包含我们之前讨论的内容,并成为许多更多进步的基础。开放语言将被用于在开发测试此功能的过程中,以类似英语的语法完成网络、套接字和数据库库。小部件将成为改进控件的基础,以在所有平台上播放视频,以及一个新的矢量形状对象。将基于之前的技术开发一个新的集成开发环境。
2014 年 8 月,RunRev 完成了一项 40 万美元的筹资活动,以将HTML5支持添加到 LiveCode 套件中。这笔资金允许雇佣额外的员工来支持这一努力。HTML5 网络交付将能够将您的 LiveCode 应用程序输出到现代网络浏览器中,允许在浏览器环境中忠实呈现您的应用程序。它使用 HTML5,因此不需要浏览器插件。您将能够使用 LiveCode 创作真正的网络应用程序。
在此之后,将有一系列项目排队完成。一个物理引擎将 Box2D 集成到 LiveCode 中,并包含动画循环功能。一个Windows 8端口将基于为 Macintosh Cocoa 端口开发的新平台 API,以支持 Windows 移动设备。