Adobe 最近宣布,Adobe Flash Professional CS5 将让 Flash 开发人员可以构建和部署原生 iPhone 和 iPod 触摸屏应用程序。随着 Flash Platform 不断扩展范围,覆盖更多设备,开发人员需要掌握针对多种屏幕尺寸和分辨率编写内容的技术。本文讨论的几种技术有助于开发人员编写出能够在任何设备上适当地显示的内容,无论设备的屏幕分辨率和像素密度是多少。

本文讨论的技术比较“初级”,涉及创建矢量和使用算法(尽管比较简单)动态地确定资产的大小和位置。对于某些应用程序,总是需要这种层次的控制,但是以后也会出现“更高层”、更简单的控制方法。

Adobe 当前正在开发一个移动 Flex 框架(代码名称是“Slider”),它会自动地应用这里讨论的一些技术,可以大大简化编写适合不同屏幕的应用程序的过程。但是,在 Slider 发布之前(以及对于那些可能不适合这个框架模型的应用程序),本文提供的提示和技巧可以帮助您进行多屏幕开发。

术语

在讨论针对多种屏幕尺寸编写基于 SWF 的应用程序的技术之前,有必要讨论一些相关的术语。尽管您可能熟悉这些术语的一般含义,但是为了实际使用它们,必须充分地理解它们:

  • 屏幕尺寸:屏幕尺寸是指屏幕的对角线长度,通常以英寸为单位。例如,iPhone 和 iPod 的触摸屏是 3.5 英寸的。我现在使用的 MacBook Pro 的屏幕是 15.4 英寸的。尽管屏幕尺寸与分辨率和 PPI 相关,但是无法仅凭屏幕尺寸判断出分辨率或每英寸像素数。
  • 分辨率:屏幕或显示器的分辨率是指屏幕上每个维包含的像素数量。iPhone 和 iPod 触摸屏的分辨率是 320 × 480 像素。Motorola Droid 的屏幕分辨率更高(像素更多),是 480 × 854。我现在使用的 27 英寸外部显示器的分辨率是 1920 × 1200。两个维的像素数相乘,就是屏幕可以显示的像素总数。
  • PPI、DPI 和像素密度:PPI(每英寸像素数)、DPI(每英寸点数)和像素密度都是指同一个概念:(在两个维中)单位物理距离内的像素数。iPhone 和 iPod 触摸屏是 163 PPI,这意味着在水平和垂直方向上每英寸有 163 像素。您可能不认为这个属性对于为多种屏幕尺寸编写内容很重要,但是 PPI 与分辨率一样重要,在某些情况下甚至更重要。

应用程序架构

多屏幕应用程序不必追求在每种设备上显示完全相同的外观;相反,它应该适应安装它的任何设备。换句话说,多屏幕应用程序应该根据设备的分辨率和 PPI 动态地调整,在大屏幕上显示更多信息,在小屏幕上删除或缩小元素,从而避免影响用户操作,比如确保按钮足够大。要想让应用程序适应不同的屏幕,必须以特定的方式设计它们,让它们在适当的时间按照适当的约束绘制和重新绘制本身。

Stage 缩放模式和对齐方式

在设置应用程序的布局之前,必须设置 Stage 的缩放模式和对齐方式。这应该在 Sprite 的构造方法中在注册 Stage 大小调整事件(后面详细解释)之前或之后进行:

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

把 Stage 的缩放模式设置为 NO_SCALE 表示不希望对内容进行任何自动缩放或自动布局,您要自己处理所有布局和缩放。这让应用程序能够根据不同的屏幕尺寸动态地调整本身。

把 Stage 的 align 属性设置为 TOP_LEFT 表示希望内容相对于左上角(坐标 0,0)进行布局。

监听 Stage 大小调整事件

在多屏幕应用程序中,执行绘制的最佳位置是 Stage 大小调整事件处理方法。在应用程序初始化和设置 Stage(应用程序必须使用的区域)的大小时,Stage 会发出大小调整事件。在纯粹的 ActionScript 应用程序中,需要在主 Sprite 的构造方法中监听 Stage 大小调整事件,如下所示:

this.stage.addEventListener(Event.RESIZE, doLayout);

在 Stage 上注册大小调整事件之后,当调整 Stage 的大小时会调用 doLayout。例如:

  • 应用程序首次初始化时。
  • 调整窗口大小时(在桌面上运行时)。
  • 设备改变方向时。

