`
peq335id
  • 浏览: 15594 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

创建flex组件

阅读更多

创建flex组件
2010年08月25日
  现在,考虑一下当应用程序更改标签的字体时会发生什么。记住,Flex 的 UI 依赖于异步处理,因此任何更改都不会立即生效。在更改字体时,您可以同时创建一个新的 UITextField,或者存储一个新的字体上下文和一个表明字体已经更改的标记。当下次呈现该组件时(通常发生在下一次屏幕刷新),您就可以应用新的字体。检查表明字体状态变更的标记是否改变,然后创建一个对应的 UITextField。有可能在两次屏幕刷新之间多次更改这些属性,但这让变更处理的效率下降。更好的策略是等待下一次屏幕刷新,然后再应用更改。注意,终端用户不会发现任何变化,因为屏幕的刷新频率下降了。这是针对任何异步、事件驱动 UI 的典型用例。应用程序存储需要应用的变更、对这些变更进行排序、然后在适当时间应用它们。您可能要问,什么时候才是最佳时间。这正是 LayoutManager 处理的任务。当您收到一个对组件的 commitProperties() 的回调时,就可以确定这是再次呈现该组件之前的最后一个调用;在这个调用之后 对属性所做的任何变更都不会出现在即将发生的屏幕刷新中。这些变更必须在下一次屏幕刷新和调用 commitProperties() 时才被应用。 这些都好理解,但您可能很想知道如何告知 LayoutManager 根据组件执行验证。假设某人更改了标签的字体,然后您存储了新的字体和相关标记,现在您需要让 LayoutManager 再次调用验证阶段。您可以为相应的组件调用一个称为 invalidateProperties() 的方法来实现验证。现在,我们看看更改标签的文本所需的代码。清单 2 显示了如何处理验证阶段(为了保持简洁,省略了一些代码)。 清单 2. 处理验证阶段 public function set text(value:String): void { _text = value; textChanged = true invalidateProperties(); } 注意,_text 是临时存储新的文本值的字段,而 textChanged 是用来标记更改的标记。此外还要注意为了通知 LayoutManager 开始验证阶段而进行的 invalidateProperties() 调用。清单 3 显示了 Label 类的 commitProperties() 中的对应代码片段(注意,为了保持简洁我省略了一些代码): 清单 3. 使用 commitProperties override protected function commitProperties():void{ if (textChanged) { textField.text = _text; textChanged = false } 这个被覆盖的方法演示了当标记被设置为 true 时,如何更新 UITextField(textField),以及如何将该标记重新设置为 false 以在未来进行标记。如果您希望使用 Flex 创建定制控件,那么这是必须理解的关键点。在清单 2 和清单 3 中讨论的验证阶段展示了 Flex 呈现引擎的 3 大基础支柱之一。这也是最容易被忽视的阶段,有许多高级的组件甚至没有验证阶段。性能考虑是忽略验证阶段的部分原因。在发生更改时就立即应用它们一般不会引起错误,但是无目的、不必要地多次应用变更会导致 Flex 应用程序的性能问题(一般情况是小问题,但也可能是大问题),理解这点非常重要。 开发人员通常在两种情况下编写组件。第一种情况是,编写一个与应用程序用例紧密结合的组件。通常,这种应用程序还不适合重用,因此可以适当牺牲性能以避免组件过于复杂。第二种情况是,编写适合在框架级别使用或由其他开发人员使用的组件。对于这种情况,尽可能提高组件的性能是值得的。一般在第二种情况中才需要认真处理验证阶段。 度量阶段详解 度量阶段是另一个重要的 Flex 阶段,它比提交阶段更常用。在组件通过了验证之后,LayoutManager 将继续度量组件,使它能够显示在特定上下文中。例如,LayoutManager 可能将组件显示为特定容器的子容器。您需要使用度量阶段,因为它帮助 LayoutManager 确定父容器是否包含滚动条。一些组件可以根据其子组件正常显示所需的空间调整自身的大小。考虑 VBox 示例,它是一个垂直排列其子容器的容器。如果您没有给 VBox 分配 height 或 width 值,它就在每次添加子容器时重新调整大小。它的 height 足以包含所有垂直排列的子容器,除非您设置某些限制。Flex 包含一个称为 measure() 的保护方法,您可以用它度量组件。LayoutManager 在适当的时间(一般在下一次屏幕刷新之前)调用这个方法,您需要在这个时间点度量组件并使用 measuredWidth 和 measuredHeight 设置 height 和 width。然后,父容器使用这些属性度量它本身。 首先度量子容器 与验证阶段相反,度量阶段是自下而上的。这是因为必须在度量父容器之前度量子容器。这确保当父容器收到度量调用时,已经度量了它的子容器。到目前为止,一切进展顺利。但是,现在假设您显式地指定了组件的 height 和 width。Flex 将这些存储的值指定为 explicitWidth 或 explicitHeight 属性。Flex 将考虑您在这种情况下指定的 width 和 height 值。不过,有时给容器设置显式度量是不明智的,因为您可能不能预先知道容器的所有子容器的总大小。 对于这种情况,Flex 给超出指定界限的子容器添加一个滚动条。注意,这些滚动条仅出现在扩展 Container 类的容器上。对于其他控件,滚动条可能出现,或者 Flex 会剪切掉一部分内容区域(称为内容切除)以保持您指定的大小。 显式地设置属性值 显式地设置 width 和 height 值将导致一个有趣的问题。如果您编写一个包含其他组件的组件并希望度量容器的大小,那么了解每个子容器的 width 和 height 将有帮助。您可能很想知道怎样才能知道特定组件的大小是被显式地指定的,或通过覆盖度量方法进行度量。回想一下,度量大小包含在 measuredWidth 和 measuredHeight 等属性中,而显式定义的大小包含在 explicitWidth 和 explicitHeight 中。仅有一对度量包含实数值,而另一对度量将包含 Not-a-Numbers (NaN)。Flex 通过提供两个方法解开了这个谜团:getExplicitOrMeasuredWidth() 和 getExplicitOrMeasuredHeight()。您仅需调用这些方法,而不必担心 height 和 width 值是否被度量或显示地设置。当一个组件被度量之后,就需要调用 setActualSize() 方法,它将设置 width 和 height 属性。只要显式地设置了 height 和 width,同时也就设置了这些属性。清单 4 演示了使用显式的 width 和 height 值创建文本输入组件有多么简单。清单 4 接收 4 个属性: 清单 4. 输入 width 和 height 
  这个例子包含 4 个属性:width、height、explicitWidth 和 explicitHeight。注意,measuredWidth 和 measuredHeight 保持为 NaN。 现在,看一看清单 5,其中没有设置任何显式的 height 或 width 值: 清单 5. 组件度量 在这个例子中,组件本身提供了度量。就像在 Flex 框架的另一个地方一样,这里的 "默认" width 和 height 值被设置为 measuredWidth 和 measuredHeight。显式的值仍然保留为 NaN。无论哪种情况,getExplicitOrMeasuredWidth() 和 getExplicitOrMeasuredHeight() 都返回正确的值。类似地,Flex 为 explicitMinWidth 或 measuredMaxWidth 设置最小的大小,以为组件提供最小和最大的界限。当组件的大小超出 maxWidth 指定的界限时,滚动条将显示当前视图区域内看不到的内容。注意,当设置了显式大小时,LayoutManager 将不调用 measure()。这是有意义的,因为当您显式地定义了大小之后,就没有必要再次度量组件。 调用 invalidateSize() 将告知 LayoutManager 初始化度量阶段。LayoutManager 包含 3 个不同的队列:invalidatePropertiesQueue、invalidateSizeQueue 和 invalidateDisplayListQueue。这些队列与在生命周期的某个点上调用 invalidateProperties()、invalidateSize() 和 invalidateDisplayList() 的组件对应。然后,LayoutManager 从每个队列中处理对应的组件,并调用每个组件的 validateProperties()、validateSize() 和 validateDisplayList() 方法。然后,这些方法中的默认实现 UIComponent 将调用 commitProperties()、measure() 和 updateDisplayList()。您可以覆盖这些方法以编写定制的逻辑。 度量组件可能还涉及到度量文本。然而,文本的行为与其他控件大不相同。度量文本要求您考虑升序、降序和行距等。幸运的是,Flex 提供的一个实用程序简化了这一过程。UIComponent 公开称为 measureText() 和 measureHtmlText() 的方法帮助您度量文本控件。清单 6 显示了如何度量文本字段:  清单 6. 度量文本字段
  package components { 
  import flash.text.TextLineMetrics; 
  import mx.core.UIComponent; 
  public class MyLabel extends UIComponent { 
  private var _text : String; 
  public function set text(value : 
  String) : void { 
  _text = value; 
  invalidateSize() 
  } 
  public function get text() : String { 
  return _text 
  } 
  override protected function measure(): void { 
  if (!_text) return super.measure(); 
  //measure text here! 
  var textLineMetrics : TextLineMetrics = 
  super.measureText(_text); 
  super.setActualSize(textLineMetrics.width, 
  textLineMetrics.height); 
  } 
  这段代码创建了一个简单的扩展 UIComponent 的 MyLabel 类,因此您仅需关注度量阶段。注意,您将在设置文本时调用 invalidateSize(),它通知 LayoutManager 在下一次屏幕刷新期间将组件添加到它的 invalidateSizeQueue()。然后,LayoutManager 调用组件的 validateSize() 方法,它是在 UIComponent 中定义的。最后,validateSize() 调用您曾经覆盖的 measure() 方法。这个调用使您能够设置控件的大小。您可以简单地将 width 设置为 200,并将 height 设置为 45,然后接受最后的结果。MyLabel 类的所有实例将共享相同的大小,这似乎不是好事情,因为它首先就不支持使用类似于 Flex 的健壮 UI 开发工具。但是使用了固定大小时,您就不需要覆盖 measure() 方法,甚至可以在将组件添加到其父组件时定义 width 和 height。清单 7 显示了度量标签控件的 2 个变体。
  清单 7. 度量标签
   
   
   
   
   
  在这个例子中,将调用 label1 的 measure() 方法,因为您没有显式地定义它的大小。然而,label2 的 measure 没有被调用,因为您显式地定义了控件的大小。注意,Flex 的 Label 类中的 measure() 实现的功能不仅仅是调用 measureText()。您需要处理左边、右边、顶部和底部的边框填充。但基本原理是一样的。
  度量阶段是 Flex 组件的生命周期中的重要阶段。尽管这是一个重要的阶段,但您很少需要关注它,除非您从头开始构建组件。大部分定制的 Flex 组件可能忽略了这个阶段,并将它留给 Flex 处理。Flex 在处理类似的琐碎事情方面表现非常出色,让您从乏味的度量任务中解脱出来。不过,如果您需要为 Flex 框架编写一个新的组件,那么就需要精通这个阶段。
  布局阶段详解
  布局阶段是 Flex 框架的 3 大生命周期阶段中的最后一个。您需要在这个阶段上花费大量时间,以致于很难将其看作是一个阶段。所有图形工作都发生在这个阶段,包括皮肤和艺术性增强等。
  假设您拥有一个经过适当验证和度量的组件。下一步就是考虑它的布局。布局阶段处理组件的许多方面。例如,您需要在这个阶段处理所有背景图像。您还需要打包在这个阶段中需要使用皮肤的所有组件。在这个阶段中,还可以将组件移动到理想位置。再次以 VBox 为例,这是一个垂直排列的容器。当您向它添加子容器时,您必须以垂直的方式排列它们。这种排列发生在布局阶段。
  Flash 坐标系的工作原理
  我将引导您了解如何使用 Flex 将子容器移动到 VBox 中,但我们首先温习一下 Flash Player 的坐标系。任何组件的左上角都由 x 和 y 值表示。每个组件的 x 和 y 值都与它的直接父组件相关。x 轴在右边为正值,但是 y 轴在下方为正值(这与传统的上方为正值相反)。因此,如果您在 VBox 中放置了一个标签,其 x 和 y 值分别为 30 和 40,标签的左上角距右边 30 像素,并且在 VBox 左上角下方 40 像素处。每个组件都有 mouseX 和 mouseY 属性,它告诉您组件的鼠标指针的相对位置。例如,如果 mouseX 为 -46,mouseY 为 78,那么鼠标指针在组件的坐标系中为向左 46 像素,向下 78 像素。除了局部坐标系之外,Flex 还有一个全局坐标系,该坐标系从整个应用程序的左上角度量 x 和 y 坐标。这些坐标称为 globalX 和 globalY。
  Flex 管理大量更改
  在其生命周期中,一个组件经历一系列的转换、旋转、缩放、剪切和拉伸,最后才显示在屏幕上。每个组件都有一个与之关联的 matrix 属性;这个属性包含关于所有这些调整的信息。因此,x和 y 坐标、globalX 和 globalY 坐标都通过这些矩阵转换关联起来。获取 x 和 y 值通常需要向 globalX 和 globalY 应用矩阵转换。从 x 和 y 坐标获取 globalX 和 globalY 坐标值需要执行反向转换。Flex 隐藏了所有这些细节,并提供两个简化这些转换过程的方法:localToGlobal() 和 globalToLocal()。您可以正确地使用这些方法,而不用担心底层转换。但是,一定要注意:函数是在点级别上工作的,而不是组件级别。让我们再看看一个基于 VBox 的例子。清单 8 在 VBox 内部创建了一个标签:
  清单 8. 在 VBox 内部创建标签
   
   
   
  box 和 myLabel 都有 localToGlobal() 方法。假设您想要获得 label 的全局位置。您的第一个想法可能是使用 label 的父容器的 localToGlobal,因为 label 的 x 和 y 坐标都与它的父容器 box 的 x 和 y 坐标相对应。不过,myLabel 拥有相同的方法,因此您也将调用该方法。结果是这两种方法都正确,但您需要使用不同的参数调用它们。您可以使用 box.localToGlobal(new Point(myLabel.x,myLabel,y)) 或 myLabel.localToGlobal(new Point(0,0))。当您调用 box.localToGlobal(new Point(myLabel.x,myLabel.y)) 时,就是请求 Flex 提供 VBox 中的点的全局位置,其坐标为 myLabel.x 和 myLabel.y。注意,这与 myLabel 无关。
  获得精确的全局坐标
  假设 myLabel 的 x 和 y 坐标分别为 40 和 30。在这个例子中,您要求获得 VBox 中的一个点 (40,30) 的精确全局位置。在这里,将对 VBox 矩阵进行转换。myLabel 的坐标系的左上角为 (0,0) -- Flex 组件都是这样。这意味着在第二个选项中(考虑到 myLabel 的坐标系),您要求 Flex 提供在 myLabel 的坐标系中为 (0,0) 的点的全局位置。不同的方法得到相同的结果,因为它们都从不同的坐标系中选择相同的点。如果没有理解这一区别,在本文的后面可能会引起错误和困惑。
  添加工具提示
  使用 Flex 时,有几个重要的原因要求您获得全局位置。例如,考虑一个典型的用例,即为组件显示工具提示。组件提示被添加到 Flex 应用程序的 systemManager,因此它们位于全局坐标系的内部。不过,您需要为位于其父组件局部坐标系中的组件显示工具提示。因此,Flex 挑选对应组件的右下角附近的点的局部坐标,然后对其应用 "局部到全局" 的转换。最后,将绘制一个工具提示组件,并将其添加为组件的子工具提示。工具提示被添加到 Flex 应用程序的 systemManager,然后放置到将被计算的全局点上。现在考虑另一种情况,在某人单击控件之后显示一个菜单,例如浏览器左上角的 File 菜单。您不能将这样的菜单添加为显示 File 选项的标签的子元素。例如,如果您将菜单添加为标签的父元素的子元素,那么 Flex 就将控件垂直放置在该点的下面,因为这是 VBox 的默认行为。如果您将菜单添加为标签的子元素,那么菜单根本就不会显示,因为标签将仅度量它所包含的文本,然后创建一个符合文本的大小。相反,您需要将菜单添加到 systemManager,它的行为类似于弹出子控件。您可以将添加到 systemManager 的组件放置到整个应用程序区域的任何位置。要将控件准确地放置在标签的下面,您需要将所需的位置转换为全局坐标。例如,在标签的坐标系中标签的底部点为 (0,label.height)。然后您可以使用标签的 localToGlobal() 转换该点,并将菜单放置到该点上。使用 move() 方法放置菜单,它将任何组件的左上角映射到所选的位置。清单 9 显示了如何将菜单添加到标签控件。
  清单 9. 将菜单添加到标签
   
   
   
   
     
分享到:
评论

相关推荐

    FLEX组件工具包

    可以使用Flash创建FLEX可用的组件

    谈谈flex自定义组件

    Flex组件开发可分为两种. 一是在mxml中创建自定义组件.另一种则在actionscript class中创建,分别知道他们的含义。

    S32KSDKCAN组件详解-CANPAL-FLEXCAN,学习S32K系列CAN组件的使用和原理

    S32KSDKCAN组件详解-CANPAL-FLEXCAN,学习S32K系列CAN组件的使用和原理

    Flex创建用户界面

    在该 Test Drive 中,您将创建一个 Flex 应用程序,它将检索、显示和修改数据库记录(请参阅图 1)。Flex 应用程序不会直接连接到远程数据库。而是将它连接到以您的首选 Web 语言(PHP、ColdFusion、Java 或任何其他...

    Flex2 发现之旅:构建多语言本地化Flex应用

    现在好了,Flex2诸多激动人心更新中的一个就是本地化特性 (localization feature),这倒是Adobe加强推广Flex2的一个强助力了(这一特性可以本地化Flex组件,这样估计以后会有中文版的Flex2 了...),使用Flex2的...

    用ActionScript开发高级可视化组件

    我们可以用ActionScript开发在Adobe® Flex™应用中使用的高级可视化组件,这个主题,包 括以下方面的内容: 1. 关于创建高级组件 2. 组件的实现 3. 使组件具备可访问性 4. 为组件增加版本号 5. 组件设计的最佳实践 ...

    理解Flex3的组件和框架的生命周期

    Adobe Flex 框架的SDK 美中不足之处就是部分由良好的半黑盒子系统所创建;这就是说, 在大多数情况下,我们这些开发者在项目周期中没有时间或精力去真正地深入到未知领域。 从技术上来讲,Flex 框架的不是一个黑盒子...

    使用 Flex 4.5 访问数据

    创建 Flex 项目以访问数据服务 连接数据服务 安装 Zend Framework 使用单个服务实例 构建客户端应用程序 为数据服务操作配置数据类型 测试服务操作 管理对服务器中的数据的访问 Flash Builder 为客户端应用程序...

    FLEX从入门到精通.pdf

     6.3 创建Flex应用程序  6.3.1 创建一个Flex项目  6.3.2 使用设计模式  6.3.3 使用数据绑定  6.3.4 使用触发器和特效  6.3.5 编译应用程序  6.4 创建ActionScript应用程序  6.4.1 创建ActionScript...

    Adobe.Flex.4中文教程

    将服务导入到 Flex 并将返回的数据绑定到应用程序组件 第 4 章: 为客户端应用程序创建 PHP 服务 创建实现服务的 PHP 类 (可选)测试 PHP 服务 将服务导入到 Flex 并将返回的数据绑定到应用程序组件 第 5 章: 通过...

    Flex手机项目代码

    Flex list数据列表,flex传递参数,flex动态创建组件,账号:wanger密码:123456

    FLEX企业应用开发实战.part1

     2.5.1 认识Flex组件和组件容器  2.5.2 组件生命周期与布局  2.5.3 组件的失效机制  2.5.4 使用ActionScript创建自定义组件  2.6 异步调用  2.6.1 异步调用导致模型数据不一致  2.6.2 异步调用导致用户...

    FLEX企业应用开发实战.part2

     2.5.1 认识Flex组件和组件容器  2.5.2 组件生命周期与布局  2.5.3 组件的失效机制  2.5.4 使用ActionScript创建自定义组件  2.6 异步调用  2.6.1 异步调用导致模型数据不一致  2.6.2 异步调用导致用户...

    Flex4权威指南+随书源代码+Flexbuild使用工具

    1. Flex4权威指南电子书与此书的源代码 2. Flexbuild使用工具适用于4.6之前版本 电子书内容概括: 1. 理解RIA 2. 开始 3. 布局界面 4. 使用简单的控件 5. 处理事件 6. 使用远程XML数据 7. 创建类 8. 使用数据绑定和...

    理解Flex3组件和框架的生命周期.pdf

    Adobe Flex 框架的 SDK 美中不足之处就是部分由良好的半黑盒子系统所创建;这就是说, 在大多数情况下,我们这些开发者在项目周期中没有时间或精力去真正地深入到未知领域。 从技术上来讲,Flex 框架的不是一个黑...

    Flex 验证器简介

    你可以扩展它们来实现更复杂的验证,甚至重新创建自定义规则的验证器。 验证器需要与目标源关联,而目标源包含一个需要验证的属性。目标源可以是一个 UI 组件,也可以是一个数据模型。当验证器与一个目标源的属性...

    Flash+Flex+Air移动开发入门经典 pdf

    《flash+flex+air移动开发入门经典——适用于android、ios和blackberry》 第1章 flash、flex和air简介 1 1.1 adobe flash 1 1.2 actionscript 3.0 2 1.2.1 ecmascript 2 1.2.2 关键概念 3 1.3 flex框架 11 ...

    Re-Flex:可调整大小的Flex布局容器组件,用于高级React Web应用程序

    Re-F | ex是我创建的基于React flex的布局组件库,因为在那里发现的所有组件都不能满足我的要求。 它旨在以简单的方式解决需要可调整大小的布局的高级React Web应用程序的需求。 这是一个基本的演示: import ...

    flex lifecycle

    生命周期(LifeCycle)简述 关于组件实例化生命周期 描述执行的序列步骤,当你从一个组件类创建一个组件时。作为生命周期的一部分,Flex自动调用组件方法,分发事件,使组件可视。

    Flex企业应用开发实战源代码

    2.5.1 认识Flex组件和组件容器 47 2.5.2 组件生命周期与布局 51 2.5.3 组件的失效机制 59 2.5.4 使用ActionScript创建自定义组件 62 2.6 异步调用 85 2.6.1 异步调用导致模型数据不一致 85 2.6.2 异步调用导致...

Global site tag (gtag.js) - Google Analytics