Article content goes here…
零、简介
第一作者(乔恩)的父母都是艺术家。他们每个人都可以画出类似真实生活的幻想画,并且震惊地看到他们的儿子几乎不能画出简笔画。如果你一直认为你的内在艺术家是通过你在电脑和互联网的帮助下可以建立的东西来最好地表达的,那么这本书可以指导你的虚拟画笔。成品呢?适用于 Android 设备的移动 Web 应用,这反过来可以激发数百万潜在用户的创造力和生产力。我们希望这本书能给你所需要的一切,让你立刻开始工作,创作出你的杰作。
这本书是给谁的
这本书是以初学者的水平写的。在很大程度上,我们没有做任何假设,从 HTML 是什么到如何应用 CSS 来查询数据库和使用 JavaScript 显示内容。对一些人来说,这可能意味着他们想浏览某些介绍性的材料(肯定会错过许多糟糕的笑话)。然而,即使是高级用户也可能从我们展示的技巧中获得一些东西。
这本书的结构
我们把这本书的内容分成几章,有三个“非官方”的部分。
在第一部分中,我们向你介绍了网络的基本语言:HTML,CSS,JavaScript 等等。然后,我们快速进入两个应用(第二章–第三章),让你熟悉一下,然后回来讨论你在设计自己的应用时可能需要解决的规划问题(第四章–第六章)
在第二部**,**中,我们开始增加一些趣味。我们开始构建令人印象深刻的用户界面(第七章)和处理视觉内容(第八章)。然后,我们向您展示另外两个应用(第九章–第十章),它们讲述了移动应用的独特性质:使用位置信息来指导您的应用(和用户),以及利用云获取信息和数据。
最后,在最后一部分,我们将讨论添加到您的应用中的下一个交互级别。我们涉及添加音频和视频(第十一章),在用户背后做一些事情以提供令人印象深刻的功能(第十二章),并将其打包上传到网络或为您以前的浏览器绑定创作创建一个完整的应用(第十三章)。
虽然我们已经按照逻辑顺序对章节进行了分组,但在第一章之后,您应该可以自由探索其余的内容。虽然许多主题是建立在一个又一个的基础上的,但是首先阅读你感兴趣的内容可能会帮助你很好地理解你肯定想要检验的前几章中的概念。同时,每一章都有独立的信息,尤其是关于设计、心理学和用户体验的讨论!我们希望你旅途愉快!
下载代码
本书中所示示例的代码可从 GitHub 的[
github.com/jonwestfall/Beginning-Android-Web-Apps-Development](https://github.com/jonwestfall/Beginning-Android-Web-Apps-Development).
获得
联系作者
我们总是很高兴收到读者的来信,如果你对这本书(或生活)有任何问题、评论或想法,你可以通过我们的个人网站或社交媒体联系我们。
乔恩·韦斯特福尔:[
jonwestfall.com](http://jonwestfall.com)
推特:@jonwestfall
罗科奥古斯特:[
nerdofsteel.com/](http://nerdofsteel.com/)
推特:@therocco
格兰特·艾伦:[
www.artifexdigital.com](http://www.artifexdigital.com)
推特:@fuzzytwtr
一、利用移动网络的力量
欢迎阅读本书的第一章。在这一章中,我们不仅会尽力告诉你在这本书里你会发现什么,而且还会把它和以前的内容进行比较。你看,很简单,尽管“网络”在手机上以某种形式存在了 10 年,但直到现在,移动 Web 应用和移动优化网站的真正力量才被认识到。
在我们展示我们为这本书计划的整洁的东西之前,最好确保每个人都在同一页上,行话。所以我们要开始讨论网页设计中的基本术语。在第二部分,我们将讨论当今移动网络的前身。最后,在最后一节,我们将讨论指导本书的概念,并让您先睹为快一些我们将开发的应用!
网页设计基础
有几个概念最好先讨论一下。如果你以前听过这些,请原谅我们。然而,如果你对网页设计完全陌生(也就是说,你从未写过一个网页或博客),那么这应该是一个很好的起点。如果我们从头开始,那么我们应该从网络的通用语言开始:HTML。
入门:超文本标记语言(HTML)
20 世纪 80 年代末,我们今天所知的计算机语言 HTML 诞生了。HTML 本质上不是真正的编程语言,因为它不是编译的。更确切地说,HTML 是由一种叫做“??”网络浏览器“??”的特殊软件来解释的。桌面电脑上的微软 Internet Explorer、Mozilla Firefox 和谷歌 Chrome,Android 设备上的 Dolphin HD、Opera Mini 和 Skyfire 等浏览器从网络服务器下载 HTML 文件,解释并显示它们。整个过程相当简单。web 服务器可以是任何类型的计算机,它通过一种叫做超文本传输协议(HTTP,即网址开头的http://
,也称为 URL s)的东西向网络上的其他计算机提供文件列表。浏览器通过 HTTP 下载这些 HTML 文件并阅读它们,寻找被称为标签的特殊功能。这些标签的功能与旧的文字处理程序中的标签相同,即指定文本和页面的其他元素在查看器中显示时的外观。考虑图 1–1 中的网页。
图 1–1。【hello.html】一个名叫的网页实例
让我们来看看组成清单 1–1 中所示页面的 HTML 代码:
清单 1–1。hello.html??
`
The tag to the left just made this a new line.
The tag to the left here just made this a new paragraph.
`代码可能看起来有点奇怪,但是让我们一行一行地看一遍。第一行简单地写着<html>,
让浏览器知道它正在读取一个 HTML 文档。您会注意到文档的最后一行</html>
也是类似的。这一行“完成”了 HTML 对象—关闭标签并告诉浏览器页面已经结束。有了这样的标签集,浏览器就知道要应用什么格式以及在哪里停止应用。
代码的第二到第四行被称为页面标题。这是程序员存储浏览器需要知道的重要信息的地方,以便正确地格式化页面。在本例中,我在标题中放置的唯一标签是一个title
标签,它指定了应该在用户 web 浏览器的标题栏中显示什么。标题是人们最常找到某些文档的地方,比如层叠样式表、JavaScript 和搜索引擎优化的元信息、不同浏览器的特殊说明、favicons(浏览器中书签条目旁边出现的小图标)以及其他与文档内容无关的页面重要信息,这就引出了第 5 行——body
标记。
标签告诉浏览器将要显示给用户的内容。从这里,我们看到的是纯文本——与图 1–1 中显示的渲染页面相同。但是,您会注意到我们添加了一些特殊的标签。第一个是<strong>
,它告诉浏览器它和它的结束标签</strong>
之间的文本应该是粗体的,以给它更强的视觉魅力。第二个标签<em>
通过强调内容或使内容倾斜来做同样的事情。 1 第三个标签<br />
,开始新的一行(br 代表换行符!).<br />
标签与大多数 HTML 标签略有不同。因为标签不要求自己像<strong>
和<em>
标签那样包含页面上的内容,所以这个标签自己关闭。最后,<p>
标签开始一个新的段落。
所有网页的核心都是某种形式的 HTML,尽管我们将在本书中讨论的大多数网页要复杂得多。值得庆幸的是,我们将带您浏览它们,这样您就不会不知所措了!
如果这是您第一次涉足 HTML 和 web 应用的世界,那么在开始阅读这本书之前,熟悉 HTML 的基础知识可能是个好主意。互联网上学习 HTML 和浏览基本代码示例的最佳资源之一可以在 W3Schools ( [
www.w3schools.com/](http://www.w3schools.com/))
)找到。一旦你对 HTML 有了一点了解,或者如果你已经从头到脚都湿透了,是时候继续学习一些我们将在本书中用到的 web 应用设计和技术的中级部分了。
变得时尚:层叠样式表(CSS)
想象一下,你正在写一个简单的网页来帮助你为人父母——一个家庭琐事清单。它可能类似于图 1–2 中的列表。
图 1–2。 家庭琐事清单
仅仅看一眼成品,这里似乎没有什么进展。我们有一个标准的无聊的黑白文件,完全缺乏任何风格或个性。让我们来看看清单 1–2 中显示的幕后代码。
清单 1–2。chores.html??
`
Family Chore List
` `- Tommy: Take out the trash
- Beth: Clean out the fridge.
- Mittens: catch mice.
1 值得注意的是,你可能习惯使用的< b >和< i >标签在 HTML 4 中的用途分别与< strong >和< em >相同。它们的使用在 HTML5 中已经被弃用,取而代之的是上面的标签。
让我们分解一下body
元素中的一小段代码。这里,页面上的无序列表是使用ul
标签创建的。当你想创建一个项目符号列表时,无序列表是很好的选择。如果你的列表需要更多的排序,你可以选择使用ol
,或者有序列表,HTML 标签。
虽然这个页面相当简单,但是你可能想增加它的趣味。也许在圣诞节前后,你想在你的家庭琐事页面上加点颜色,让最卑鄙的骗子精灵也能开心地笑一笑(见图 1–3)。
图 1–3。 圣诞杂务清单用绿色和红色增添节日气氛
也许在 7 月 4 日,你可能想让你的家人充满爱国热情(见图 1–4)。
图 1–4。 爱国杂务清单上有红、白、蓝三色
每次我们改变颜色时,我们通过添加适当的标签来修改 HTML 源代码。看看清单 1–3 中的爱国版 chores.html。
清单 1–3。 爱国的 chores.html
`
Family Chore List
- Tommy: Take out the trash
- Beth: Clean out the fridge.
- Mittens: catch mice.
直接对 HTML 进行修改对于小页面来说很好。然而,想象一下,如果有 12 个孩子和数不清的宠物要协调,添加那些字体标签可能要花多少时间。或者你有多个页面,每个孩子一个,如果他们的兄弟姐妹有很好的颜色组合而他们没有,你不想让他们感到被忽略了。不要担心——我们可以使用一种叫做层叠样式表(CSS)的东西来控制这一切。基本上,CSS 文件是一个小文档,由一组应用于 HTML 文档的样式组成,这些样式可以随时更改,影响它所连接的每个页面,而不必编辑原始的 HTML 文档。清单 1–4 提供了一个示例 CSS 文件。
清单 1–4。 爱国. css
body {background-color: blue} h1 {color: white} li {color: red}
请注意,文件的格式只是您希望编辑的 HTML 标记(例如 H1 和您希望赋予它的属性)。在这种情况下,我们希望h1
中的文本颜色为白色。我们可以简化 chores.html 来包含一个到这个 CSS 文件的链接,如清单 1–5 中的代码所示。
**清单 1–5。**chores.html同 CSS 参考
`
我们将得到与图 1–4 中所示完全相同的输出。现在,想象一下如果我们向上扩展这是如何工作的。首先,家长不再需要直接编辑 HTML 标签来改变样式。根据假期的不同,他们可以简单地链接多个 CSS 文件(简单地修改清单 1–5 中的第四行代码)。其次,他们可以进一步扩展 CSS 来指定间距、字体(Mittens 讨厌衬线)等等。最后,如果他们有不止一个页面,他们可以简单地将每个页面顶部的 CSS 表链接到他们当前的“主题”,所有的页面看起来都一样。虽然上面的例子非常简单,但是它们展示了 CSS 的强大功能。我们将在本书中更详细地研究 CSS!
互动:JavaScript
有时候伟大的设计不足以表达你的观点。有时候你想做一些华而不实的事情,或者一些独特的事情,或者一些非常有用的事情。最简单的方法之一是使用 JavaScript。JavaScript 是一种脚本语言,在浏览者的网络浏览器中运行。例如,也许你以前访问过一个网站,得到一个类似于 Figure 1–5 中的弹出消息。
图 1–5。 一个 JavaScript 警告
通常,您会在填写表单页面时看到这些消息,或者可能在网上购物车中看到这些消息,告诉您您的商品缺货或类似的恼人消息。虽然您可能习惯于在您的计算机上的网页上看到这些消息,但它们也可以在移动网络浏览器中显示(参见 Figure 1–6)。
图 1–6。 安卓手机上的 JavaScript 警告
创建这些消息的代码非常简单。清单 1–6 将代码集成到我们在上面的 CSS 例子中看到的 chores.html 页面中。
**清单 1–6。**chores.html用 JavaScript 引用
`
让我们从 CSS 链接下面的新代码部分开始,在head
部分内,带有标签script
。script
标签告诉浏览器将要给出一段脚本代码(在本例中,类型为text/javascript
)。然后浏览器解释代码。因为它在head
部分,浏览器只是存储这些代码以备后用。这段代码被称为一个函数,你可以把它想象成一个用“快捷方式”包装的命令列表。这里的命令是另一个名为alert
的函数。可以想象,JavaScript 函数会变得非常复杂,函数包括其他函数并与用户输入交互。
一旦函数被加载到浏览器的菜单中,我们需要告诉浏览器我们什么时候想执行它。在这种情况下,我已经更改了body
标记,以包含行onload=ShowWarning();
。这告诉浏览器,当页面被加载时,我希望它运行函数ShowWarning
。两个括号表示我可以包含传递给函数的信息的地方。这对于创建计算器或检查表单中的输入非常有用。例如,我可以写出类似清单 1–7 的内容。
**清单 1–7。**chores.html用 JavaScript 引用传递一个变量
`
Family Chore List
` `- Tommy: Take out the trash
- Beth: Clean out the fridge.
- Mittens: catch mice.
清单 1–7 中的代码将产生与清单 1–6 中的代码完全相同的消息。然而,在清单 1–7 中,我将猫的名字作为变量传递。函数ShowWarning
现在希望我传递一个名为“catname”的变量,它可以在代码中使用这个信息。当我调用body
标签中的ShowWarning()
时,我简单地添加了要传递给函数的猫的名字。如果我想的话,我可以通过多项考试。如前所述,这可能会变得相当复杂,取决于我有多想惩罚可怜的米滕斯。
正如您所看到的,将 JavaScript 与 HTML 和 CSS 结合在一起可以产生外观漂亮、易于更新、可以与用户交互的页面。但是有时你可能需要制作一个不给出样式信息的文档——它只给出一般信息。下一节将给出一个主要的例子,因为我们开始进入 XML 的奇妙世界了!
获取信息:可扩展标记语言(XML)
如果你在网上呆过一段时间,你可能会注意到一些页面上有一个奇怪的小图标,看起来像这样。
图 1–7。 一个 RSS 图标
这个橙色的小图标告诉读者当前网站有一个 RSS 源。对于用户来说,RSS 提要看起来很无趣,难以理解(请看图 1–8 了解 RSS 提要的开始)。然而,其他网页和脚本可以使用它们从一个来源获取大量信息,并以不同的方式显示给用户。
图 1–8。 博客的 RSS 提要开始,显示新条目
例如,图 1–9 是我的个人博客的 RSS 提要的开始。每个元素都包含各种各样的数据,这些数据看起来并不美观,但提供了人们可能想要在一个叫做 RSS 阅读器的特殊软件中查看我的博客的所有信息。虽然某些应用,如 Microsoft Outlook,有内置的 RSS 阅读器,但许多人更喜欢使用专用的阅读器客户端。一个流行的 RSS 阅读器是 Google Reader,它可以链接到我的 RSS feed,并生成我的博客的漂亮视图,这样 Google Reader 用户可以很快看到我最近发布了什么文章。
图 1–9。 我的个人博客,显示在谷歌阅读器内
现在,你可能会问,为什么我想让人们在其他地方而不是通常的网址上浏览我的网站。简单的回答是,对于我的用户来说,在一个软件中查看他们阅读的所有博客(我的和其他人的)可能更方便。谷歌阅读器(Google Reader)等软件可以跟踪数百个 RSS 订阅源,包括新闻源、博客,甚至只是简单的状态更新,比如我的 Twitter 订阅源。所有这些信息都由 Google Reader 以一种称为可扩展标记语言(XML)的格式检索。XML 不是您希望让人类观众看到的格式,但是如果您在网页之间或 web 服务之间共享信息,您会希望使用这种格式。
虽然上面的例子将 XML 显示为输出,但是支持我的博客的 web 应用(WordPress)生成 XML,以便其他网站如 Google Reader 可以使用它。XML 也可以用作输入。例如,我可能想获取数据(如体育比分)并在我的网页上显示它们。最有可能的是,这些体育比分将会以 XML 的形式出现,然后我的网页就可以打开它并对其进行解析。解析只是一个花哨的术语,意思是“读取、解释和显示”。我的网页会读取分数,在必要的情况下解释分数(即计算一些东西,聚合一些东西),然后以某种有意义的方式显示给用户。
概括地说,我们现在已经看到了如何构建一个基本的网页,如何使它看起来漂亮(容易),以及如何使它与用户互动。最后,我们讨论了网页和程序如何使用 XML 在彼此之间获取数据。在我们阅读这本书的过程中,我们将深入讨论每一个领域,并给出大量如何使用它们的例子。事实上,在接下来的第二章中,我们将讨论如何从一个非常流行的 web 服务中获取数据,并在我们创建的第一个完整的应用中显示它!
JSON:人类可读的数据交换
如果你有一个绝妙的想法,要开发一个依赖于其他服务的应用编程接口(API)的移动 web 应用,比如 Twitter 或 Foursquare,那么很有可能你会很快被介绍给 JSON (JavaScript Object Notation),这是我最喜欢的技术之一。
JSON 是一种人类可读的、基于 JavaScript 的超轻量级数据交换技术。基本上,它是一个 JavaScript 对象,可用于传输简单的数据结构和信息数组。当在 web 应用中处理外部数据时,我爱上了 JSON,因为它比 XML 等其他技术更易于使用。不过,和所有技术一样,你的收获可能会有所不同。图 1–10 展示了一个 JSON 文档的例子。
**图 1–10。**T3nerdofsteel.com 罗科·奥古斯托 JSON 格式的作品集
移动网络的昨天和今天
我们中的许多人在 20 世纪 90 年代末开始使用互联网,或者,如果你不在 20 世纪 90 年代末,也许你已经用了一辈子了!虽然我们可能非常熟悉桌面上的互联网,但将它放在一个可以放入我们口袋的小屏幕上可能会有点奇怪,尤其是在谈到网络时经常听到的不同的行话和营销用语。我们将从讨论数据多快到达你的手机开始,然后讨论什么样的数据可以被发送。
了解速度(或者“3G 到底是什么?”)
在最新智能手机的广告中,你经常会听到“4G”或“比 3G 更快”这样的数字。“G”代表技术的产生。你很少听说 2G,第二代,这是有原因的。智能手机上数据的冲击与第三代蜂窝网络数据标准的出现相吻合。然而,1G 和 2G 确实存在,如果你拥有第一部 iPhone(2007 年发布),你只有 2G 速度,使用的协议包括 GPRS、EDGE 和 1X。2G 网络上的数据传输速度大约是拨号调制解调器的两倍,约为 115KbpsSo,虽然电子邮件和基于文本的网页加载速度相当快,但任何包含太多图像或多媒体的内容都将花费大约永久的时间 2 。
大约在 2001 年,我们所认为的 3G(或第三代)数据网络的最初设计被起草,理论速度可以达到 7Mbps 以上。这些网络,包括 UMTS、WCDMA 和 EV-DO 等协议,可以比 2G 网络更快地传输数据。这是第一次,允许创新,如电影和音乐直接传输到手机上。显示复杂网页的限制因素不再是数据连接的速度,而是手机的速度。到 2007 年,大多数电信提供商已经采用并“推出”3G 网络和设备,如移动宽带卡,变得很普遍。
在过去的几年中(2008-2010 年),当前 3G 技术的新版本和批准版本已经出现。虽然对于我们之前所熟知的 3G 技术与这种被称为“4G”的基于 3G 的新技术之间的确切差异存在相当大的争议,但很明显,较新的协议,如 asHSPA、HSPA+、WiMAX 和 LTE,比它们的 3G 前辈更快。不幸的是,虽然所有主要运营商都在逐步推进其提高数据速度和网络容量的计划,但这些更新和变化不会立即对最终用户变得明显,直到他们购买了具有正确内部硬件的电话来利用这些众多变化。
许多以移动设备为目标的 web 开发人员可能会陷入的一个常见陷阱是,开发移动应用时,速度是唯一需要考虑的因素。如果我知道我的用户需要一个 3G 网络来使用我正在开发的功能,考虑到我知道我会有一个更快的数据连接,这可能会吸引我跳过简化应用的其他部分。然而,如上所述,速度不是唯一需要考虑的因素。设备的实际处理能力和软件能力(即网络浏览器的能力)也会降低应用的速度。如果你想要这方面的证据,使用你自己的智能手机或平板电脑的 Wi-Fi 而不是蜂窝数据,观察某些网站和应用在连接到互联网时如何仍然滞后,尽管连接速度(通常)比 3G 或 4G 快得多。我们将讨论如何避免编写臃肿、反应迟钝的应用。
语言和协议,昨天和今天
既然我们已经知道我们能走多快,我们也许应该谈一谈过去 10 年里网页是如何呈现给手持设备用户的,以及移动世界的现状。
起初,手持设备,如最早的现代个人数字助理(PDA),没有直接连接到互联网。这意味着用户想从网上阅读的任何内容都需要先下载,然后存储在设备上或缓存起来。一个非常受欢迎的服务 AvantGo 在 2009 年关闭之前运营了十几年。虽然这些服务有些烦人(因为你需要定期手动将你的 PDA 与你的电脑同步,以获取你想要的内容),但它们通常以非常基本和易于阅读的方式呈现内容。具有讽刺意味的是,这种类型的呈现已经经历了一点复兴,因为今天的用户在在线或其他繁忙的时候(即在工作中)找到内容,并希望保存它以供以后阅读。一个受欢迎的服务,Read It Later ( [
readitlaterlist.com/](http://readitlaterlist.com/)
),甚至有一个移动客户端,以类似于 20 世纪 90 年代流行的老式“离线缓存”系统的格式显示这些保存的网页!图 1–11 显示了一篇稍后阅读的缓存文章。
至少感觉是这样的。
图 1–11。 读完之后,在安卓系统上,显示了一个雅虎的缓存版本体育文章
随着内置 Wi-Fi 无线电和智能手机的 PDA 的出现,用户可以直接连接到网页并查看其内容。然而,在直接接入互联网之前,许多电信公司提供带有 WAP 浏览器的手机。WAP,即无线应用协议,是一种极其简单的数据服务,它允许用户通过简单的菜单找到他们想要的信息。这些菜单通常都是文本,可能到处都有 1-2 张图片,旨在成为基于网络的电子邮件、电影时间或天气信息等内容的快速入口。装有 WAP 浏览器的手机本身并没有连接到互联网,因为它们只能看到提供商在菜单上放了什么,但至少它们可以在有手机覆盖的任何地方查看,而不是下载并离线阅读。
与 WAP 类似的概念是 Java 平台微型版,通常缩写为 j2me。j2me 允许用户在手机上加载小的 java 小程序,这些小程序可以像 WAP 一样连接到特定的服务,提供类似的体验。虽然 j2me (Java Platform,Micro Edition)和高通的 Brew MP 操作系统在 2-3 年前就可以在手机上使用,但它受到提供商可能在手机上设置的奇怪的安全设置和预防措施的限制。奇怪的是,它可以在已经安装了可以去任何地方的网络浏览器的手机上使用。这不禁让人想知道,当你可以简单地访问移动版的 Gmail 时,为什么你会加载一个特殊的 Gmail j2me 小程序。
最后,到 2005 年左右,市场上的大多数智能手机都包含了一个相当不错的网络浏览器,用户可以打开它,键入一个 URL,并查看实际的网页。这些网页通常是以下两种类型之一:塞进较小屏幕的普通网页(见图 1–12)或专门创建的网站移动版本(见图 1–13)。两者各有利弊。普通页面通常在小屏幕上看起来很糟糕,信息从页面上流出,不可读,或者用技术术语来说,不可呈现(呈现是网页在浏览器中显示的过程)。虽然信息通常显示得很糟糕,但如果一个人有足够的耐心和技能,他通常可以找到他们需要的东西。
图 1–12。 我的个人博客,桌面视图,显示在手机浏览器上
另一方面,移动版本通常更容易浏览,因为它们是专门为使用 XHTML 或 CHTML 等 HTML 语言变体的小屏幕设计的。这些页面看起来很好,非常有用,但通常缺乏具体的内容。
图 1–13。 我的个人博客,显示在移动浏览器的移动视图中
这本书的目标是帮助你创建一个网站的移动优化版本,包含与桌面版本相同的内容,同时仍然可用。正如你所料,那些觉得你的页面易于使用的用户更有可能忽略一些缺失的部分。但是,需要 20 分钟的用户(或者像我们的一位编辑指出的,20 秒!)寻找最新的比赛比分或天气预报可能会涌向其他地方。
我们喜欢的概念——以及未来的发展!
在我们结束这一章的时候,我们想花一点时间来讨论一些我们想要记住的指导原则,并希望你不仅在阅读这本书的时候,而且在开始编写自己的 web 应用的时候也能记住。
理念一:像用户一样思考
想想你拥有的一个网站,一个你为之做出贡献的网站,或者只是一个你经常访问的网站,问问你自己:大多数人在访问这个网站时都做些什么?答案可能很快就会出来。然而,更深入地思考这个答案到底有多“平均”可能是值得的。
例如,我的一个朋友最近在《赫芬顿邮报》上发表了几篇博客文章,该网站以快速和直言不讳的方式对一篇文章发表评论而闻名。当他发给我他的文章的链接时,我把它拉了出来并通读了一遍。完成后,我关闭了浏览器,开始了我的一天。本周晚些时候,我的朋友问我是否看到了那篇文章,在我说我看到了之后,他问我“你对那些评论有什么看法?”答案很简单。我对那些评论没有任何想法,当然甚至不足以阅读它们。然而,在他看来,由于它们是对他自己作品的反馈,评论比文章本身更有趣(毕竟,对一个作者来说,他们自己的作品似乎很熟悉,也很无趣)。现在想象一下,如果我的朋友设计了发布他作品的网站。如果你看到用户的评论被突出显示,甚至以较小的字体显示在文章的旁边或底部以外的其他地方,你可能不会感到惊讶。对我的朋友来说,“普通”用户对评论比对文章更感兴趣,而事实上,情况可能正好相反。
谢天谢地,我的朋友不是程序员。但是作为程序员,我们必须跟踪我们的用户在用我们的网站或应用做什么。如果我们把所有的注意力都集中在用户认为微不足道的功能上,而忽略了用户认为必要的核心功能的更新或增强,我们可能会失去这些用户。
概念 2:不要惹恼用户
我能给出的概念 2 的最好例子来自于“货币化”这个邪恶的词,或者简单地说,“嘿,我做了很多工作,我想以法定货币的形式得到某种回报!”货币化通常来自销售广告;用户理解的东西是生活的事实。如果你想要免费的东西,你会期望以某种方式时不时地受到广告的影响来保持它的免费。大多数人认为这比为内容付费更可取,事实上,许多出版商报告说通过广告比通过销售他们付费的产品赚得更多!
然而,仅仅因为你在向人们做广告,并不意味着你需要在他们面前插入广告!你需要使用有品位的广告,激起用户兴趣的广告,不惹恼用户的广告。每一段或者每一页的顶部、侧面和底部的广告很少是有效的。
类似地,不必要的内容或特殊效果也可能使用户烦恼。例如,最近我遇到一个页面,它使用了一个特殊的登录按钮,有一个很好的凸起边缘,在我的桌面浏览器上看起来很好。然而,在我的 Android 智能手机上,浏览器很困惑:这是一个按钮还是一个图像?当我敲它的时候,什么也没发生。最后,通过一个非常奇怪的动作,轻敲、轻握和移动手指,我让它登录了。如果此类网页的作者只需执行以下操作之一,问题就会得到解决:
- 用移动浏览器测试了页面
- 使用标准的 web 表单按钮
在这种情况下,形式优先于功能。不要误解我的意思,花哨的设计很好,只要它们不降低可用性。
概念 3:重测信度
在我(乔恩的)日常工作中,我研究个人如何做决定以及这些决定的影响。在我的研究生涯中,重测信度的概念是指一个给定任务一次运行的结果应该与第二次(以及随后)运行的结果相同。我将借用研究方法论中的概念来讨论一个关于测试你的内容的观点。
和概念 1 类似,用户都不一样。他们中的大多数人会有一个稍微不同的设置,比你在设计网页或应用时。例如,现在我使用的是 27 英寸的显示器,作为一名设计师,我觉得这非常有用,但我不希望大多数人都有。因此,如果我设计一个网页,我可能不应该假设人们的浏览器窗口是 1565 像素宽,912 像素高,就像我现在这样。当使用较小的屏幕时,这变得尤其重要。一些 Android 手机和平板电脑的屏幕相对较大,而另一些则较小。在各种设备上测试你的应用或网页(也许在朋友的帮助下)可以确保你的用户每次访问网站时都能获得最佳的体验。人们还必须小心重复访问,因为浏览器可能会缓存它应该更新的内容。另一方面,我们将在未来章节中重点介绍的一些技术利用了模板或框架,这些模板或框架将使浏览器缓存您的朋友。这些技术重用用户已经下载的内容!
理念四:保持简单愚蠢!
如今,你走在街上,一定会看到一些父母把他们的智能手机放在他们蹒跚学步的孩子面前,让他们在长途乘车或在商店里忙碌。在这个神奇的基于触摸、支持互联网的手机和平板电脑时代到来之前,在宽带互联网时代到来之前,我(罗科)也喜欢称之为“前时代”,进入一个基础计算机班被认为是一种巨大的特权。如果一个人想在高中毕业时拥有一份成功的、热爱电子表格的工作,这是他们在小学时就应该做的事情之一。
在每周和父亲一起看《星际迷航》的宗教般的成长过程中,你可以想象当我进入六年级,终于能够上我的第一堂正式的计算机课时,我是多么的欣喜若狂。我是说,拜托!你怎么能不想像斯科特一样,在几秒钟之内就在电脑上完成透明铝的配方呢?就在一秒钟之前,你还在对着鼠标说话,并试图给它发出语音命令。!这就是为什么开学前的整个夏天我都去图书馆查阅我能找到的每一本计算机书籍,为我即将到来的计算机初学者课程做准备。当我了解到计算机世界并不像《星际迷航》那样迷人和令人兴奋,而且每一部有电脑黑客的电影看起来都是如此时,这种兴奋很快变成了失望。相反,我从那门课中学到的最多的是如何复制贝弗利山警察主题曲并把它放在软盘上,以及如何打开 HyperCard 应用(尽管奇怪的是我们从未学会编写 HyperCard 应用。)
第一年,虽然很失望,但却成了我对计算机的决心/痴迷的催化剂,这使我在七年级时再次报名参加了计算机班。我不知道的是,这门计算机课,我生命中每天这微不足道的一小时,最终会导致我一生的痴迷。看,这是美国在线在美国开始真正流行的一年。最重要的是,今年见证了 HTML 2.0 的诞生。我的老师当时看到了这项技术的发展方向,并对信息自由交换的未来充满憧憬。每天在课堂上,他都会反复强调,总有一天“创建网页的人”(这是在 Web 开发人员这个术语被创造出来之前)会获得和医生、律师一样的报酬,并且同样有价值和重要。当然,我们都认为他是一个疯狂的老人,但他对未来的兴奋足以让我着迷,最终我开始相信它并宣扬它。他对这个愿景深信不疑,以至于我们全年唯一要做的工作就是创建学校的整个网站。
在我从那堂课上学到的所有东西中,我学到的最重要的规则是 KISS 原则,这是“保持简单愚蠢”的首字母缩写尽管我很喜欢这位老师教给我的知识,但不可否认,他是个爱发牢骚的老混蛋。每次我们为我们学校的网站想出了一个绝妙的主意,比如添加动画 GIF 火焰和海狸和大头鱼的精灵,他总是说“保持简单,愚蠢!”作为一个孩子,不断被拒绝,基本上每天都被称为白痴,这很烦人,但它教会了我耐心和克制的艺术。这让我意识到,即使特性 X、Y 和 Z 在我从事的任何给定项目中都很棒,但更重要的是将它们放在次要位置,这样我就可以对特性 A、B 和 C 进行编码和交付。现在,当我在做一个项目时,我会坐下来,详细规划我需要做些什么来启动我的项目。我把我对额外功能的任何酷想法放在一边,这些额外功能不是发布时必须的,所以我可以在以后手头的任务不会转移我的注意力时再去做。
不管你是谁,也不管你从事设计或开发有多长时间,有一点永远是正确的。任何项目最难的部分是开始那个项目。你的项目中不需要的功能越多,你最终添加的功能就越棒(例如,给热棒添加火焰使它跑得更快),你就越难决定从哪里开始你的项目。所以请记住,无论你刚刚想到的想法多么不可思议,如果不是绝对有必要让你的项目起步并引起人们的兴趣,那么在将它添加到项目中之前,请试着三思。对这个想法做一个心理记录或物理记录,稍后再回来讨论。一个完美的例子就是像 Twitter 这样的程序。几年前 Twitter 发布的时候,它是一个非常稀疏的程序,围绕着一个非常简单的想法“你现在在做什么?”随着时间的推移,更多新的和令人兴奋的功能被按需添加。Twitter 现在已经从一个你可以告诉世界你午餐吃了什么的愚蠢的小网站发展成为一个大量投资的 Web 应用,它打破了像迈克尔杰克逊之死这样有新闻价值的事件,甚至在从内战中互联网匮乏的国家获取信息方面发挥了重要作用。
记住罗马不是一夜建成的。这是一个不断发展的帝国,每天都在自我建设,你应该以同样的方式看待你的下一个网络项目。从小处着手,尽可能地增加,同时不要让自己在这个过程中不知所措。本质上— 保持简单,笨蛋!
即将到来
既然我们已经讨论了网页设计的具体细节、首字母缩写词、奇怪的故事和概念,那就让我们来谈谈你会在这本书里发现什么。
从下一章开始(只差几页了!),我们将利用当今网络上最流行的服务之一 Twitter 开发一个简单的应用。Twitter 是一个伟大的网络现象,所以我们将在第三章的另一个小应用中继续使用它。然后,我们将后退一步,看看更大的画面——比如你如何首先开发一个应用(第四章),以及如何处理不同的屏幕分辨率和浏览器平台(第五章 & 6 )。在第七章中,我们将展示 jQuery Mobile——更重要的是,展示如何用它让你的应用看起来更专业和“漂亮”。第八章将继续这个主题,展示一些在用户界面设计中使用的好资源。这样一来,我们就可以玩玩基于位置和基于云的应用,然后讨论如何使用音频和视频、Ajax 以及如何准备产品的“发货”来结束这本书。有很多材料要涵盖,但我们知道你已经准备好了!此外,如果你还没有注意到,我们的趋势是通过例子给你很多信息,然后回到更像教科书的叙述。通过这种方式,希望你能在这本咬指甲的电脑书上保持专注!(好吧,这有点讽刺,尽管我们真心希望这种方法能让阅读变得“有趣”。)
所以,不再拖延,让我们从第一个应用开始吧!
二、推特应用:那条推特是谁的?
既然我们已经涵盖了本书中将要学习的内容,那么是时候开始动手创建我们的第一个移动 web 应用了。这两个应用都是与 Twitter API 交互的非常简单的应用。API 或应用编程接口是一种接口,用于根据用户提供给应用的一组规则或参数与特定应用进行交互。人们通常会使用 API 从应用的基础设施中收集和解析数据,而无需直接连接到应用的数据库来获取这些信息。
我们将构建的第一个应用是“那条推特是谁?”,它将解析一个预定义的已验证 Twitter 用户的小列表,并在页面上显示一条随机的推文,以及可能创建该推文的四个可能个人的列表。
我们将构建的第二个小型 Web 应用名为“我爱火腿”,它也将借用 Twitter 的数据消防水管,为移动用户创造一种快速而有趣的娱乐形式。《我爱火腿》将关注非常基础的游戏机制。用户可以从两个预定义的押韵 Twitter 搜索中进行选择。如果他们选择收到最多结果的 Twitter 搜索,那么他们就是赢家。这两款手机网页游戏都将严重依赖 HTML5、JavaScript 和一项名为 JSONP 的神奇技术。
在这一章中,我们将让你在自己的个人电脑上建立并运行一个开发环境(把它想象成你自己的迷你互联网,它将连接到真实互联网上的 Twitter,但大多数情况下只是在你的电脑上运行),并讨论那条 Tweet 是谁?应用。在下一章,我们将继续讨论我爱火腿应用。我们开始吧!
JSONP
你可能记得我们在第一章谈到 JSON。JSON 是一项很棒的技术,如果你在过去几年中在 web 开发领域工作过,你可能会遇到一两次。如果你在过去的一天里浏览过网页,你也可能浏览过使用它的网站!如果您曾经使用过 Flickr、Twitter 或 Gowalla 的 API,那么您可能也非常熟悉 JSON。对于那些完全跳过第一章的人来说,JSON 是一种人类可读的数据交换技术,它是轻量级的,也是一种开放标准。作为一项技术,JSON 还相当年轻,它的使用可以追溯到世纪之交,2002 年JSON.org
( [
www.json.org](http://www.json.org)
)网站上线。
如果您熟悉使用 JavaScript 和创建对象,那么 JSON 应该对您来说比较熟悉。然而,不要将 JSON 与 JavaScript 对象混淆,因为它们是不同的。虽然我很喜欢 JSON,但是有一件很小很烦人的事情,大多数开发人员直到花了几个小时拔掉自己的头发,让自己过早地秃顶,才意识到,这是一件非常讨厌、很小、很烦人的事情,叫做跨域脚本。
要理解什么是跨域脚本以及为什么你的浏览器中有硬编码规则来阻止你这样做,你必须首先理解什么是跨站点脚本(XSS)。XSS 是网站和应用中的一种漏洞,它允许攻击者或入侵者将自己的脚本和内容注入到网站或系统中。入侵者可能会利用 XSS 漏洞将脚本上传到您的服务器,这将允许他们在自己的浏览器中为您的服务器模拟 Bash shell(常见的 UNIX shell 或命令行界面),或者更糟的是,可能会利用该漏洞从您的数据库中窃取数千个用户名和密码。
出于这些考虑,在大多数情况下,您的浏览器不会从站点服务器之外的域加载 JSON 数据。为了获取和使用这些数据,必须在加载页面并提供给用户之前,在后端服务器端获取这些数据。这看起来没什么大不了的,直到你开始构建拥有成千上万用户的应用。那么解析外部数据最终会影响服务器的性能。为了解决这个性能问题并将一些外部数据解析需求委托给最终用户,我们将使用 JSONP 或“带填充的 JSON”,这将允许我们的应用请求我们需要的 JSON 数据,因为它将被包装(或填充)在一个 JavaScript 对象中。
设置您的开发环境
在我们开始编码之前,我们需要建立一个开发环境。为了简单起见,我将假设我们使用的是基于 Windows 的操作系统,所以我将只介绍设置一个基本的 WAMP (Windows、Apache、MySQL 和 PHP)服务器的步骤,以便我们在上面测试我们的代码。我知道并不是每个人都使用基于 Windows 的系统,但是如果你使用 Linux 或者 OS X,那么你可能已经熟悉了建立一个*AMP 测试环境。
对于我们的测试环境,我们将使用开源的免费 WAMP 服务器 Uniform Server ( [
www.uniformserver.com/](http://www.uniformserver.com/)
)。你可以从他们的网站下载 WAMP 服务器。我正在使用的版本,以及将在本章截图中显示的版本,将来自版本“7 . 1 . 2–Orion”
设置测试环境相当简单。只要找到你从网站上抓取的下载文件,运行自解压 EXE 文件。完成后,打开文件夹。在运行服务器之前,我想看一下 Uniform Server 团队为了让我们的生活更轻松而提供的一些有用的程序。第一个应用称为预检查(Run_pre_check.exe)。 1 让我们运行这个应用,看看图 2–1 中的结果。
图 2–1。 统一服务器的预检查应用显示端口 80 和 443 当前正在使用
如您所见,如果我试图在此时运行服务器,它将会失败。我目前打开了 Skype,它运行在我运行服务器所需的经典 HTTP 端口(端口 80 和 443)上。在网络中有一个程序到端口的规则,所以我们需要做一些简单的调整。虽然您可以编辑一些配置文件来更改您将使用的端口,但为了简单起见,我将关闭 Skype,以便我们可以在默认设置下运行。
现在我们已经释放了端口,我们可以运行“Start.exe”应用,它将打开并在您的系统托盘中放置一个图标。右键单击系统托盘中的统一服务器图标。它看起来像一个蓝色的盒子,里面有数字 1,如下面的图 2–2 所示。选择菜单顶部的“安装并运行所有服务”选项。现在,如果您打开 web 浏览器并将其指向http://localhost/,
,您应该会看到默认的统一服务器启动页面(localhost 只是您当前工作的计算机的另一个名称,IP 地址是 127.0.0.1)。
您可能需要以 Windows 管理员的身份运行这个命令和其他命令。为此,右键单击命令并选择“以管理员身份运行”
图 2–2。 系统托盘中看到的统一服务器菜单
现在我们的服务器已经启动并运行,我们已经差不多准备好开始写一些代码了。我们必须做的最后一件事是熟悉服务器的默认 WWW 根文件夹。如果你打开解压统一服务器的文件夹,你会看到一个名为 www 的文件夹(见图 2–3)。任何通过浏览器查看您的站点的用户都可以看到您放在此文件夹中的任何内容。由于我们将使用我们自己的项目文件,您可以随意删除该文件夹中的所有内容,重新开始。稍后,您可能会在设置生产服务器时使用这些文件。但是,出于开发目的,并不需要它们。
图 2–3。 默认的 WWW 文件夹视图,将存放您的应用项目文件
现在,您已经成功地为本地开发建立了自己的 web 服务器,并清理了根文件夹,是时候开始一些编码了!如果你需要任何关于统一服务器的帮助,或者只是想更深入地挖掘一下,看看你能用这个服务器做些什么,你可以运行统一服务器目录中的“help.bat”批处理文件,它会给你提供一些非常深入的文档(见图 2–4)。
图 2–4。 统一服务器快速帮助文档
你的第一个移动 Web 应用
给自己倒杯咖啡,做点伸展运动,因为现在是开始编码的时候了。我们正在构建的第一个应用,“那条推特是谁?”,将是一个小而简单的游戏,收集经过验证的 Twitter 用户和名人,并随机显示他们的一条推文。然后,用户将会看到一个由四个可能创建该 Twitter 帖子的 Twitter 用户组成的列表。如果最终用户选择了正确的 Twitter 用户来支持该帖子,那么他们的分数将增加 100 分,并进入下一个随机帖子。如果没有,他们会得到一个视觉提示,表明他们的猜测能力较差,并将继续随机发布下一篇 Twitter 帖子。
我们要做的第一件事是为我们的游戏创建一个非常基本的 HTML 布局,或者说基础。在那之后,我们将继续用一点 CSS3 来设计这个平淡无奇的框架布局,一旦它看起来很漂亮,我们将最终继续编写我们的 JavaScript,它将在我们的第一个移动 web 应用中把一切联系在一起。
HTML
清单 2–1 包含了我们游戏的基本 HTML。
清单 2–1。 那是谁的推文?
`
Player 1
页面的 HTML 标记非常简单。从head
元素开始,您可能注意到的与标准的基于桌面的 web 开发略有不同的第一件事是使用了名为“viewport”
的meta
元素。当涉及到移动设计和开发时,这个元素是极其重要的,我们将在第十章中详细讨论。通过它,您可以控制用户是否可以缩放页面上的内容,甚至可以控制用户可以放大页面的多少。在这里,我们将视口的缩放设置为默认值,并关闭了允许用户放大和缩小页面的选项,因此我们不必担心最终用户无意中双击显示器会导致您即将开发的 web 应用放大或缩小,同时让您的用户感到沮丧。
一旦进入body
元素,你可能会注意到我们使用了几个“新”HTML5 元素,比如header
和section
。header
元素是一个较新的标签,用于从语义上构建您的代码,以指示对 web 上的页面或文章的介绍。在我们的header
区域,我们用它来存放玩家的当前分数,我们会在每一轮之后用 JavaScript 更新分数,以及玩家的名字。考虑到这个演示的简单性,我们将把玩家命名为Player 1
。
接下来我们有section
元素,它用来存放我们演示的主要内容。像header
一样,section
元素是一个新的 HTML5 标签,用于语义标记文档或页面的部分。回到过去的 xHTML 时代,我们通常会用潮水般的无休止的div
标签来指定页面的各个部分,这可能会让搜索引擎和视障人士的屏幕阅读器感到非常困惑。现在,通过正确使用section
标签,搜索引擎和屏幕阅读器应该很容易就能猜出页面上哪些信息是应该大声朗读或搜索的重要信息。
在页面的主要内容部分,我们有一个 ID 为tweet,
的div
容器,它将用于存放我们从已验证用户的数组中提取的随机 tweet,以及一个空的ul
(无序列表)元素,它将用于包含我们将向最终用户显示的四个随机验证的 Twitter 用户。
在#tweets
容器内部,我们看到两个div
容器—.avatar
和.content
。对于那些不熟悉 CSS 的人来说,在本书中,每当你提到代码时看到散列标签(#),就意味着我们指的是元素的 ID。如果我们通过一个标签的 class 属性来引用它,那么它前面会有一个句号,比如上面的.avatar
。
现在我们已经有了基本的结构设置,是时候进行整个过程中我最喜欢的一部分了——用 CSS 来设计页面的样式!
CSS
在上一章中,我们讨论了 CSS。在这里,您将通过实际操作来了解更多信息。然而,如果你没有跟上正在发生的一切,也不要气馁。我们将在这一章和以后更多地讨论它。
有了这里的 CSS,我们不打算做任何超级花哨的东西。然而,我们将利用 Android 的 Webkit 2 渲染引擎来使用一些在过去几年中变得流行的较新的 CSS3 功能。让我们从一些基本的样式重置和一般布局样式开始,然后一节一节地浏览我们的 CSS 文件。在清单 2–2 中,我们将梳理页面上的基本 HTML 元素,并重置它们的边距和填充,或者它们在页面上的间距,以及重置整个文档中使用的字体大小和类型。
清单 2–2。 那是谁的微博?CSS 文件–第一部分
`/*** RESET ***/
html, body, header, section, div, p, ul, li, h2 {
margin:0; padding:0;
}
ul, li {
list-style:none;
}
/*** GLOBAL CSS ***/
html, body {
width:100%;
overflow-x:hidden;
}
body {
font-size:14px;
font-family: ‘Droid Sans’, Arial, Helvetica, sans-serif;
background:#06c;
}
h2 {
font-size:14px;
}`
如果你过去写过 CSS,这第一点样式代码应该看起来非常基本和熟悉。我们首先将几个页面元素的边距和填充重置为零,以确保我们分配给页面的任何样式都可以在大量 Android 设备上正确定位。这一点非常重要,尤其是当你记住 Android 是一个快速发展的平台,每年会发布两次或更多的新版本。
接下来我们要做的是删除任何可能附加到无序列表(ul)
和列表项(li)
元素)的项目符号,然后设置页面的默认字体和字体大小,以及应用的背景颜色。
最后但同样重要的是,我们将使用“Droid Sans”网络字体。看,在过去的几年里,随着网络的发展,设计师和开发人员一直在尖叫和乞求一种新的和更容易的方式来使用那些你在他们的应用和网站上的印刷广告中一次又一次看到的华丽字体。我是认真的,谁想整天盯着 Arial 或者 Times New Roman?CSS3 令人难以置信的特性之一是在你的项目中使用了 True Type 字体。从现在开始,你不必依赖于压缩不良的图像或可怕的侵入式 Flash 解决方案来利用漂亮的排版。
2 Webkit 是一个开源的网页浏览器引擎,这意味着人们可以使用它制作网页浏览器软件。安卓使用它的定制版本,苹果的 iOS 也是如此。
谷歌甚至想尽办法帮了我们一个忙,创建了一个免费开放的网络安全字体数据库,供你随心所欲地使用。您可以在[
www.google.com/webfonts](http://www.google.com/webfonts)
访问 Google Web Fonts 网站。一旦你找到你想要使用的字体,谷歌会给你一些 HTML 代码添加到你的布局中,将字体加载到你的浏览器中,并从你的 CSS 文件中调用它,因为我们已经将“Droid Sans”称为我们页面的默认字体(见图 2–5)。
图 2–5。 在谷歌网络字体网站上查看 Droid Sans 字体
在清单 2–3 中,我们将为用户提供一个时尚的标题,它将停留在他们浏览器的顶部,并将包含玩家的假名以及他们的分数。
清单 2–3。 那是谁的微博?CSS 文件,第二部分
/*** HEADER ***/ header { width:100%; font-weight:bold; text-transform:uppercase; text-shadow: 1px 1px 1px rgba(255,255,255,0.5); line-height:40px; background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0, rgb(135,135,135)), color-stop(0.8, rgb(201,201,201)) ); -webkit-box-shadow:0 0 15px rgba(0,0,0,0.5); box-shadow:0 0 15px rgba(0,0,0,0.5); } header h2 { margin-left:10px;
} .score { float:right; margin-right:10px; }
CSS 的 HEADER 部分是我们享受乐趣和利用 CSS3 魔力的地方。在广泛使用 CSS3 之前,如果你想创建一个使用渐变背景的页面部分,那么你必须依赖于在图形设计程序中创建图像并拼接它们以满足你的需要。现在,就像魔术一样,你可以在你的 CSS 中添加一些不那么简单的代码,只需要几行代码就可以创建出和 Photoshop 一样的渐变效果。除了这些漂亮的渐变,我们还可以用一行小小的 CSS 代码给我们的header
添加阴影。就像魔法一样!
清单 2–4 可以被认为是我们 CSS 文件的主菜,因为它包含了使我们的页面看起来很棒的大部分属性。
清单 2–4。 那是谁的微博?CSS 文件,第三部分
`/*** SECTION ***/
section {
margin:20px 10px;
padding:10px;
border-radius:7px;
background:#aaa;
-webkit- box-shadow:0 0 20px rgba(0,0,0,0.5);
box-shadow:0 0 20px rgba(0,0,0,0.5);
}
section.fail {
background:#990000;
color:#fff;
}
section.win {
background:#009900;
color:#fff;
}
section.fail li, section.win li {
border-bottom:1px solid #fff;
}
section.fail li:first-child, section.win li:first-child {
border-top: 2px groove #fff;
}
section #tweet {
width:100%;
margin-bottom:10px;
padding-bottom:10px;
}
section .avatar {
float:left;
width:48px;
height:48px;
}
section .content {
margin-left:58px;
min-height:48px;
}
section .person {
margin-left:42px;
}
section ul {
width:100%;
clear:both;
}
section li {
margin:0;
padding:5px 5px 5px;
height:32px;
line-height:32px;
border-bottom:1px solid #666;
}
section li .avatar {
width:32px;
height:32px;
}
section li .avatar img {
width:32px;
height:32px;
}
section li:first-child {
border-top: 2px groove #666;
}`
CSS 的section
部分,就像它之前的 HTML 文档一样,是大部分奇迹发生的地方。你应该注意到的第一件事是 CSS3 的另一个漂亮的新特性——border-radius,它是为了让我们的生活变得更简单而开发的。现在,我们可以将这项工作交给浏览器的渲染引擎来完成,而不是花费数小时来尝试将图像正确拼接在一起,以使文档具有圆角,或者更糟,依赖臃肿的 JavaScript 库来满足我们的边界半径需求。
这里我们利用 border-radius CSS 属性给我们的section
容器一个漂亮的现代智能手机外观,然后用一个漂亮的阴影来结束它。之后,我们为.win
和.fail
类定义了两组样式,我们将通过 JavaScript 调用每一轮样式,作为用户选择是否正确的视觉指示器。
图 2–6、2–7 和 2–8 分别显示了我们的游戏视图、错误答案后的视图和正确答案后的视图。现在,让我们了解一下生成用户反馈视图所需的 JavaScript。
图 2–6。 那是谁的推特?运行安卓 2.3 网络浏览器
图 2–7。 那是谁的微博?未能选择正确的推文所有者后显示
图 2–8。 那是谁的推特?选择正确的推文海报后显示
JavaScript
现在我们已经设计好了页面的布局和样式,是时候用一些 JavaScript 让它动态起来了。本书中的所有应用演示都将利用 jQuery JavaScript 框架。如果你不熟悉 jQuery,它是一个奇妙的 JavaScript 库,世界各地都在使用,与 Internet Explorer 6 占主导地位的旧时代相比,它使跨平台 JavaScript 开发变得微不足道。
这里有一点 JavaScript 代码,所以我会像之前处理 CSS 代码一样分解它,一次解释一个部分。在编写这个演示时,我在代码中添加了大量有用的注释,这将进一步帮助我们当中的新开发人员理解正在发生的事情。
清单 2–5 将向我们展示一组将在我们的应用中使用的默认变量,并给我们一个非常丰富的数组,其中包含一些 Twitter 最受欢迎的验证用户。
清单 2–5。 那是谁的微博?Javascript 文件,第一部分
`/**
* Who’s That Tweet
* @author: Rocco Augusto
* @file: js/main.js
**/
/* This array holds a list of verified
Twitter accounts that we will use
to pull in random tweets for each
round
*/
var defaultIcon =
‘https://si0.twimg.com/sticky/default_profile_img/default_profile_3_normal.png’;
var currentRound = [];
var correct = ‘’;
var tweets = [
‘jimmyjohns’,
‘sugarsammyk’,
‘wilw’,
‘JeriLRyan’,
‘pattonoswalt’,
‘trutriciahelfer’,
‘AndrewWK’,
‘ChristianKane01’,
‘charliesheen’,
‘levarburton’,
‘edwardjolmos’,
‘Rosie’,
‘kevinrose’,
‘jason’,
‘leolaporte’,
‘aplusk’,
‘StacyKeibler’,
‘LilianGarcia’,
‘nicolerichie’,
‘rainnwilson’,
‘ericschmidt’,
‘pennjillette’,
‘nerdist’,
‘Scobleizer’
];`
这里我们定义了几个将在整个应用中使用的全局变量。第一个是defaultIcon
变量,它包含默认用户 Twitter 头像的长 URL,我们将在整个脚本中使用。我们可以不使用变量,只在需要时将代码添加到脚本中,但是在编码时尽可能多地缓存代码以供重用始终是一个好的做法。现在,当我们想在脚本中的任何地方添加defaultIcon
时,我们不必记住一些又大又长又复杂的 URL,在大多数情况下,这些 URL 只会在视觉上搞乱我们的代码。
接下来,我们创建一个名为currentRound
的空数组,它将存放我们从 Twitter 上获取的当前回合的所有数据。我们创建一个预定义的验证用户阵列,从中随机选择。对于这个列表,我刚刚在谷歌上搜索了经过验证的 Twitter 用户,并复制了我在谷歌搜索的第一页上找到的所有用户的名字。
如果这是一个基于 Twitter API 的真实游戏,而不是一个演示,我们会希望利用一个包含所有 Twitter 验证帐户列表的在线服务器,但是,因为我们是从小规模开始,所以现在一个数组就可以了。
清单 2–6 显示了主 JavScript 文件的第二部分,这是关于那条 Tweet 是谁的。
清单 2–6。 那是谁的推特?Javascript 文件,第二部分
`// this function will grab a random user from
// the tweets array.
function getRandom() {
var l = tweets.length; // grab length of tweet array
var ran = Math.floor(Math.random()*l); // grab random user
// check if randomly selected user is in list
if(currentRound.indexOf(tweets[ran]) == -1) {
if(currentRound.length == 0)
correct = tweets[ran]; // make first random user the correct user
//push random user to currentRound array
currentRound.push(tweets[ran]);
// grab three additional random users
if(currentRound.length < 4)
getRandom();
}
else {
// if random user is already in list then start over
getRandom();
}
}`
在清单 2–7 中,我们的下一个函数将遍历并从我们的 tweets 数组中选择一个随机用户,然后抓取另外三个随机用户供用户选择,如函数getRandom()
所示。在这个函数中,我们使用 JavaScript Math 对象来选择随机用户。
清单 2–7。 那是谁的微博?Javascript 文件,第三部分
`// grab the user avatars for users in currentRound array
function buildQuiz() {
var l = currentRound.length;
for(i=0;i<l;i++) {
$.getJSON(‘https://twitter.com/status/user_timeline/’ + currentRound[i] +
‘.json?count=10&callback=?’, function(data) {
var img = data[0].user.profile_image_url;
var name = data[0].user.screen_name
var h = ‘’;
// crete the html that will be injected into the game screen
h += ‘
- ’;
h += ’
h += ’’ + name + ‘’;
h += ‘ - ’;
// add users and images to page
$(‘section ul’).append(h);
});
}
}function init() {
//reset the correct answer and currentRound array
correct = ‘’;
( ′ u l , s e c t i o n ′ ) . r e m o v e C l a s s ( ) ; ('ul, section').removeClass(); (′ul,section′).removeClass(); (‘ul’).empty();getRandom();
//display the default twitter account icon
$(‘#tweet .avatar’).html(‘’);
//grab a random tweet from the correct user
$.getJSON(‘https://twitter.com/status/user_timeline/’ + correct +
‘.json?count=10&callback=?’, function(data) {
var ran = Math.floor(Math.random()*data.length);console.log(data.length);
console.log(ran);$(‘#tweet .content’).html(data[ran].text);
// randomize the currentRound array so the correct user isnt always first
currentRound.sort(function() {return 0.5 - Math.random()});// grab avatars and display usernames
buildQuiz();
});
}`在接下来的两个函数中,我们将通过调用函数
init().
来启动应用。该函数重置所有变量以启动一个全新的游戏,解析随机选择的验证 Twitter 帐户的 JSONP Twitter API 提要,然后通过函数buildQuiz()
将所有要构建和显示的内容传递给用户。一旦文档加载到浏览器中,DOM(文档对象模型 HTML 文档中所有对象的跨平台表示)准备好被操作,下面的代码(清单 2–8)就会运行。在 jQuery 中,可以在文档准备好的时候运行代码 JavaScript 中的
ondocumentready
事件——使用下面的简写方式$(function() { ... code goes here });
一旦文档准备好,我们将调用
init()
函数,该函数将重置页面上的所有内容,随机获取一个用户,并像我们之前所经历的那样构建测验。我们还将把click
事件分配给所有将被写入页面的列表项,这样它们最终会像按钮一样工作。一旦用户点击列表项,应用将使用发布推文的用户的正确头像替换defaultIcon
,如果用户选择正确,则更新分数,并将gameover
类分配给游戏,如果屏幕再次被点击,则应用将告诉应用开始新一轮游戏。清单 2–8。 那是谁的微博?Javascript 文件,第四部分
`$(function(){
// run the init() function and start the application
init();// check for correct user on user selection
$(‘ul li’).live(‘click’, function() {
var name = $(this).attr(‘rel’);
var score = $(‘.score span’);// restart the game if game over
if(KaTeX parse error: Expected '}', got 'EOF' at end of input: …ar (‘#tweet .avatar img’).attr(‘src’,img);if(name == correct) {
score.text(parseInt(score.text())+100);
KaTeX parse error: Expected 'EOF', got '}' at position 42: …); }̲ el…(‘section’).addClass(‘fail’);
}// add gameover class to page
$(‘ul’).addClass(‘gameover’);
}
});
});`这就是了!对于那些正在编写代码的人,恭喜你,你已经正式完成了你的第一个移动 web 应用。你现在可以启动你信任的 Android 设备(如果你还没有这样做的话),连接到你的电脑所在的网络,并在上面查看你的新应用。为此,只需将您设备的浏览器指向您计算机的 IP 地址。您可以通过打开命令提示符(Windows)并运行
ipconfig
命令(参见图 2–9)或打开终端(OS X/Linux)并运行ifconfig
命令来找到您的 IP 地址。**图 2–9。**Windows 7 上的命令提示符显示我们服务器的 IP 地址
这就是你的第一个应用。
总结
我们在这里已经讨论了很多“应用”领域,比如设置开发服务器、编写 CSS 和 JavaScript 文件,以及测试新的应用。我们将在下一章的另一个例子中继续这种“应用”写作,然后停下来多谈一点网页设计的核心概念。现在来说说第三章里的火腿!
三、推特应用:我爱火腿
现在我们已经有了一个移动 web 应用,我想让我们探索使用 Twitter API 来做一些与老一套经典的“显示 Twitter 消息应用”有所不同的事情。正如我们在第二章中讨论的,使用 Twitter API 可以让你接触到总是充足的数据“消防水管”,这些数据可以用于所有类型的应用和游戏——基本上是你能想象到的任何东西。
我一直喜欢使用 Twitter 的一个想法来自几年前的一系列旧网络节目。虽然这个游戏的名字随着节目的变化而变化,但游戏背后的主要原则始终是一样的。用户会看到两个不同的押韵的搜索词,他们必须猜测哪个词会产生更多的推文。虽然规则很简单,但这个我们将构建并命名为“我爱火腿”的小游戏可以带来数小时的乐趣。所以事不宜迟,让我们启动本地开发环境,开始编写一些代码吧!
HTML
下面的清单 3–1 建立了基本的 HTML 文档,它将成为我们应用的基础。
清单 3–1。 HTML 为我爱火腿
`
I Love Ham 我们在这个应用中使用的 HTML 标记将比“那条推文是谁?”中的要少一些,我们以前构建的应用,它看起来也非常相似!为了简单起见,我保留了几乎相同的文件夹树布局的命名约定(参见图 3–1):
/index.html
/css/styles.css
/js/main.js
图 3–1。 一个清晰易读的文件结构,就像 Adobe Dreamweaver CS 5.5 中看到的那样,将为您节省大量的时间,并减少后续的挫折!
在创建文件和组织项目的文件夹结构时,我发现坚持人类可读、一目了然且在整个项目中保持一致的命名方案通常很有用。如果您最终将文件命名为 "
supercooldocument12-667.html
",您会使最终用户更难找到这些文档,如果您将来回到应用进行更新和编辑,这可能会导致问题。(相信我们:你会完全忘记那些文件是做什么的。)另一个技巧是用当前日期命名文件,或者使用版本控制系统来保持事物的完整性。所以请记住,在命名文件时,要保持简单和/或有意义!CSS
我们的 CSS 也将看起来类似于我们之前构建的应用。这里和那里有一些关键的区别,我们在这个应用中展示了一些简洁的 CSS 属性,例如
text-shadow
CSS 属性,它允许您在客户端浏览器中对文本应用一些非常奇妙的阴影效果。这并不依赖于让一个设计者用新的花哨的文本来制作一些过度压缩的图像,就像我们在过去所做的那样(过去,我指的是几年前!).清单 3–2 涵盖了在我们的应用中使用的常用元素的间距和字体大小的基本重置。
清单 3–2。 CSS 为我爱火腿——第一部
`/*** RESET ***/
html, body, header, section, div, p, ul, li, h2 {
margin:0;
padding:0;
}ul, li {
list-style:none;
}/*** GLOBAL CSS ***/
html, body {
width:100%;
height:600px;
overflow-x:hidden;
}body {
font-size:14px;
font-family: ‘Droid Sans’, Arial, Helvetica, sans-serif;
background:#993366;
}h2 {
font-size:18px;
color:#fff;
text-shadow:1px 1px 5px rgba(0,0,0,0.9);
}`我们的
h2
标签将成为我们text-shadow
的幸运接收者。如果您查看这个应用的 HTML 标记,您可以看到这个h2
标签包含了一个将呈现给用户的文本简介。根据游戏的当前状态,文本将改变多达四次,并将由应用的 JavaScript 更新。如前所述,如果我们用老方法做这件事,我们将不得不创建四个包含我们想要的文本的单独的图像,或者在需要时手动将这些图像插入页面,或者根据需要将它们作为背景图像分配给要分配给我们的 blurb 容器的 CSS 类。虽然这并不难做到,但这需要编写更多的代码,并在设备上加载更多的图形资源,如果用户在一个数据连接缓慢的区域,可能会导致明显的延迟或导致用户在情感上与你的应用断开连接!在清单 3–3 中,我们将设置列表项:
清单 3–3。 我爱火腿的 CSS 第二部
`/*** SECTION ***/
section {
margin:20px 10px;
padding:10px;
}sectionul {
width:100%;
margin:25px 0;
}section li {
margin:10px 0;
padding:10px 5px 10px;
min-height:22px;
line-height:32px;
border-radius:7px;
background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#a1a1a1), to(#A1A1A1), color-
stop(.6,#8A8A8A));
-webkit- box-shadow:0 0 20px rgba(0,0,0,0.5);
box-shadow:2px 2px 10px rgba(0,0,0,0.8);
}`你也会注意到我们对 CSS 中的列表项做了一些不同的处理。这里,我们给按钮添加了一个漂亮的渐变背景,让它们看起来更有魅力。不同于之前我们在第一个应用中创建的渐变背景,这一个使用了三色渐变系统来给它更多的斜面效果。此外,就像我们的
text-shadows
一样,使用 CSS 有助于减少浪费我们客户的资源,例如加载我们不使用的图像。我知道我确实在反复强调这一点,但那是因为这是一条必须遵守的真正重要的规则!永远不要不小心浪费你客户的资源,尤其是当你生活在一个古怪的数据上限或缓慢的数据连接的世界里。最后但同样重要的是,在我们的 CSS 文件中(参见清单 3–4,我将向您介绍两个非常方便的 CSS 选择器来让您熟悉一下:beforeand :afterselectors
。清单 3–4。 我爱火腿的 CSS 第三部
`sectionli.fail {
background:#990000;
color:#fff;
}sectionli.win {
background:#009900;
color:#fff;
}sectionli.fail, section li.win {
border-bottom:1px solid #fff;
}sectionblockquote {
margin:0;
padding:0;
}
sectionblockquote:before {
content: "\201c\ ";
font-size:26px;
float:left;
margin-right:5px;
padding-left:5px;
}sectionblockquote:after {
content: "\201e\ ";
font-size:26px;
margin-left:5px;
padding-left:5px;
}`现在,这些选择器很简洁,因为它们允许您在它们所附加的元素之前或之后添加内容。在这里,我将它们附加到 blockquote 元素,这是一个较老的 HTML 元素,用于在语义上将该内容标记为应该在页面上脱颖而出的引用。
现在,如果您查看
content
属性,您可能会有点困惑。在大多数情况下,人们通常会在这个字段中添加一些有意义的东西,比如一个“>”来代替无序列表中的项目符号,或者在链接到一篇文章的内容简介后添加一个省略号。然而,没有多少人知道,您还可以在这个属性中包含十六进制代码,以显示键盘上不常见的字符,例如我想在我的blockquote
内容的开头和结尾添加的引号!JavaScript
既然我们已经很好地理解了所有东西是如何布置的,那么是时候开始研究如何将所有的齿轮、滑轮和链轮放在一起,并让这个应用正常工作了!首先,就像在我们之前的应用中一样,我们首先在这里声明将在整个应用中使用的全局变量。在 JavaScript 中,理解使用全局变量和局部变量的区别是非常重要的。
简而言之,我想花点时间强调这是最基本的解释,局部变量是一个可以在函数中使用,但不能在不同的函数中使用或作为脚本的一部分的变量。功能基本上是可以重用的“捷径”。例如,我可能会创建一个函数,对给定的输入(称为“函数参数”,即在函数调用后放入()中的信息)进行一些数学运算,并在整个代码中重用该函数。局部变量在功能块内部使用,但在外部不可访问。就这些变量而言,把函数内部想象成一个与代码其余部分分离的小世界!
另一方面,正如您现在可能已经猜到的,全局变量是全局可访问的,因此您可以在 JavaScript 文件中的任何函数或对象中调用它。虽然有些人会嘲笑全局变量的使用,因为它们会引起问题。例如,一个全局变量可以从各种函数中更新,这就造成了在调试过程中变量如何变化的混乱。但是,为了学习,由于这是一本针对初学者的书,我们将在我们的示例中使用它们。
清单 3–5 设置了一个在整个 JavaScript 文件中使用的全局变量列表,以及一个充满押韵演示选项的数组,让我们的用户开心几个小时…或者分钟。
**清单 3–5。**Javascript for I Love Ham-Part 1
`/**
* I Love Ham
* @author: Rocco Augusto
* @file: js/main.js
**/var correct = ‘’;
var choice = ‘’;
varresultLength = 0;
var tweets = [
[‘I love ham’,‘Earthquake in Japan’],
[‘Android is awesome’, ‘I just hit an opossum’],
[‘Ice cream sandwich’,‘I fell out of my hammock’],
];`与我们之前的游戏不同,我们将有更少的选择呈现给我们的用户。虽然我很想添加 50 到 100 个不同的押韵例子,但不幸的是,我只能机智地不假思索地创造三个例子。就目前而言,我认为三个是好的,但是如果你在家跟着做,试着尽可能多的放进去!我敢肯定,你们中的很多人比我更机智!
清单 3–6 遍历我们应用的
init()
函数,从 API 获取我们的 Twitter JSON 提要。清单 3–6。 我爱火腿的 Javascript 第二部分
`functioninit() {
window.scrollTo(0, 1);//reset the correct answer and currentRound array
correct = ‘’;
choice = getRandom();
$(‘ul, section’).removeClass();
$(‘ul’).empty();//find out which item has more search results
for(i=0;i<choice.length;i++){
var position = i;
$.getJSON(‘http://search.twitter.com/search.json?rpp=100&q=’ +
choice[i].replace(/\s/g,‘%20’) + ‘&callback=?’, function(data) {
//check the length of results for each search
//then set them to the “correct” variable
correct.push(data.results.length);
});
}// generate the buttons for this round
buildQuiz();
}`这里有我们的
init()
函数,它将在 DOM(文档对象模型)加载后在应用中被调用和运行。当使用 Twitter API 时,你可以通过搜索发送几个参数。让我们快速浏览一遍!- 告诉 API 我们希望每页返回多少结果。在这种情况下,我们每次搜索最多获得 100 个结果。
Q
是容纳我们的搜索查询的参数。Callback
被触发以确保 API 以 JSONP 格式发回数据,这样我们就不会遇到任何跨域安全问题!
你会注意到上面的另一件事是搜索查询中的 I,我们在那个时候调用这个术语进行搜索。在那一部分,我使用了
replace()
方法在我们的字符串中搜索所有空格,并用%20
替换它们,这是一个空格的 URL 编码版本。这使得搜索可以通过普通的 HTTP 请求发送,而不会弄乱网页真正指向的位置。为了更好地理解为什么这是必要的,想象一下——有人给你发了一个[
someawesomesite.com/some](http://someawesomesite.com/some)
的链接。由于 URL 是不完整的,如果你发送链接的人点击了它,那么他们很可能会被导航到一个 URL 为[
someawesomesite.com/some](http://someawesomesite.com/some),
的页面,而 URL 的其他部分会被忽略,但是点击一个看起来像[
someawesomesite.com/some%20awesome%20page](http://someawesomesite.com/some%20awesome%20page)
的 URL 会把用户带到他们想要去的地方。始终确保您创建的 URL 中没有中断(参见图 3–2)!图 3–2。 注意前面来自 Android Thoughts 的 URL 使用连字符而不是空格来呈现给用户一个更加友好和人类可读的 URL
从 Twitter 获取 JSONP 数据后,我们将解析
data.resultsfield
的数据,然后获取该数组的长度、其中的记录数,然后将它们推送到我们之前创建的正确数组中,如清单 3–7 所示。**清单 3–7。**Javascript for I Love Ham-Part 3
`// this function will grab a random user from
// the tweets array.
functiongetRandom() {
var l = tweets.length; // grab length of tweet array
var ran = Math.floor(Math.random()*l); // grab random userreturn tweets[ran];
}functionbuildQuiz() {
var h = ‘’;for(i=0;i<choice.length;i++){
h += ‘ - ’;
h += ’’ + choice[i] + ‘
’;
h += ‘ - ’;
}// write buttons to the page
$(‘ul’).html(h);
}$(function(){
// run the init() function and start the application
init();// check for correct user on user selection
$(‘ul li’).live(‘click’, function() {
var id = $(this).index();
var result = ‘’;// restart the game if game over
if($(‘ul’).hasClass(‘gameover’)) {
init();
$(‘h2’).text(‘Which one of these fabulous tweets has more search results?!’);
}
else {
if(correct[id] > correct[not]) {
//congratulate the player
result = ‘Congratulations! you are a total rock star!’;
$(‘sectionli:eq(’+ id + ‘)’).addClass(‘win’);
}
else if(correct[id] == correct[not]) {
//if it is a tie
result = ‘It is a tie! You’re a winner by default!’;
}
else {
//shame the player into playing again
result = ‘Boo! You failure!’;
$(‘sectionli:eq(’+ id + ‘)’).addClass(‘fail’);
}// addgameover class to page
$(‘ul’).addClass(‘gameover’);
$(‘h2’).text(result + ‘Tap a button to play again!’);
}
});
});`在我们继续之前,值得一提的是,我们在“你是赢家”一行中加了一个反斜杠。这是因为我们使用了撇号,JavaScript 通常将其解释为字符串的结束。通过在它前面放置反斜杠,我们已经“转义”了它,告诉 JavaScript 对后面的撇号使用“替代”含义(在这种情况下,替代含义就是简单地将其视为字符串的一部分)。
其余的函数与我们已经创建的非常相似,所以我们将跳过它们,直接跳到控制按钮被按下时会发生什么的代码。在这段代码中,我们获取被按下按钮的索引,或者无序列表中的位置。然后,我们将这个搜索的值与另一个搜索的值进行比较。如果你的选择是数字较大的那一个,那么你就赢了,页面顶部的广告会变成一条祝贺你成功的好消息,或者如果你选择得不好,会变成一条失败的消息。在我们的逻辑语句中,我们也有在平局和两次搜索得到相同票数的情况下该怎么做的说明。
现在继续保存您的工作,启动您的浏览器,运行您新设计的应用(参见图 3–3)!虽然这很简单,但我相信您已经开始了解如何使用 HTML5、CSS3 和 JavaScript,实时创建一个非常有趣且响应迅速的 web 应用了!
图 3–3。 我喜欢在安卓 2.3 设备上运行的火腿
总结
不算太寒酸,如果我自己这么说的话!我们设法用一点代码和一个古怪的想法,很快就把它变成了一个好看的概念验证。我们已经展示了另一个通过 JavaScript 利用 Twitter API 的例子,并且我们已经建立了将它扩展到其他方面的平台——不仅仅是搜索 Tweets,还可以使用趋势主题和提及。只要再多花一点时间和精力,我们就可以在这个非常基础的 Twitter 应用的基础上,把它变成一个成熟的游戏,从我们用户的生活中吸取时间!
四、应用的基本规划和结构
到目前为止,我们已经让您直接开始编写一些应用,给了您一些关于屏幕分辨率、JavaScript 和 CSS 的背景信息,并且我们给了您一大包免费(而且便宜)的“东西”,以各种资源的形式供您在开发时使用。有了这些信息,你就不难完全疯狂地编写各种各样的好东西,并把它们公之于众。唯一的问题是,如果你不真正考虑你在构建什么,这个世界可能不会太热衷于实际使用你已经构建的东西。没有什么比在一个只有你(也许还有几个朋友)会看到的项目上花费大量时间更让人沮丧的了。
在这一章中,我们将以两种不同的方式来谈论应用开发:规划你的应用,这涉及到理解你正在构建什么,以及如何确保你不会忽略重要的部分;结构化你的代码,这是一个更简单的想法,但同样重要的原因我们将讨论。这是“将秩序带入混乱”的章节,我们希望你能注意到我们的警告和建议!
了解你的听众
如果你对创造东西有任何热情,那么你可能有过这样的经历:“我希望我有一个工具,它可以[在此插入机智的想法] …我知道,我只是要建造它!”此时,您很有可能出去为自己的使用一起做了一些东西,然后意识到其他人也可能对使用它感兴趣。我知道,每当我创建一个新的 web 或移动应用时,我总是这样做,为我自己的需要或有我这样需要的人而构建。也许这些人是你的观众。
或者也许你只是那些能看到别人看不到的问题的人之一。你知道,如果你把某样东西放在那里去解决某个问题,其他人会抓住不放,称赞你的名字。也许他们是你的观众。
或者最后,也许你是一个创新者,认为你已经进入了下一个伟大的游戏、服务或程序,人们会吵着要用。如果你付出一点努力(也许只是 50-100 个小时的编码),你可以看到上瘾的大众的金钱符号在增加——他们当然是你的观众,对吗?
好吧,也许你的激情、独创性和创新就足够了,观众就会神奇地出现。但是让我们思考一下这个问题。在前面的每个例子中,你假设你的激情、问题和快乐会延伸到其他人身上,这是一个相当大的飞跃。如果你在一家公司,向其他人推销这些产品,第一个问题会是,“我们怎么知道我们有受众?”简单地回答“我会买”是不够的。你必须知道你的目标是谁,他们是否感兴趣。
给人们想要的东西
有很多方法可以让你开始研究你的下一份申请。有时候,一个需求突然出现在你面前,或者你看到了一个明显的机会。其他时候,你可能认为某样东西会很受欢迎,但不知道它是否真的会受欢迎。虽然你可以在 Twitter 和脸书上寻找可以补救的抱怨,或者利用某种调查来了解你的观众想要什么,但我们将在这里介绍一个非常简单的方法,它符合一个普遍的规则:知道人们在寻找什么。下面的方法应该能让你了解人们是如何花时间上网的,从而让你知道你在哪里有机会。
我们从网络上流行的广告系统开始,谷歌的 Adwords。注册是免费的,即使你从来没有投放过一个广告,Adwords 提供的一个你可能会发现非常有用的工具是外部关键词工具(
[
adwords.google.com/select/KeywordToolExternal](https://adwords.google.com/select/KeywordToolExternal)
)。这个工具告诉你有多少人在谷歌上搜索特定的关键词。这是一个很好的方法来看看人们是否真的对你想做的东西感兴趣。例如,我考虑了一段时间的一个项目(从某种意义上说,实际上已经建立了)将是一个为有抱负的作家磨练技能的网站。我设想一个网站,在那里一个人可以得到一个主题,写一些散文形式(短篇小说,散文,诗歌等)。)并让其他人投票。题目的获胜者会得到一些“荣誉”,也许会赢得真正的奖励。
我怎么知道这个有没有市场?嗯,我可能会使用关键字工具来做一些简单的搜索,就像图 4–1 中的那些一样,搜索关键字“写作比赛”和“写作帮助”
图 4–1。 谷歌关键词搜索“写作大赛”和“写作帮助”
人们应该记住,关键字搜索是为广告商设计的,所以对“营销 SEO 语言”这种不友好的混乱语言进行一点解读是很重要的。首先,我知道“写作竞赛”的流量(按谷歌每月搜索量计算)是“写作帮助”的 2.5 倍。这是有用的信息,因为它表明有更多的人寻求竞赛和认可,而不是对他们的作品的建设性评论。如果我的网站或应用将同时具备这两个元素,那么竞赛的角度可能会更好。然而,如果我不完全确定我的应用或网站会是什么,我可能会发现关键词创意列表(图 4–2)特别有用:
图 4–2。 上面为搜索词的部分关键词创意列表
这里的“竞争”一栏可能有助于告诉我去哪里。根据 Google Adwords,你会看到“竞争”是指当人们搜索列出的关键词时,有多少其他广告商试图让他们的广告出现。对于“写作竞赛”(或者列表中更靠后的另一个项目,“免费帮助撰写商业计划”),我会有激烈的竞争,但对于“论文写作竞赛”(或者另一个未显示的项目:“说服性写作竞赛”)竞争很少。
使用 Adwords 中的外部关键字工具,我不仅可以了解人们在搜索什么,还可以了解其他公司在做什么广告。这可以帮助你更好地了解你的产品是否有受众(通过使用你怀疑他们会在谷歌中使用的关键词),以及是否已经有很多你要面对的替代品。虽然口碑广告对某些产品很有效,但你不应该低估搜索流量的力量!
谁是我的用户?
假设你知道你的产品有受众,你现在必须弄清楚谁是你的用户。最近,在参加一个充满光明、年轻的未来 MBA 高管的课程时,我惊讶地发现,他们对“瞄准”或找到他们的利基用户并专门针对他们进行营销的想法感到恼火。他们对不向“每个人”营销的想法犹豫不决,没有意识到:a)“每个人”可能都不感兴趣,b)目标用户比一般的“每个人”更有动力实际使用你的产品。
了解你的用户最好的方法是研究你自己的产品(在其早期阶段)或者其他已经存在的产品或网站。如果你正在开发一个应用来跟踪通勤交通的到达和离开时间以及延误,也许可以看看竞争应用或服务的目标是谁。很有可能你的目标是同一个群体,所以花些时间和精力考虑这个群体对产品的需求是值得的。
让我们通过一个例子来讨论这个问题,这个例子是我前面提到的虚构的 transit 应用。确定受众可能很困难,您可能需要考虑不止一组人。忙碌的通勤者或商务旅行者似乎是一个合理的考虑群体。如果我想瞄准这个群体,我可能会问并回答几个问题,例如:
- 我的应用或网站中的哪些功能会吸引忙碌的人?
- 我的应用中的哪些功能、细微差别或程序会让快速移动的人慢下来?
- 我的应用有哪些对使用公共交通工具的人有用的功能?
- 我怎样才能方便地向忙碌的用户发出信号,告诉他们有重要的事情正在发生(例如,一辆晚点的公共汽车或火车)?
- 我的应用将如何使用?它会被用来计划一次旅行,还是在最后一刻改变路线?还是两者都有?
这个列表可以从这里开始,但是你得到了图片。通过开发一个假设的“用户”,并设身处地地为他/她着想,你可以更好地了解你需要做些什么来让他/她的生活更轻松。让它变得更容易,你将获得一个用户或客户!然后简单地对你的下一批人进行同样的研究,也许这次是“休闲旅行者”或“游客”
并不是所有的研究都必须在你的头脑中进行;资源的存在是为了挖掘你的潜在用户在说什么。或许看看你潜在竞争对手的评论,看看人们对这些应用的爱憎。您还可以查看用户组和论坛,甚至进行简单的 Twitter 搜索,以了解特定领域的“问题”。
正如我在前面几段提到的,您可能也已经准备好了这些信息。如果你过去开发过一个网站或应用,你可能用过 Google Analytics (
[
google.com/analytics](http://google.com/analytics)
)或 Flurry Analytics ([
www.flurry.com](http://www.flurry.com)
)这样的产品。这些产品可以跟踪谁使用了您的应用,并为您提供宝贵的信息,您可以在以后使用这些信息来定义您的“用户”例如,在我写的一个应用中,我有一个简单的表格,人们可以用它来告诉我更多关于他们自己的信息。从那里,我发现我的应用的平均用户年龄在 25 到 34 岁之间,如图 4–3 中的所示。
图 4–3。 申请的年龄分布
这些信息在很多方面都很有用。首先,我可能会考虑这个团队会觉得重要的特性,并关注未来版本中的特性。或者,我可能会将小额广告预算从青少年转向 20 岁出头的市场,更多地关注 25 岁至 34 岁的人群,以吸引新用户。我对我的用户了解得越多,我就能更好地理解他们的需求,我的网站或应用就能更好地为他们服务。
不过需要注意的是:您可能注意到我的应用只有 17%的用户的已知信息。碰巧的是,我的应用中记录这些信息的部分可能对某些人口统计更有用,这可能会扭曲我的数据。在不深入讨论这个特定程序的情况下,最好注意不要依赖于一个来源,尤其是如果您只有少量数据,或者觉得您的样本可能有偏差。
一旦我从各种渠道获得了关于我的受众和用户的信息,我就可以制定一个计划。
有计划的
作为一个渴望游戏、建设和盈利的新开发者,规划很可能是最容易被忽视的事情。在这一节中,我们将讨论构建什么类型的应用,应用应该是什么样子,以及用户应该如何浏览它。通过从一开始就理解所有这些,我们可以保持我们的优先次序,并且在编码时,简单地实现我们已经解决的问题。让我们先来看看我们可以构建的不同类型的移动应用或界面。
所有手机都不一样
这本书的标题包括“web 应用”这几个字,这本质上承认了还有其他种类的应用。让我们来谈谈移动界面或应用的三种类型。
本机应用
如果你已经拥有或使用了一部安卓手机(如果你正在阅读这本书,我希望你已经拥有了),你可能已经使用了手机上的一些应用。web 浏览器是这些应用中的一种,联系人应用是另一种,计算器应用又是另一种。这些 Android 应用通常使用 Java 编写,并使用称为 Android 软件开发工具包(SDK)的特殊工具进行编译。这些工具可以免费下载和使用,用来创建可以在 Android Marketplace 上发布的应用。
这些应用被称为“本地”应用,因为它们直接从电话上执行。用户有一个专用的图标,点击它打开应用(见图 4–4)。这些应用可以轻松地在手机上存储数据,如果用户允许,还可以相互连接。通常,它们必须通过市场或出版商的网站下载和安装,但也可以通过在手机上下载和运行应用的 APK 包来“侧装”或安装在设备上。
图 4–4。 FAILboard Pro:原生安卓应用
本地应用往往速度更快,因为应用的所有部分都存在于手机的内存中,而且它们还可以更深入地访问手机的硬件,这是网络浏览器所不具备的。出于同样的原因,本地应用会给最终用户带来风险;刚刚安装的应用可能真的是一个试图窃取信息的特洛伊木马,或者开发人员急于推出更新,没有注意他们正在做什么,留下了一个安全漏洞。这类似于 2011 年 Skype 发生的事情,当时有人发现用户名和密码以未加密的人类可读文本保存在用户的手机上,任何人都可以轻松检索。幸运的是,很快就有了解决问题的方法。对于开发人员来说,开发一个原生应用可能需要更多的时间,也可能需要更陡峭的学习曲线,尤其是如果开发人员已经精通 HTML、CSS、JavaScript 和其他 web 技术。
移动网站
移动网站,或为移动设备优化的网站,通常在用户直接导航到该网站或常规网站后被用户浏览,常规网站将用户重定向到移动版本。这些仍然是网站,通常不会在用户的设备上存储数据或与之进行非常密切的互动。从本质上说,他们只是在那里做一个演示,并不是真的与你的用户进行激烈的互动。这通常是公司或网站改善移动用户体验的最基本的方法。移动网站允许你进行一些基本的操作,但是除了提供一些简单的文本页面和一两个表格之外,不与你交互。
正因为如此,这些网站缺乏桌面上的“完整功能”(即完整的网站),也可能不是特别适合智能手机或平板电脑屏幕(例如,平板电脑可能会看到过大的版本,智能手机可能会看到过小的版本,这取决于网站针对的是哪种设备)。虽然开发人员可能喜欢这种方法,因为它的创建、更新和测试相当简单,但最终用户并不认为这些移动网站是应用。如果你的目标是构建一些交互性的东西或者被看作是一种工具,那么你可能会想要避免这种方法的简单性,而倾向于 Web 应用。
Web 应用
最后,我们将讨论前两种应用的联合,以及我们在本书中开发的应用的类型。Web 应用试图将本地应用的无缝性与来自移动网站的相对容易的编码和更新结合起来。例如,我们在本书中的早期应用(见第二章第一章和第三章第三章第三章)有用户可以轻松按下的按钮,就像图 4-4 所示的原生应用一样,但是存在于网络浏览器中。如果用户要创建应用的快捷方式(或者应用本身可以询问用户是否愿意创建一个快捷方式),那么应用可以像本地应用一样拥有自己的图标。也有一些技术可以让 web 应用像本地应用一样将自己集成到操作系统中。
最好这样想:web 应用,就像普通的应用一样,是用来交互的,而不仅仅是浏览的。
那我该造哪个呢?
现在,你可能在想你真正想去的方向。老实说,虽然这本书关注的是 web 应用的好处(因为它们通常比本地应用更容易编程,比移动网站功能更全,并且初学者也可以访问),但您可能无法只使用一种解决方案。我们再次提到了解你的用户的想法。如果你的用户所在的区域总是有手机服务,那么也许一个 Web 应用会像本地应用一样有用。如果用户使用各种不同的设备(例如,Android、Windows Phone 或 iOS powered),那么 web 应用可能是同时在这三个平台上运行的最简单的方法。
最后,你必须发展你的移动策略来适应你的用户。在本书的后面(第十三章),我们将告诉你如何“欺骗”一点,只需要很少甚至不需要工作就可以将一个 web 应用转换成一个本地应用(从而让你至少拥有一个 web 应用和一个 Android 本地应用)。
一旦你选择了如何构建你的移动战略,你就应该考虑避免直接投入并编写代码的冲动。一个好的开发人员会规划他或她的应用,无论是本地的、基于 web 的还是移动网站。这一步可以按照构建应用的思想进行分组,我们将在接下来讨论。
构建您的应用
在这一节中,我们将讨论从头开始设计应用的过程。这采取三个步骤的形式,线框图或模型阶段,图形设计阶段,和代码构造阶段。先说设计。
线框/实体模型
有了一个想法,然后立即开始编码,而不考虑最终产品会是什么样子,这是非常诱人的。这可能是个坏主意,原因有很多:
- 它可能会让你陷入一个最终看起来并不那么好的设计中(例如,它太杂乱了)。或者你可能意识到,如果你没有直接创建按钮和框,你的设计就不会有效率!
- 它可能会阻止你创新,因为你不“想”改变事物来增加新的特性。
- 它可能会阻止你征求反馈,直到项目结束,那时改变事情可能太费时间了。向用户展示你的设计,看看他们是否觉得直观,然后调整一个图形,比向他们展示一个应用,然后重新编码以使设计更好更容易。
为了防止这些事情,许多设计师创建他们的应用的线框图表或“模型”。例如,我们之前讨论过的一个非常粗糙的交通应用模型可能是这样的(Figure 4–5)。
**图 4–5。**tran zit 应用的原始模型
正如我提到的,这是一个相当粗糙的模型;事实上,它甚至可能不是我最终拥有的设计的. 0001 版本。不过,在模仿它的过程中,我确实意识到了一些事情。我制作了运输时间、提醒和偏好的按钮;我为警报留出空间;我甚至在底部留出了一些空间做广告。然而,我还有另一个屏幕,标记为“E”,我不知道我可以用它来做什么。有了模型,我可以简单地删除和重画,以获得正确的。但是,如果我在现实生活中开发它,我可能会在那里留下一片空白,直到它接近 1.0 版本时才真正意识到这一点。
显然,你可以随意创建模型。图 4–5 是用我平板电脑上的一个应用创建的,这个应用可以让我徒手绘制(你可能已经看出来了)。人们也可以在 web 编辑器中用实际的图像、按钮等等来设计一个模型(即使按钮实际上不会工作)。另一种选择是使用 PowerPoint 或 Keynote 等程序,在这些程序中很容易绘制方框、制作动画和创建许多类似的绘图。
HotGlooand 和其他模型工具
如果你正在寻找一个基于网络的工具来创建你的模型,那么你可能想看看 HotGloo。产品主页如图 4–6(
[
www.hotgloo.com/](http://www.hotgloo.com/)
)所示。这个工具附带了一个月订阅,可能是我用过的最好也是最容易使用的线框工具之一。我用过的一些线框图工具只为你提供了基本的线框图,但是 HotGloo 允许你同时做很多视觉设计和线框图,节省你的时间。你可能想考虑的其他产品包括 lucid chart(
www.lucidchart.com
)和 Pencil Project ([
pencil.evolus.vn](http://pencil.evolus.vn)
),它们可能会集成到你已经在使用的现有工具中,比如 Microsoft Visio。**图 4–6。**hot gloo 网站,我们可以有把握地认为它是在 HotGloo 被框住的
用户移动:导航还是故事板
一旦你完成了你的线框,是时候坐下来把这些点连接起来,弄清楚你将如何在你的网站上构建内容,绘制出所有的页面和它们所属的部分。这个过程的这一部分被称为站点地图,如果你花时间去做的话,会非常容易和有趣。如果你的应用不是特别线性的(例如,也许是一个游戏),你也可以把这看作是故事板。用最简单的话来说,就是以一种有组织、有逻辑的方式来布局内容。
创建地图时,最好尝试在相似的部分或组中保留相似的内容。这将使构建应用变得更加容易,因为您一眼就能看出应用中的哪些页面需要相互关联。在一个游戏的例子中,把这想象成以一种逻辑的方式呈现你的信息:把所有的“黄金”和你可以用它购买的东西放在一起,或者所有的“生命点”和影响它们的增强功能放在一起,等等。
看看下面的图 4–7 可以更好地了解传统网站地图的样子。注意到它和我们在文法学校被迫做的那些家谱项目非常相似吗?嗯,这是非常相同的原则。站点的父页面(或部分)都有与该部分或类别相关联的子页面。
图 4–7。 演示应用的简单站点地图
对于这个网站地图,我使用了一个图形设计工具来创建这本书的模型;但是每当我在做一个个人使用的项目时,或者当我坐下来和一个想快速看到一些东西的客户在一起时,我会在一张餐巾纸或一张笔记本纸上画出网站地图和线框。
尽你所能创建你的网站地图。不管它是如何创建的,重要的是你要坐下来,仔细考虑你的页面是如何组织的,以使你的构建和开发更容易。
任何开发人员都不想做的最后一件事就是完成一个项目的 80%,却不得不回去重新做一些事情,因为由于缺乏适当的规划而犯了一个错误!
既然我们知道了应用的外观和内容是如何组织的,我们就可以开始编码了。让我们用本章的最后几页来讨论如何最好地构建我们的开发环境以获得最大的生产率。
构建你的发展
有了这些高级信息,你还需要考虑一些实用的开发规则,让你在编写应用的时候保持有条理和高效。接下来,我们将讨论一些组织你的代码和保存它的目录的想法。
代码结构
现在你已经完成了你的线框图,并且对你想让你的页面上的所有元素去哪里有了一个粗略的想法,是时候开始弄清楚你将如何组织你的代码,这样你就不会在构建你的应用时做更多的工作。
你现在可能正在挠头想,“这能有多难?我只是在一页纸上写文字。”你可能是对的。然而,假设您的应用中有十个不同的页面。您对 web 应用进行了更新,并意识到您的页脚有问题。
如果准备不充分,我们不幸的开发人员可能会在组成应用的十个不同的 HTML 页面中复制并粘贴同一个页脚。现在是时候更新代码了,我们虚构的开发人员必须用新的页脚信息更新十个不同的 HTML 文件。
正确构建这段代码的一个更简单的方法是获取页脚信息,它在整个站点中都是相同的,并为它创建一个单独的文件。然后,在您的代码中,您可以将该文件包含到您的页面模板中,并像以前一样在每个页面上显示它。如果您将来不得不更改代码,使用这种方法,您只需在一个文件中更改代码,这会让您的工作变得更加轻松。
让我们看看下面的例子。在清单 4–1 中,我们有一个非常稀疏的页面,它使用 PHP 来获取我们希望在每个页面上都有的额外页面代码。
清单 4–1。 使用 PHP 包含语句,我们将拉进额外的代码,以包括在我们的页面
`
Super Cool Web Application Super Awesome Header Article Header Fusce luctus accumsan odio. Cras vel sodales mi. Suspendisse et arcu quis magna feugiat ultrices sit amet non erat. Etiam malesuada dui venenatis eros gravida aliquet. Aliquam erat volutpat. Nullam dapibus cursus ultricies. Suspendisse congue accumsan purus non scelerisque. Phasellus ut sapien libero, vel luctus velit.
如果你看清单的底部,你会注意到我正在拉进页面
footer.php
(见清单 4–2)。我是通过将我的include
函数包装在<?php ?>
标签中来做到这一点的。这告诉您的页面执行 PHP 代码(如果您的服务器支持的话),并在这段代码中查找与前面列出的文档位于相同相对路径的页脚文档。如果您使用的是我们在本书前面讨论过的统一服务器本地开发服务器,那么这应该非常有用。否则我们可能需要指定一个相对路径;例如,如果我将我所有的“包含”文件放在一个名为“includes”的目录中,我的代码可能是:include('includes/footer.php')
。我们一会儿将讨论目录结构,所以一旦你在这里完成了,你将知道相对路径看起来如何到你的文件。现在我们知道了使用 PHP 在文档中包含一个文件是什么样子,我们将看看这个 PHP 文件的内部结构是什么样子,这样您就可以看到以一种简单的、可重用的方式来构造您的代码是多么简单。
**清单 4–2。**footer.php 档案里面的一看
`
© 2011 Super Awesome Site, Inc. All rights reserved.
`正如您在这里看到的,本文档中的代码非常简单。我们有一个浮动在文档右边的无序列表和一些浮动在文档左边的版权文本。我们将想象在远处的某个地方有一个为这个文档创建的样式表,它使一切都变得很漂亮。
PHP 最酷的地方在于它运行在服务器上,而不是客户端。这意味着你在 HTML 文档中包含的 PHP 代码(无论这是指将其他文档包含到你的模板中,还是自定义创建的类、函数等。)将永远对客户端可见。当客户端加载页面并查看源代码时,他或她看到的只是一个无缝的 HTML 文档(参见清单 4–3)。
清单 4–3。 在浏览器中查看我们的人造文章会显示一个完整的 HTML 文档,没有服务器端 PHP 代码
`
Super Cool Web Application Super Awesome Header Article Header Fusce luctus accumsan odio. Cras vel sodales mi. Suspendisse et arcu quis magna feugiat ultrices sit amet non erat. Etiam malesuada dui venenatis eros gravida aliquet. Aliquam erat volutpat. Nullam dapibus cursus ultricies. Suspendisse congue accumsan purus non scelerisque. Phasellus ut sapien libero, vel luctus velit.
文件夹结构
在前一个例子中,我们讨论了将文件分割成小的结构,使它们更易于管理。对于更多的文件,您可能还想创建目录来存储按功能分组的特定文件。
在图 4–8 中,我为一个虚拟应用创建了一个模拟文件夹结构。就像在你的文档中分离你的代码一样,整齐地安排你的文件夹结构也是一个很好的实践,这样你就可以在你的应用的整个开发过程中很容易地找到你需要的文件。
图 4–8。 在 Adobe Dreamweaver CS5.5 的文件浏览器中看到的组织整齐的模拟文件夹结构
这里我们坚持一个非常基本的结构,其中所有的资源目录(比如我们的
css
、img
和js
文件夹)都在站点的文档根文件夹中,并且有一个template
文件夹将保存我们的 web 应用的不同页面的模板代码。在 template 文件夹中有一个 includes 文件夹,我们将使用它来存放在整个应用中使用的文档,例如页眉或页脚的标记代码,甚至可能是一些随机的内容块。参考我们在上一节中关于相对路径的例子,在图 4–8 中的
index.php
文件中的包含行将引用页脚文件为include('template/includes/footer.php')
。这不仅保持了事物的分离,也具有逻辑意义。页脚是模板的一部分,它包含在几乎所有内容中,因此它位于模板目录中的 includes 目录中。现在,当需要开发我们的应用或在未来进行更新时,我们不必试图记住所有代码的位置,因为我们可以很容易地从逻辑上一眼就找到它。
如果我们想编辑联系页面上的信息,我们只需编辑位于
/template/contact.php
的模板文件。如果我们发现头文件有问题,我们可以很容易地跳到/template/includes/header.php
中,对我们心中的内容做任何我们需要的更改,然后让这些更改在整个应用中得到反映。总结
希望现在你已经到了另一个章节的结尾,在实际编码开始之前,你对创建一个 web 应用,甚至是一个 web 站点的思维过程和工作有了更好的了解。如果你在一家代理公司或工作室工作,或者其他以开发人员为中心的企业,那么你可能会在一个团队中,每个人负责自己的任务,并在交给你作为开发人员之前负责计划的不同部分。(在测试团队、开发里程碑、构建等方面,您可能还有更多。然而,如果你是为自己工作,你现在知道该怎么做才能让你的生活变得更容易忍受,让你的工作量变得更整洁。
五、使用 CSS 3 处理多个屏幕分辨率
设计网站时最难处理的事情之一是你可能会遇到无数不同的用户配置。现代 web 浏览器和操作系统是高度可配置的,不同的选项会影响您的 web 应用的查看方式。在这一章中,我们将专门讨论屏幕分辨率——或者屏幕上的像素数量——以及如何使用 CSS 3 适应不同的分辨率设置。
眼睛疲劳和分辨率进化的历史
如果你曾经在深夜使用电脑,也许是在一整天的工作之后,你可能会发现一个有用的技巧:你可以改变屏幕上对象的大小,使你的眼睛更容易阅读它们。这通常包括更改计算机的显示分辨率。分辨率就是屏幕显示的像素数量,由两个数字表示,第一个是像素宽度,第二个是像素高度(即高度)。通过改变分辨率,最常见的是将其从较高的分辨率,如 2560 × 1600(顺便提一下,我在晚上 7 点输入本文时使用的分辨率)缩小到较低的分辨率(可能是 1600×1200——一个不错的 11 点分辨率),您会带走单个像素,这意味着您屏幕上的项目会显得更大。
20 世纪 90 年代末,随着越来越多的人开始上网冲浪,标准分辨率被称为 VGA(视频图形阵列),通常设置为 640 × 480。随着时间的推移,显示器变得更大、更便宜、更高效,大多数用户都采用了 SVGA(老实说,S 代表超级!)!),在 800 × 600。这让位于 1024 × 768 和更大的 XGA(扩展图形阵列——谢天谢地不是 Xtreme)。今天我的显示器显示的是前面提到的 2560 × 1600 的 WQHD(宽四高清)。
你可以想象,自从 640 × 480 不再流行以来,网页设计师们已经为屏幕分辨率奋斗了很多年。他们最终分成了两个阵营——一派支持为一种分辨率设计(“固定宽度”),另一派支持为多种分辨率设计(“灵活宽度”)。固定宽度的人认为,最好的网页设计是你绝对确信所有用户看到的你的网站尽可能接近你设计的方式。这意味着选择一个分辨率,比如 1024 × 768,并设计你的页面来利用这个空间(见 Figure 5–1)。如果用户有一个更大的分辨率设置,你的页面会在两侧有额外的空间,但是表格和位置会保持在你想要的位置,在你的 1024 像素宽度内(见图 5–2)。如果用户的分辨率非常小,那么你的内容将会占据屏幕的大部分空间,他们将会被迫使用非常可怕的水平滚动条。
图 5–1。 分辨率为 1024 × 600 的固定宽度网页示例
**图 5–2。**2048×1536 分辨率的同一页面。注意两边的宽黑条
相比之下,灵活宽度的布局将试图适应所有尺寸的分辨率(参见图 5–3 和 5–4)。
**图 5–3。**1024×600 分辨率的可变宽度网页示例
图 5–4。 同一页 2048 × 1536 分辨率
现在,你可能已经开始看着你的智能手机或平板电脑,心想,“嗯……想知道这个东西的分辨率是多少?”你猜怎么着这也是大多数手机网页设计者想知道的。目前,随着 Android 每天激活大约 350,000 个新设备,设计人员和开发人员都意识到他们需要对 web 应用开发方法进行重大改变,以便与我们每天用来浏览 web 的大量设备保持联系。如果你喜欢固定宽度的方法,这是一个很难玩的游戏:我为什么分辨率构建我的移动应用?有一些简单的答案(“好吧,大多数人都有 iPhones,我只是为它而建”),但它们也有自己的缺点(“什么?!?他们做了一个更大的 iPhone,叫做 iPad…呃哦…”)。通过瞄准特定的设备,你也容易惹恼除了你的目标之外的任何设备的用户。
在这一章中,我们将为您提供一点“屏幕分辨率”也就是说,我们将尝试通过讨论您的移动 web 应用如何能够真正智能地理解用户正在使用的设备的分辨率,甚至方向,并自动适应它来解决这个问题。这就好像你将编码一个小大脑,说“嗯,这个设备有很大的宽度;让我们展示我们能展示的一切”或者“哦,不;这是一个小屏幕。我们不能并排显示这些信息!”作为一名设计师,我们可以利用小大脑,让它变得更加智能,让它以各种不同的方式向不同的设备显示相同的内容,进而向不同的用户显示。让我们从一个例子开始。
日常机器人
想象一下,你已经决定开始为 Android 用户发行一份日报,并且想出了一个很棒的标题:每日机器人。唯一的问题是,你们有些用户用的是一个摩托罗拉 Xoom,分辨率 2048×1536;有的在用三星 Galaxy Tab(1024×600 分辨率);还有一些人使用 Roccwest XTreme,出于某种奇怪的原因,它的分辨率为 1280 × 800。如果你的目标是这些设备中的一个,那么使用固定的宽度,另外两个看起来就不太对了。令人欣慰的是,我们可以编写一个在三种情况下看起来都不错的页面——参见图 5–5 到 5–7:
**图 5–5。**1024×600 分辨率的日常机器人
图 5–6。??【每日机器人】1280 × 800 分辨率
图 5–7。 每日机器人 2048 × 1536 分辨率
将这些数字放在一起比较可能会非常令人惊讶——内容完全相同,但布局发生了相当明显的变化。更令人惊奇的是,这个是同一个页面——我们的开发人员能够创建它一次,并让它足够智能地对这三种不同的分辨率 1 做出适当的反应。
但是我们没有平板的朋友怎么办?嗯,只要做一点点工作,我们也可以用日常的 Droid 智能手机版来容纳它们,如图图 5–8(纵向)和图 5–9(横向)所示。
图 5–8。 每日机器人 480 × 859 分辨率
在这种情况下,开发人员(Rocco)不知道编写叙述的人(Jon)会选择什么分辨率,但页面看起来仍然很棒。
图 5–9。??【每日机器人】859 × 480 分辨率
让我们来看看 Daily Droid 背后的代码,了解页面是如何构建的,以及我们如何确定它应该显示“智能手机”还是“平板电脑”版本。我们将在下一节讨论 HTML,然后在下一节讨论 CSS。通读下面的代码,根据注释,您应该对每个部分的功能有所了解。
每日机器人的基本 HTML 代码
我们已经把 HTML it 分成了几个部分,所以你可以在可管理的片段中浏览它。在第一部分,如清单 5–1 所示,我们创建了初始的 HTML 布局并指定了两个不同的标题。
清单 5–1。 每日机器人的 HTML 代码第一部分
`
The Daily Droid ` `The Daily Droid
Smartphone Edition
Tablet Edition
从清单 5–1 中的代码可以看出,智能手机版和平板电脑版文本都出现在 HTML 中。CSS(在本节后面的“每日 Droid CSS”中讨论)将选择正确的一个来显示。在 HTML 的第二部分,如清单 5–2 所示,我们将布局内容和文章空间,然后完成 HTML 结构。
清单 5–2。 每日机器人的 HTML 代码,第二部分
`
<!–
SECTION: FEATURED ARTICLES
The featured article would be the main article on the page
that will be featured. Think of it in this sense as the
front page story on a newspaper - which makes sense since
this demo’s completed code would be a mock vintage newspaper
layout.The article contains several sections. You have the header
section which contains the title of the article as well as
a “figure” or image that would be displayed with the article
and any caption text that would go along with it.
-->
Title goes here…
Figure caption…
Title…
Body Content…
现在让我们转向 CSS 和日常 Droid 的视觉呈现。
每日机器人的半魔法 CSS 代码
下面是用来设置日常 Droid 整体外观的 CSS 样式表。如您所知,CSS 将采用上一节中解释的普通 HTML 结构,并按照我们的指定对标签应用各种样式。我们将 CSS 分成几个部分来帮助解释它的作用。第一部分,如清单 5–3 所示,设置正文和一些标题的外观。
清单 5–3。 每日机器人的 CSS 代码,第一部分
/* CSS reset code only for the elements that will be used in our code. We could use a more robust CSS reset solution, but I am a firm believer that you should not riddle your stylesheet with code that you have no intention of using in your markup. */ html, body, h1, h2, h6, p, article, figure, figcaption header, hgroup, section { padding:0; margin:0; } /* General global styles to be used throughout the demo */ html, body { width:100%; overflow-x:hidden; } body { font-size:14px; font-family:"Times New Roman", Times, serif; line-height:20px;
background:url(bg.png); -webkit-box-shadow: inset 0 -5px 300px rgba(153,99,38,1); /* This inset box-shadow adds gives the page a nice vintage feel to it */ box-shadow: inset 0 -5px 300px rgba(153,99,38,1); } h1, h2 { font-weight:normal; } h1 { font-size:36px; line-height:42px; } h2 { font-size:20px; } h6 { font-size:16px; text-transform:uppercase; } p { margin:10px 0; } /* Header/Mast CSS code */ #mast { padding:20px 0 00; text-align:center; letter-spacing:1px; } #mast h1 { font-family:'UnifrakturCook', Georgia, "Times New Roman", Times, serif; font-size:62px; line-height:48px; }
现在我们已经有了一些 CSS,是时候看看在“平板电脑”和“智能手机”版本之间切换的代码了。默认情况下,我们希望显示 Tablet Edition,因此代码如清单 5–4 所示:
清单 5–4。 每日机器人的 CSS 代码,第二部分
#mast h6 { display:none; /* hiding both of the pages subheaders */ } #mast h6:nth-child(3) { display:block; /* displaying the "Tablet Edition" subheader by default */ } #mast time { display:block; margin:10px 0; border-top:double 6px #000; border-bottom:double 6px #000; text-transform:uppercase; font-size:16px; line-height:24px; } /*
`Article/Content styles.
This section will rely heavily on two new features
of CSS3: Flexible Box Model and Columns.The Flexible Box Model is probably one of my favorite
new features of CSS3. In a nutshell, it allows one to
take control of how their page is laid out, using a grid
of flexible boxes and essentially eliminating the need to
hack together layouts by improperly using floats in one’s
code.CSS3 Columns are another time saving new feature of CSS3
and allow a designer/developer to take a block of code
and automatically convert it into a column based layout
that is just perfect for a newspaper demonstration.
/
#content {
padding:0 10px;
display:-webkit-box; / here we are using the -webkit-box argument instead of
plain old “box,” so our code will work across newer and
older Android browsers*’
/
-webkit-box-orient: horizontal; / setting the box orientation to horizontal
displays the content in this container from
left to right instead displaying the content
in the traditional way of top to bottom /
}
#featured {
max-width:50%; / our featured article will take up half the width of the display /
height:100%; / our featured article will take up all of the available height of the
display /
box-flex:1; / tell our child elements to be evenly sized and take up one “box”
space /
-webkit-box-flex:1;
}
#featured .entry {
-webkit-column-count: 2; / this will display our featured content article text in 2
columns /
-webkit-column-gap: 20px; / here we add a hearty 20px gap/spacing between our
columns /
-webkit-column-rule: 1px solid rgba(91,58,21,0.5); / here we are adding a border to
our columns /
}
#regular {
margin-left:5px;
padding-left:10px;
max-width:49%;
box-flex:1;
-webkit-box-flex:1;
-webkit-column-count: 3;
-webkit-column-gap: 20px;
-webkit-column-rule: 1px solid rgba(91,58,21,0.5);
border-left: 1px solid rgba(91,58,21,0.5); / here we are adding a border to the
#regular container to match the rest of the columns’ borders /
}
#regular article {
stacking on top of each other /
}
article h1, article h2 {
margin-bottom:10px;
font-family:Bevan, “Times New Roman”, Times, serif;
}
article .entry {
text-align:justify; / to give the page a more realistic feel we will justify the
column text */
}
article figure {
width:90%;
padding:0;
margin:10px auto 20px auto;
}
articlefigcaption {
font-style:italic;
text-align:right;
}`现在我们将设置智能手机代码(在清单 5–5 中)并相应地调整布局。
清单 5–5。 每日机器人的 CSS 代码,第三部分
`/*
Android Smartphone Devices
Here we will use CSS3 media queries to determine
the resolution of our screen and present the user with
a completely different layout if their viewing
does not meet certain requirements.Here we are targeting smartphone devices that will,
on average, have a width of 320px (portrait) and up
to 569px (landscape).This layout will display the content in a more
commonly used smartphone style layout, presenting the
user with a list of articles that they can scroll up
and down to view.
/
@media screen and (min-width: 320px) and (max-width: 569px) {
body {
-webkit-box-shadow: inset 0 -5px 50px rgba(153,99,38,1); / lessen the shadow on
the page to adjust to the screen’s new dimensions /
box-shadow: inset 0 -5px 50px rgba(153,99,38,1);
}
h1 {
font-size:20px; / lower the size of the header font to accommodate the smaller
screen resolution /
line-height:24px;
}
h6 {
font-size:12px; / same as the h1 above it /
}
#mast h1 {
font-family:‘UnifrakturCook’, Georgia, “Times New Roman”, Times, serif;
font-size:42px;
}
#mast h6:nth-child(2) {
display:block; / since we are dealing with a smaller screen we will show the
“Smartphone Edition” subheader /
}
#mast h6:nth-child(3) {
display:none; / and hide the “Tablet Edition” subheader /
}
#mast time {
font-size:12px;
line-height:24px;
}
section#content {
-webkit-box-orient: vertical; / here we are telling this content to display
vertically instead of horizontally /
padding-bottom:15px;
}
#featured {
max-width:100%; / take up the entire width of the screen instead of half of it
/
}
#featured .entry {
-webkit-column-count: 1; / only display our text in a single column, which is
more appropriate for our screen real estate /
-webkit-column-gap: 0; / remove the 20px padding around columns /
-webkit-column-rule: none; / remove the border off our columns /
}
#regular {
margin-left:0px;
padding-left:0px;
max-width:100%; / like our featured article we will now take up the entire
width of the page /
-webkit-column-count: 1; / like our featured article we will display a single
column of text /
-webkit-column-gap: 0;
-webkit-column-rule: none;
border-left: none;
}
#regular article {
display:block; / display our articles as blocks so they appear vertical /
}
article .entry p, article figure {
display:none; / hide all of our article content so the user is not stuck
scrolling into oblivion /
}
article .entry p:first-child {
display:block; / display only the first paragraph of an article for the user */
}
article {
margin-bottom:10px;
border-bottom:2px solid rgba(0,0,0,1);
}
}`对于一份简单的报纸来说,这是很多代码;然而,它的美妙之处在于它的多功能性:一个 HTML 页面和一个 CSS 页面来管理所有设备——手机、平板电脑、Android 媒体播放器,以及其他任何有人安装 Android 的设备!让我们花一点时间,通过媒体提问来讨论这种神奇是如何发生的。
媒体查询
当您查看前面的代码时,您可能注意到的第一件事是,编程的非常流畅的老式报纸布局只包含两个相对较小的代码文件。五到七年前,在一个 web 开发人员必须戴着两顶不同的帽子(web developer hat 和 Internet Explorer 6 hacker hat)的地方,创建这样一个布局会是一个非常麻烦的任务,很可能包含两个(如果不是更多的话)完全不同的布局。每个布局都必须有自己的一组 HTML 和 CSS 文件,由一些后端服务器代码显示给客户端,这些代码查找设备的用户代理字符串。移动设备将被提供专门为移动设备设计的 HTML 和 CSS 模板。台式计算机将被提供等同于桌面的模板。代码版本之间没有融合或流动性。
快进到未来几年——我们正处于 HTML5 和 CSS3 的黎明——前景完全不同。目前,在我们生活的世界里,桌面互联网浏览器的开发和发布速度比大多数用户安装最新更新的速度还要快。在移动领域,它几乎同样进步,智能手机操作系统的新版本,以及相应的互联网浏览器的新功能丰富版本,每六到十二个月发布一次,如果不是更早的话!
这对你,移动 Web 开发者来说意味着你不会停留在过去,为十年前的浏览器编码。作为一个以 Android 用户体验为目标的开发者,你最多只需要担心过去一年半的 Android 版本的开发。专注于新设备而不必担心过多关注过去的技术会妨碍用户的体验,这种能力给开发人员带来了我们以前没有的自由。随着自由而来的是创新,随着创新而来的是更好的技术和功能,如 CSS3 媒体查询,这种技术让我们能够创建我们之前构建的美丽的“The Daily Droid”演示。
自 HTML4 时代以来,媒体查询已经以某种形式成为 web 开发的一部分。在字体标签和嵌套表格的黑暗时代,媒体类型通过控制与用户用来查看内容的媒体相关的样式和样式表而声名大噪(见图 5-10 和图 5-11)。例如,开发人员将为“打印”媒体类型分配一些样式,以从博客上的打印文章中删除所有广告,这样用户在尝试打印博客内容时就不会不必要地耗尽昂贵的墨水(参见清单 5–6)。
清单 5–6。 媒体查询示例 1:基于媒体类型隐藏或显示块
`
` 图 5–10。 在普通桌面网络浏览器中查看的 Android 思想主页
图 5–11。 打印时查看同样的安卓思想网页
开发人员还可以为“投影”媒体类型分配样式或样式表,以解决在会议室的投影仪上观看项目时网站标题中褪色的颜色(参见清单 5–7)。
清单 5–7。 媒体查询示例 2:根据媒体类型更改背景颜色
`
`然而,随着 CSS3 的出现,媒体类型的概念已经演变成更加漂亮和灵活的东西,这使得级联样式表能够不仅仅是一种为 web 文档和标记添加样式的“愚蠢”机制。当使用媒体查询时,感觉它们从一开始就应该是 CSS 的一部分。我听到我的一些朋友把媒体查询称为“自由”,甚至听到我认识的一个开发人员——当然,在一个漫长的编码夜之后——把媒体查询简单地称为数字时代的新“黑魔法”。事实上,它们都不是。媒体查询作为一种工具,当掌握时,将使您作为开发人员的工作更容易,并且在一天结束时,将为您提供一个漂亮灵活的布局,立即转换为用户的查看媒体,就在您的眼前!
如果您过去使用过 JavaScript 或任何其他脚本或编程语言,那么媒体查询对您来说可能很容易学会。基本上,我们所做的是为样式表分配逻辑,这将让客户端的浏览器在将正确的模板样式分配给正确的查看设备时完成所有繁重的工作。以下是使用 CCS 媒体查询的一个非常基本的示例:
<linkrel="stylesheet" media="screen and (orientation:portrait)" href="portrait.css" />
在本例中,当浏览器从垂直位置的移动设备查看应用或网站时,我们告诉客户端的浏览器加载“portrait.css”样式表。 2 不限于向链接标签分配媒体查询。媒体查询也可以直接添加到你的设备的 CSS 文件中,就像我们在前面的例子“The Daily Droid”中看到的那样。事实上,当使用@import 规则调用 CSS 文件以获得正确显示时,甚至可以调用媒体查询,如下例所示:
<style type="text//css"> @importurl(landscape.css) screen and (orientation:landscape); </style>
在下面的例子中,我们将有几个@import 规则导入到许多不同的 CSS 文件中,用于不同的布局类型(参见清单 5–8)。
清单 5–8*:媒体查询示例 3*
`
@import url(landscape.css) handheld and (orientation:landscape) and (max-
width:648px);
@import url(landscape.css) all and (orientation:portrait);
`
2 如果手机从横向模式切换到纵向模式,带有传感器来检测移动的设备通常会告诉软件,允许您的网页根据您定义的风格自动重新格式化。
我完全知道你在想什么,“如果我必须编写我的 web 应用来匹配连接到 16×9 显示屏的电视或设备的 Google TV Android 设备,会怎么样?!"您不必担心,因为 CSS3 媒体查询的灵活性已经涵盖了您的需求,如下例所示:
<link rel="stylesheet" media="all and (device-aspect-ratio: 16/9)" href="television.css" />
从前面的例子中可以看出,在一个由 HTML5 和 CSS3 支持的设备和应用迅速主导的世界中,媒体查询是任何 web 开发人员的武器库中一个不可思议的工具。要了解更多关于媒体提问的力量,请点击这里查看 W3.org 网站—
[www.w3.org/TR/css3-mediaqueries/#media0](http://www.w3.org/TR/css3-mediaqueries/#media0).
总结
在这一章中,我们已经讨论了很多关于你的网页的大小,以及这个大小是如何根据用来浏览内容的屏幕而变化的。现在我们已经解决了屏幕分辨率的问题,我们将放大一点,解决处理不同浏览器的最佳方式!
六、处理不同的浏览器平台
到目前为止,我们已经讨论了检测访问您的 web 页面或应用的设备类型以及适当处理它的方法。这涉及到特殊的 CSS 文件、格式问题等等。然而,正如任何优秀的面包师会告诉你的那样,把所有鸡蛋放在一个篮子里并不总是最明智的想法。这就是为什么,在这一章中,我们将后退一步,讨论您可以用来了解什么设备正在访问您的服务并采取适当行动的方法。
原因很简单:没有一种解决方案能解决所有问题。例如,您可能需要允许移动用户访问 web 应用,并且您可能会发现可以格式化页面,使其在桌面和手机上看起来都很棒。对于极其简单的布局,这通常是开发人员所做的。然而,对于更复杂的系统,可能需要创建一个完全独立的网站。中庸之道是构建一个在桌面、平板电脑或手机上都很好看的 HTML 文档。在这一章中,我们会给你一些你需要的工具来判断是什么设备在看你的页面,并且我们会提供一些关于你的页面如何对每个设备做出反应的想法。毕竟,就像没有两个网站是完全一样的——尽管很相似——也没有两个设备的行为是完全一样的(但谢天谢地,就像网站一样,有相似之处)。
元标签和视口
我们已经讨论了许多对于普通用户来说是隐藏的关于 HTML 的事情——使用的不同标签,不同的部分,比如
head
和body
,甚至像 CSS 和 JavaScript 这样的东西如何嵌入到 HTML 文档中。然而,元标签或元素是特殊的,虽然它们不会显示给用户,但它们通常会影响用户对页面显示或格式的体验。META 标签位于 HTML 页面的
head
部分,通常有两个元素,元素名和值。例如,以下值指定了与特定网页相关联的关键字:<**meta** name="keywords" content="android, howto, information" >
一点元历史
当搜索引擎首次开始索引互联网时,他们使用关键字和描述元素来理解给定网页的内容。在 20 世纪 90 年代末,全文搜索引擎(如谷歌)开始索引并使用给定网页的所有文本来确定页面包含的内容,这些
META
元素变得不那么重要了。事实上,一个完整的行业已经兴起,声称通过“优化”他们的网页来帮助网页所有者获得更多的流量,这通常包括更新搜索引擎使用的META
元素。这个行业的“搜索引擎优化”,或搜索引擎优化,今天仍然存在,事实上是一个非常残酷的业务类型,虽然许多搜索引擎寻找旧的“技巧”使用,并可能惩罚网页使用它们。例如,使用的一个技巧被非正式地称为“关键字填充”,这听起来就像是——用许多不同的术语填充META
关键字元素,其中一些可能在搜索引擎中得分很高,但在页面的实际内容方面并不准确。现代 SEO 公司必须依靠许多其他技术来提高页面的搜索排名,包括许多我们通常不认为是设计师的东西(例如,页面上有什么链接、页面标题、布局、措辞等等)。关于
META
标签的一件有趣的事情是,“官方的”META
标签比网络上存在的标签总数要少得多。各种生产网络浏览器的软件公司,如微软,可能决定构建他们的浏览器来检测“非官方的”META
标签并对其做出响应。例如,微软率先使用了 MobileOptimized
META
标签,该标签告诉其移动互联网浏览器(Pocket Internet Explorer 或 Internet Explorer Mobile)如何专门渲染使用该标签的页面。一些非微软生产的浏览器支持这种标签,但不能保证这种标签对竞争对手浏览器的用户会像对 Internet Explorer 用户一样有帮助。类似地,我们的老朋友 AvantGo(前面提到过)也使用了一个名为 HandheldFriendly 的标签来实现相同的目的,但也存在相同的问题。视口元素
所有这些困惑、竞争和不一致导致了被称为 Viewport 的新
META
元素的引入和相当广泛的接受,尽管仍然是非官方的,但它是移动开发人员感兴趣的最新“特殊”META
标签。视口可以被认为是网页顶部的窗口。有时候,整个网页适合窗口,而其他时候,我们希望窗口大小不同,这取决于我们如何构建页面。与以前的尝试相比,Viewport 标签更成功的一个原因是它能容纳的信息量。例如,一个简单的视口标记可能如下所示:<meta name="viewport" content="width=320,height=device-height" />
这段代码告诉移动浏览器,这个页面的内容应该是 320 像素宽,和设备的屏幕一样高。(如果你是为平板电脑设计的,你可能会把它调整到 800 像素宽。)为了更好地了解这将如何显示页面,请看一下 Figure 6–1。它显示“那条推特是谁?”我们在第二章中使用前面的视口设置制作的游戏。
图 6–1。 这里我们有“那条推特是谁?”设置了视口的游戏
注意页面的布局是如何大于手机的可用查看空间的?这是因为当我们将高度设置为设备的高度时,我们将宽度设置得太宽了——320 px——浏览器不知道任何关于初始比例的信息,正如页面底部的缩放按钮所证明的那样。在这种情况下,浏览器放大以显示页面的左上角,并提供缩放按钮,以便用户可以放大和缩小页面,根据自己的选择查看尽可能多或尽可能少的页面内容(虽然有时能够缩放页面上的内容很好,但如果我们可以在该页面上禁用该功能,则更好,这样我们可以保证我们的布局将按照我们预期的方式显示)。换句话说,浏览器对它应该如何显示这个页面做了一个有根据的猜测,但是由于把它拉到了左上方,它悲惨地失败了。它还可以显示所有缩小的内容,在这种情况下,所有 320 像素都适合,但文本会非常小。我们要给它更多的信息,这样它第一次就能正确显示。
幸运的是,Viewport 标签还可以包含关于页面缩放的信息——包括用户放大和缩小给定页面的能力。以下稍微复杂一些的 Viewport 标记指定了所有这些内容:
<meta name="viewport" content="width=320, height=device-height, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
这段代码告诉浏览器两件事。首先,它提供了比例值,允许浏览器知道您认为最大和最小的比例,以及最初设置比例的位置。在这个例子中,我们告诉浏览器,我们对页面进行了编码,因此它被设计为 100%可见,它不应该再变大或变小。这段代码添加的第二项是关闭用户放大和缩小选项的能力,如下面的图 6–2 所示。现在,我们不必担心我们的设计不会以我们希望的方式展示给用户。就我个人而言,我喜欢在构建移动网站或应用时总是剥夺用户缩放页面的能力。我知道有些人真的喜欢通过缩放天堂的能力,但在现实中,移动设备的屏幕空间非常有限,作为一名设计师或开发人员,我觉得你的工作是利用有限的屏幕空间,而不是让用户通过缩放来浏览你的成品。
图 6–2。 第二章的“那是谁的推特?”关闭用户可扩展的游戏
但是,如果你想要一个快乐的媒介,即你的应用应该自动放大,但也应该允许用户根据自己的意愿修改缩放比例,那该怎么办呢?那么像素更高的设备呢(比如谷歌 Nexus One,480 像素宽)?我们可以用几种方法来解决这个问题。第一种方法是删除
META
标签中的user-scalable=no
行,并针对某个屏幕密度调整比例值。这让META
标签给出初始值,但不约束用户。为了确定这是否是正确的举措,我们可以进行一些用户测试(即,调查人们对我们的移动界面的看法),或者如果我们真的很好奇,我们可以实现一些 javascript 代码来查看用户在做什么,然后将其写入日志(这超出了本书的范围,尽管资源确实存在,如本页的讨论:[
htmldoodads.appspot.com/zoom-level.html](http://htmldoodads.appspot.com/zoom-level.html)
)。我们还可以构建一个页面,根据设备像素密度以不同方式显示,这是我们必须在底层 CSS 中指定的,使用低密度(ldpi)、中密度(mdpi)和高密度(hdpi)标签,然后为每种情况指定不同的 CSS 格式。最后,如果我们有幸只为一个平台开发(例如,只有 Android 手机),我们可以研究浏览器的具体特性。在这种情况下,Android Webkit 浏览器会自动缩小文本元素的大小,以便它们适合屏幕(去查看在线报纸上的一篇文章,并放大一大块文本来查看这一过程)。如果这是我们的使用场景,那么我们就没有什么可担心的了。虽然这很容易让人相信,但你应该在 Android 设备上彻底测试你的页面。使用
META
标签作为额外的安全层来帮助内置浏览器也没有坏处。用户代理
有时,指定浏览器应该如何处理您的页面并不能满足您的需求。例如,也许你知道某些信息,不管它在移动设备上如何缩放或格式化,对于普通用户来说在小屏幕上处理太多了。也许你的页面使用了一堆 Flash 小程序,这些程序不能在 iPhone 或 iPad 等 iOS 设备上运行,你想把这些用户重定向到其他地方。也许你的网站上有一些特性和功能并不是在所有的应用中都可用,对于不太先进的浏览器来说需要禁用。最后,也许你只是想给出一个网址
[
mysite.com](http://mysite.com)
,让它自动将手机和平板电脑导向一个特殊的优化版本,同时向其他人显示整个页面。大多数网站实现这些目标的方式是通过读取访问者的 web 浏览器提供的用户代理字符串。让我们首先来看一个示例用户代理,然后看看我们如何在我们的应用中使用它。Nexus One 用户代理
用户代理字符串的格式是由 RFC 1945(HTTP 规范)制定的,其中包括该字符串的定义。该字符串由产品名称和版本以及可选注释组成。虽然这些是 RFC 1945 要求的字符串的一部分,但是许多供应商添加了额外的信息,例如操作系统、加载的扩展和平台细节。运行 Android 2.2 (Froyo)的 Google Nexus One 上的内置浏览器发送以下用户代理:
Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
这个字符串,分解后,翻译成:
- Mozilla 5.0 浏览器
- 运行在 Linux 操作系统上,特别是 Android 2.2
- 使用美国英语
- 在 Nexus One 手机上,运行操作系统的内部版本 FRF91。
- 它(注释指示)类似于 AppleWebKit 浏览器(版本 533.1)。
我们的 web 页面或应用可以获得很多信息(如果您查看 RFC,甚至可以获得关于引擎或当前浏览器提供的安全级别的更多信息)。利用这一点,我们可以将特定手机、浏览器、操作系统和语言的用户引导到我们为他们创建的特殊格式的页面,或者显示我们针对的浏览器的特定功能。
然而,对于用户代理检测有一个需要考虑的警告:用户代理欺骗。许多第三方浏览器,如 Android 上流行的 Dolphin HD 浏览器,允许用户设置自己的用户代理。这有多种原因,包括:
- 用户希望看到页面的桌面版本,不管它的格式看起来有多糟糕。
- 用户想要访问专门为另一个操作系统或浏览器构建的页面(即,可能 web 开发者还没有构建优化的 Android 版本,但是已经有了优化的 iOS 版本。)
- 出于这样或那样的原因,用户只是想在网站的日志中显示为桌面系统!想到的一个是开发者设置的移动用户希望查看的限制(即,仅向桌面用户显示特殊报价)。
对于用户代理欺骗,我们无能为力。毕竟,整个系统的设置围绕着被准确报告的用户代理。如果这是您所关心的问题,您可能需要使用除用户代理检测之外的替代方法来为您的用户提供正确的页面,而不管他们想要什么。这通常采用脚本的形式来测试浏览器的功能——然而,人们需要知道移动浏览器具有哪些细微的功能,哪些只有桌面浏览器才具有——这远远超出了我们在这里讨论的范围。
现在,您已经对用户代理字符串的用途有了基本的了解,让我们看几个例子,在这些例子中,我们检测最终用户的用户代理字符串。
PHP 用户代理检测
清单 6–1 展示了一个 PHP 示例,在这个示例中,我们将检测用户代理字符串并将其显示给用户。如果用户使用的是 Android 网络浏览器,那么他们将会看到总是令人愉快的笑脸(见图 6–3),但是如果他们试图在非 Android 驱动的设备上查看脚本,那么他们将会看到一张永远不受欢迎的皱眉脸(见图 6–4)。
清单 6–1。 PHP 用户检测代码
<?php $userAgent = strtolower($_SERVER['HTTP_USER_AGENT']); if(stripos($userAgent,'android') !== false) { echo 'You are using an Android web browser! :)'; } else { echo 'You are not using an Android web browser! :('; } ?>
为了理解这段代码是如何工作的,我们将一行一行地把它拆开。首先,我们定义变量
$userAgent,
,它获取请求页面的浏览器的用户代理字符串。然后我们使用 PHPstripos
函数——它在字符串中搜索一个字符串的出现——来解析用户代理以获得我们提供的值。如果在字符串中找不到这个值,在本例中是android,
,那么向用户显示一条消息。如果找到了,将显示另一条消息。这只是一个小例子,展示了如何使用 PHP 来检测用户代理字符串,但是在很多情况下,这种技术可能会让您省心。例如,在 PHP 中使用检测可能允许您在内容发送之前阻止它(通常 JavaScript 检测不会这样做)。此外,如果您的应用大部分是用 PHP 编写的,那么您可能更愿意用这种方式记录用户代理,而不是通过 JavaScript。
图 6–3。 使用 PHP,我们获取用户代理字符串,并使用它来决定向最终用户显示哪些内容
**图 6–4:**Drat!看起来此人没有使用 Android 浏览器!
JavaScript 用户代理检测
虽然 PHP 非常适合检测服务器端的用户代理字符串,但有时开发人员可能需要检测客户端的用户字符串。例如,假设您正在使用一个站点或应用,该站点或应用允许您将信息导出到用户计算机上的文本文件或二进制格式文件中,以便以后查看。在 Android 设备上,文本是没有问题的,但如果你的用户选择二进制格式,当它无法打开时,他们可能会感到困惑。因此,我们可能只想隐藏该选项,而让其他选项可用。幸运的是,使用 JavaScript 完成这项任务就像使用 PHP 一样简单。
介绍 JavaScript 代理检测代码
清单 6–2 中显示的 JavaScript 代码让我们快速体验了 JavaScript 中的检测是多么简单;它类似于 PHP。与上一段代码相比,这段代码唯一的主要区别是,我们没有像使用 PHP 那样将消息写入页面,而是选择向用户显示一个弹出对话框(参见图 6–5 和图 6–6)。
清单 6–2。 Javascript 用户检测代码
<script type="text/javascript"> var ua = navigator.userAgent.toLowerCase(); window.onload = function() { if(navigator.userAgent.match(/android/i)) { alert('Android Rocks!'); } else { alert('Yawn, I guess your boring Desktop browser is okay'); } } </script>
**图 6–5。**Android 2.3 姜饼设备上的警告对话框
图 6–6。 谷歌 Chrome 浏览器上无聊的警告对话框
使用 JavaScript 代理检测向不同平台展示不同内容
单一平台开发人员(例如,为 Android、iOS 或一个操作系统编写应用的人)的一个自然发展是跳到不同的平台。Web 应用非常适合这一点,因为它们很大程度上可以一次编码并轻松地“移植”到其他类似的架构上。然而,为了避免衍生版本成为一场噩梦(例如,Android 和 iOS 版本,需要您分别对两个版本进行添加),可能更容易的是只拥有一段可以根据其运行位置进行更改的代码。在本例中,我们将向您展示如何将上一节中的清单 6–2 中的 JavaScript 代码实现到一个 Web 应用中,该应用将根据其运行的位置显示不同的内容。
我们还将通过把 jQuery Mobile 用作这个应用的“框架”,让您体验一下在下一章中会经常看到的东西。如果你喜欢接下来几个屏幕的样子,那么你会喜欢阅读第七章。
让我们首先讨论我们的总体目标:显示下载应用的适当链接。在 Android 中,我们希望链接指向 Android Market(或者可能是已经开放的新的 Android 应用商店之一,比如亚马逊的应用商店)。在 iOS 中,我们希望链接指向苹果应用商店。我们还想展示适当的图形。让我们从构建一个显示 Android 链接的简单页面开始。我们首先需要获取图形(可以在 Android 品牌页面上找到,(
[www.android.com/branding.html](http://www.android.com/branding.html)
)以及苹果应用商店图形([www.apple.com/itunes/affiliates/resources/documentation/identity-guidelines.html](http://www.apple.com/itunes/affiliates/resources/documentation/identity-guidelines.html)
),并将它们放在与清单 6–3 相同的目录中。清单 6–3。 下载我们的 App HTML 页面
`
Download our App Our App!
******We have an application you can download in the Android Marketplace!
**We have an application you can download in the Apple App Store!
bugjr.com
您会注意到这个页面相当简单。如果您查看页面的内容,您会看到我们有两个内容块:第一个名为
androiddiv
,显示 Android Marketplace 的文本和图像。第二个是applediv
,显示苹果应用商店的文本和图片。这两个块在它们的 div 标签中都被设置为"display: none"
,这意味着默认情况下,两者都不显示。页面顶部是一个非常简单的 JavaScript 函数,它测试检测到哪个用户代理,并切换到适当的文本块(通过将显示设置为"block"
)。如果我们在 Android 网络浏览器中加载这个页面,我们会看到图 6–7:图 6–7。 在安卓浏览器中加载下载 App HTML 页面
然而,如果我们在 iPhone 上的 Safari 中加载这个页面,我们将会看到 Figure 6–8:
**图 6–8。**Safari 中下载 App HTML 页面
现在我们有了一个简单的方法来引导我们的用户找到正确的下载,而不需要他们点击某个图标!正如你所想象的,我们可以将同样的检测用于其他目的——向不同的用户显示不同的文本,显示不同的广告,等等……最好的部分是它都是用 HTML 和 JavaScript 编写的,这意味着如果你选择使用一个产品将你的 Web 应用转换成一个本地应用(我们将在第十三章中讨论,使用 PhoneGap 或 Titanium Mobile 等工具),你可以使用这个技巧为用户提供更高级别的定制!
既然我们已经讨论了在 PHP 和 JavaScript 中检测用户代理,我们将讨论如何使用 Apache Web 服务器来完成检测。
。htaccess 用户代理检测
这些类型的文件是通常与 Apache web 服务器相关联的配置文件。也称为分布式配置文件,
.htaccess
文件可以基于每个目录为 web 应用设置一系列规则和配置。如果服务器支持的话,通过使用 mod_rewrite 模块,.htaccess
文件可以用来控制将 URL 重写为更干净、更容易被人阅读的内容。的另一个有趣的用法。htaccess 文件将使用它来检测用户代理字符串,并在需要时将用户定向到不同的站点或子域。参见清单 6–4。清单 6–4。 举个例子。htaccess 文件
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{HTTP_USER_AGENT} ^.*Android.*$ RewriteRule ^(.*)$ http://android.yoursitesurl.com [R=301] </IfModule>
前面的代码首先检查 Apache 服务器是否支持重写代码,然后打开重写引擎并设置条件和规则。该条件在用户代理中检查 Android,如果找到,规则告诉 web 浏览器将请求重定向到
[
android.yoursiteurl.com](http://android.yoursiteurl.com)
而不是通常的[
yoursiteurl.com](http://yoursiteurl.com)
(或者用户输入的任何内容)。这种类型的检测是非常强大的,并且可能会惹恼一些用户。虽然用户可以通过关闭 JavaScript 来禁用 JavaScript 检测。htaccess 和 PHP 用户代理检测只能通过改变用户代理来“欺骗”,这不是所有浏览器都支持的。(值得注意的是,免费的 Dolphin HD 浏览器允许用户在 Android、iOS 和桌面之间轻松切换用户代理,这对于测试和欺骗非常有用!)此外,用户可能希望在他们的 Android 浏览器中查看完整的网页,虽然 PHP 方法允许您提供某种代码切换(即,用户可以单击的链接将设置一个 PHP 会话变量,告诉您的代码不要显示移动网站)。htaccess 用户代理检测不允许这样做。然而,在简单的情况下。htaccess 解决方案是最容易配置的。明智地选择您的检测方法!
总结
恭喜你!您已经完成了另一个章节,使用新发现的知识视窗和用户代理字符串,您将能够更好地处理可能不时出现的某些讨厌的用户界面问题。尽管这本书主要关注的是为 Android 设备构建 web 应用,但是认为你永远不会遇到需要开发跨所有平台的应用的情况是愚蠢的。使用我们在那里讨论的内容,您可以为您的应用定制一个高效、优雅的解决方案!