通过在 Stage 大小调整事件处理方法中执行布局,应用程序会在 Stage 的大小发生变化时自动地进行布局,无论变化的原因是什么。

注意: 使用stage.stageWidth 和 stage.stageHeight属性判断 Stage 的大小。

不必使用 SWF 元数据设置 SWF 文件的尺寸。实际上,如果这么做,在应用程序初始化时可能会阻碍调用大小调整事件处理方法。最好在应用程序描述符文件的初始窗口部分中设置应用程序的宽度和高度,如下所示:

<initialWindow> <width>320</width> <height>480</height> <!-- several other properties... --></initialWindow>

决定资产的大小

对于为在不同屏幕尺寸和分辨率的设备上运行而设计的应用程序,常常需要动态地决定资产的大小。例如,一个按钮在 iPhone 上的外观和可操作性很好,但是它在高分辨率的设备上可能太小了,用户无法看清或敲击它。

按像素考虑大小

要想在应用程序中添加单色背景,只需按像素考虑大小。例如,无论屏幕有多大,背景总是需要与屏幕的像素尺寸匹配。下面的代码在应用程序中添加适合任何屏幕大小的单色背景:

var bg:Sprite = new Sprite();bg.x = 0;bg.y = 0;bg.graphics.beginFill(0x006E59);bg.graphics.drawRect(0, 0, this.stage.stageWidth, this.stage.stageHeight); this.addChild(bg);

Stage 对象的 stageWidth 和 stageHeight 属性表示内容的 Stage 的像素尺寸。只需使用这些信息就可以创建适合任何大小的设备的应用程序背景。

按物理单位考虑大小

在可以相对地设置资产大小的情况下(比如背景),按像素设置资产大小是可行的;但在需要绝对地设置资产大小时,就不能这么做了。换句话说,无论屏幕多大,背景只需与整个 Stage 的大小匹配即可;但是,字体和按钮等元素的大小需要更精确的控制。在这种情况下,必须按物理单位或 PPI 考虑大小。

英寸

通过使用 PPI 决定资产的大小,可以精确地控制资产的大小,无论它在哪种屏幕上显示。例如,要想让按钮在大型桌面监视器和小型移动屏幕上都是 ¾ 英寸 × ¼ 英寸的,必须使用屏幕的 PPI。

注意: 研究表明,鼠标单击或手指敲击的目标不应该小于 ¼ 英寸或 7mm,否则会影响操作的一致性和可靠性。确保按钮在任何设备上都便于操作的惟一方法是按物理单位设置大小。

可以使用 Capabilities.screenDPI 属性判断当前屏幕的 PPI。当然,资产最终总是按像素而不是英寸设置大小,所以需要把 PPI 转换为像素数。我使用一个简单的实用程序函数,如下所示:

/** * Convert inches to pixels. */private function inchesToPixels(inches:Number):uint{ return Math.round(Capabilities.screenDPI * inches);}

下面的代码演示如何创建在任何设备上都显示为 ¾ 英寸 × ¼ 英寸的 Sprite:

var button:Sprite = new Sprite();button.x = 20;button.y = 20;button.graphics.beginFill(0x 003037);button.graphics.drawRect(0, 0, this.inchesToPixels(.75), this.inchesToPixels(.25));button.graphics.endFill(); this.addChild(button);
公制

除了英制单位之外还有公制单位,而且公制单位对于小尺寸更合适。下面的版本把毫米转换为像素数:

/** * Convert millimeters to pixels. */private function mmToPixels(mm:Number):uint{ return Math.round(Capabilities.screenDPI * (mm / 25.4));}

动态的布局

既然已经按适应多种屏幕尺寸的方式设计了应用程序,还掌握了决定资产大小的技术,现在该开始资产布局了。

为了能够适应不同的屏幕尺寸,资产布局的关键是了解什么可以硬编码,什么必须根据当前屏幕的属性计算出来。例如,在应用程序顶部创建标题栏时,您希望 x 和 y 坐标是 0,0,这意味着这些属性可以硬编码。换句话说,无论应用程序在哪种设备上运行,总是希望标题栏定位在左上角。下面的代码创建一个作为标题栏使用的 Sprite 并以硬编码方式设置它的位置:

var titleBar:Sprite = new Sprite();titleBar.x = 0;titleBar.y = 0;

尽管标题栏的位置在不同的设备上是不变的,但它的宽度并非如此。例如,在 iPhone 上,宽度应该是 320 或 480 像素(取决于设备的方向)。在分辨率更高的设备上,需要更大的宽度。

很容易使用 stage.stageWidth 属性决定标题栏的宽度,但是高度呢?可以按像素硬编码高度,但是根据分辨率不同,它的大小在不同的设备上会有很大差异。在这种情况下,更好的方法是按物理单位设置,这会让标题栏在所有设备上显示一致的外观。

下面的代码创建一个标题栏,它演示以下概念:

  • 在适当的情况下,硬编码绝对位置
  • 使用 stage.stageWidth 按像素动态地决定标题栏的宽度
  • 为了确保在所有设备上显示一致的外观,按英寸设置标题栏的高度
var titleBar:Sprite = new Sprite();titleBar.x = 0;titleBar.y = 0;titleBar.graphics.beginFill(0x003037);titleBar.graphics.drawRect(0, 0, this.stage.stageWidth, this.inchesToPixels(.3));titleBar.graphics.endFill();this.addChild(titleBar);

以上示例演示如何动态地设置资产的大小,但是如何动态地定位呢?标题栏的位置很明确,它总是放在左上角;但是,应该如何定位页脚呢?页脚的 x 坐标总是 0,但是 y 坐标取决于 Stage 的高度。

下面的代码演示如何创建页脚,这个页脚总是横跨应用程序的整个宽度,而且无论屏幕有多高,它总是定位在底部:

var footer:Sprite = new Sprite();footer.graphics.beginFill(0x003037);footer.graphics.drawRect(0, 0, this.stage.stageWidth, this.inchesToPixels(.3));footer.graphics.endFill();footer.x = 0;footer.y = this.stage.stageHeight - footer.height;this.addChild(footer);

相对定位

资产布局有三种主要方法(其中两种已经讨论过了):

  1. 使用硬编码的位置,比如对应用程序的背景和标题栏的定位
  2. 计算出位置,比如对应用程序页脚的定位
  3. 根据其他资产计算出位置

根据另一个资产计算出资产的位置称为“相对定位”,它对于设计多屏幕应用程序非常重要。仍然以标题栏为例,我们已经创建了总是按我们的期望定位和显示的标题栏,但是标题本身呢?

可以硬编码 y 坐标,把标题定位在顶部下面几个像素的地方。然后,根据 Stage 的宽度和标题的宽度计算 x 坐标。但是,由于两个原因,这不一定会产生最好的结果:

  1. 因为标题栏的高度会根据屏幕的 PPI 变化,文本不一定会垂直居中。
  2. 如果由于任何原因决定移动标题栏(例如,想去掉页脚,把标题栏放在底部),那么还必须修改标题的代码。

相对于标题栏定位标题可以解决这两个问题。因为这种做法很常用,我为此编写了一个简单的实用程序函数:

/** * Center one DisplayObject relative to another. */private function center(foreground:DisplayObject, background:DisplayObject):void { foreground.x = (background.width / 2) - (foreground.width / 2); foreground.y = (background.height / 2) + (foreground.height / 2); }

通过使用 center() 函数,很容易定位标题:

var title:SimpleLabel = new SimpleLabel("My Application", "bold", 0xffffff, "_sans", this.inchesToPixels(.15));this.center(title, titleBar);this.addChild(title);

自适应的内容

动态地设置标题栏等元素的大小和位置并不困难,但是实际的应用程序内容比较难处理。例如,假设一个游戏的主要内容是一个由正方形组成的格子。让这个游戏在多种设备上都便于操作的最佳技术是什么?应该根据屏幕尺寸放大或缩小正方形,还是应该添加或删除行和列?

应该根据游戏的规则选择适当的方法。例如,对于象棋或跳棋游戏,不能根据屏幕尺寸添加或删除行或列。在这种情况下,通常应该放大或缩小内容以便保持一致。

一些游戏实际上可以根据屏幕尺寸调整游戏内容。例如,实时战略游戏在大屏幕上可以增强,因为高分辨率可以容纳更多 tile;在小屏幕上,最好删除一部分 tile,让余下的 tile 更大,可以显示更多细节。在这种情况下,需要调整内容。

由于内容的差异很大,对于让内容适应不同的屏幕尺寸没有通用的战略或公式,但是有几种标准的技术。下面说明让游戏板适应任何屏幕尺寸的逻辑:

  1. 决定 tile 或块的大小。如果 tile 包含位图,大小将由位图的像素大小预先确定(因为位图不能像矢量那样缩放)。如果 tile 是矢量,可以为 tile 设置标准化的绝对大小。
  2. 判断必须在多大的空间里布置 tile。布置 tile 的空间应该是屏幕的总尺寸减去标题栏、导航栏等元素的空间。
  3. 计算余下的空间中容纳的行和列数。一定要考虑到正方形或 tile 之间需要的间距。
  4. 在可用空间中布置 tile。这需要点儿技巧,因为在游戏板上下通常会余下一些空间,您很可能希望这些空间平均分配在上面和下面。

下面的代码在分配的空间中布置尽可能多的 ¼ 英寸的块,同时确保游戏板上下的空白边相等:

// Display as many blocks on the screen as will fitvar BLOCK_SIZE:Number = .25;var BLOCK_BUFFER:uint = 3;var blockSize:uint = this.inchesToPixels(BLOCK_SIZE);var blockTotal:uint = blockSize + BLOCK_BUFFER;var cols:uint = Math.floor(this.stage.stageWidth / blockTotal);var rows:uint = Math.floor((this.stage.stageHeight - titleBar.height) / blockTotal);var blockXStart:uint = (this.stage.stageWidth - ((cols * blockSize) + ((cols - 1) * BLOCK_BUFFER))) / 2;var blockX:uint = blockXStart;var blockY:uint = ((this.stage.stageHeight + titleBar.height) - ((rows * blockSize) + ((rows - 1) * BLOCK_BUFFER))) / 2;for (var colIndex:uint = 0; colIndex < rows; ++colIndex){ for (var rowIndex:uint = 0; rowIndex < cols; ++rowIndex) { // Use a private function to draw the block var block:Sprite = this.getBlock(blockSize); block.x = blockX; block.y = blockY; this.addChild(block); blockX += blockTotal; } blockY += blockTotal; blockX = blockXStart; }}

下面的代码是生成每个块的函数:

/** * Get a new block to add to the game board */private function getBlock(blockSize:uint):Sprite{ var block:Sprite = new Sprite(); block.graphics.beginFill(0xAAC228); block.graphics.drawRect(0, 0, blockSize, blockSize); block.graphics.endFill(); block.cacheAsBitmap = true; return block;}

注意: 在创建每个块时,把它的 cacheAsBitmap 属性设置为 true。尽管移动应用程序的优化超出了本文的范围,但是对于不需要经常缩放或旋转的 DisplayObject,最好把 cacheAsBitmap 属性设置为 true。这会改进在桌面机上的性能,而对于处理器能力不强的设备,效果非常显著。

管理字体

字体是几乎所有应用程序的关键元素之一,在针对多种屏幕设计应用程序时,必须像其他资产一样小心地处理字体。下面是关于以适应不同设备的方式使用字体的三个提示:

  • 使用FTE (Flash Text Engine): 强烈建议使用 FTE,即 Flash Player 10、Adobe AIR 1.5 和 Flash Lite 4 中新增的 Flash Text Engine。FTE 不但显示效果比 TextField对象好,而且允许更精确地定位文本。可以使用 TextLine 的ascentdescenttextWidth 和 textHeight 等属性精确地定位文本。
  • 考虑创建组件: 在前面的标题示例中,我使用了自己开发的非常简单的 SimpleLabel 组件,它封装使用 FTE 的代码,可以显著简化创建文本的过程。通过这样做,不但在需要添加文本的每个地方都减少了几行代码,还提供了一个控制文本的中心位置,可以在这里进行全局文本修改或纠正与文本相关的 bug。
  • 如果需要的话,覆盖宽度和高度获取方法: 在我的 SimpleText 组件中,覆盖了 DisplayObject 对象的 width 和 height 属性,这让文本字段与 center() 等实用程序函数更好地配合。下面的 width 和 height 获取方法对于我来说效果最好:
public override function get width():Number{ return this.textLine.textWidth;} public override function get height():Number{ return (this.textLine.ascent - 1);}

结束语

随着 Flash Platform 的发展,Flash 开发人员的机会越来越多了。Flash 开发人员可以使用相同的工具、技能和代码构建应用程序,它们可以在越来越多的设备上运行,这让他们有机会为数量空前的用户提供应用程序。但是,为了利用 Flash Platform 宽广的覆盖面,开发人员需要在构建应用程序时考虑到适应多种屏幕。幸运的是,只需理解并掌握几种相当简单的技术,开发人员就可以非常充分地利用 Flash Platform 的价值。

为多种屏幕尺寸编写移动Flash内容相关推荐

  1. WebApp最佳实践用户体验篇之如何针对多种屏幕尺寸设计合理的移动应用

    身为一个移动web网站的设计师,除非你只是针对某种特定的设备设计,否则你应该会常常碰到这样的问题:如何清楚地了解网站运行设备的屏幕尺寸大小?这个问题一直困扰着移动设备上的设计师. 例如: iPhone ...

  2. 创建支持多种屏幕尺寸的Android应用

    负责人:冰凝 原文链接:http://developer.android.com/guide/practices/screens_support.html Android涉及各种各样的支持不同屏幕尺寸 ...

  3. android支持多种屏幕

    术语和概念 屏幕尺寸 实际的物理尺寸,测量屏幕的对角线. 为简单起见,Android的组中的所有实际的屏幕尺寸分为四个广义大小:小,正常,大,超大. 屏幕像素密度 屏幕的物理区域内的像素的数量,通常简 ...

  4. html5开发之ios屏幕适配,iOS开发屏幕尺寸以及屏幕适配等问题(转载内容)

    原帖地址:http://blog.csdn.net/phunxm/article/details/42174937/ 仅供我个人收藏学习,原博主如不同意请联系qq651263878进行删除,在此表示感 ...

  5. Android 获取屏幕尺寸与密度

    遇到一个问题,我的地图浮标图片在WVGA手机上正好,在QVGA上就显的太大,所以我要根据屏幕的不同调整浮标的大小使其在QVGA大小合适.有的同事提出了依据分辨率来区分不同的屏幕,但是单WVGA就支持好 ...

  6. android获取屏幕尺寸、密度

    http://developer.android.com/reference/android/util/DisplayMetrics.html DisplayMetrics metric = new ...

  7. Android---Android 屏幕尺寸与密度

    Android 屏幕尺寸与密度 2011-10-11 23:15:37|  分类: Android|字号 订阅 针对dip和px 的关系,做以下概述: HVGA屏density=160:QVGA屏de ...

  8. 小程序 富文本自适应屏幕_自适应文本:跨屏幕尺寸构建可读文本

    小程序 富文本自适应屏幕 Many of you may already know about responsive web design. Cited from Wikipedia, respons ...

  9. ios屏幕尺寸和分辨率

    iOS平台家族成员主要包括iPhone.iPod Touch和iPad,但是各类设备的分辨率各不相同,目前存在的尺寸主要有: iOS设备的尺寸多种多样,此外,屏幕的分辨率也有多种,总结如下表所示: 其 ...

最新文章

  1. Trie树检索字符串
  2. mysql更新一个表里的字段等于另一个表某字段的值
  3. php 字符串替换函数,php字符串替换函数str-replace速度比preg-replace快
  4. 基于深度学习的图像分类Image classification with deep learning常用模型
  5. ref 和out 关键字
  6. 866. 试除法判定质数
  7. 网络合作伙伴通信协议指南:NETWORK ASSOCIATES GUIDE TO COMMUNICATIONS PROTOCOLS
  8. STP重新收敛过程和补充内容
  9. conda An unexpected error has occurred
  10. Python pytz时区转换
  11. 迁移oracle数据库,简简单单的Oracle数据库迁移方法
  12. 服务器上系统使用排行,服务器操作系统使用排行榜
  13. 并发编程(十)ThreadPoolExecutor源码分析、拒绝策略、队列、示例代码
  14. 深度学习图片分类实战学习
  15. 大学英语B-必考词汇400个
  16. 牛客网拼多多校招最大乘积
  17. Shell脚本-批量生成100个账号
  18. mysql create table as select from_CREATE TABLE 表名 AS SELECT 语句
  19. html中如何让两张图片的间隙消失,css怎样处理图片间隙问题?
  20. The file Tomcat8.exe was not found... Either the CATALINA_HOME environment variable is not defined c

热门文章

  1. 使用Azure Data Factory优雅的迁移SQL Server 2000 DTS包
  2. 又一主播逃税被罚!快手主播“驴嫂平荣”被追缴并罚款6200.3万元
  3. IDC:2021年全年中国市场折叠屏产品规模约150万台
  4. 微信加入新功能,60秒语音不必从头听到尾,网友:还需要进度条
  5. 爆款预定!雷军再曝小米12 Pro:首发自研芯片澎湃P1
  6. 优酷《女心理师》热播 产后抑郁等话题引热议
  7. 周子学辞任中芯国际董事长
  8. 国产特斯拉Model Y已开始向欧洲用户交付
  9. 这届年轻人,连泡面也买不起了
  10. 100家店干翻17000家药店!刘强东最恐惧的对手来了!