加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

flex 渲染机制 之外部渲染器

发布时间:2020-12-15 01:16:34 所属栏目:百科 来源:网络整理
导读:itemRenderer-这种 itemRenderer 的 MXML 标记和 ActionScript 代码与使用该 itemRenderer 的列表位于同一文件中。代码与文件中的其余代码内联。 ??? 您应该还记得我说过,应该将内联 itemRenderer 视作单独的类。事实上,Flex 编译器提取这些内联代码并为您
itemRenderer-这种 itemRenderer 的 MXML 标记和 ActionScript 代码与使用该 itemRenderer 的列表位于同一文件中。代码与文件中的其余代码内联。

??? 您应该还记得我说过,应该将内联 itemRenderer 视作单独的类。事实上,Flex 编译器提取这些内联代码并为您创建类。内联 itemRenderer 的优势在于代码与列表位于同一位置,但是如果 itemRenderer 变得复杂时,这又变成了劣势。本文中我将向您展示如何自己创建类。

??? 将 itemRenderer 提取到一个外部文件有几个优势:

??? itemRenderer 可轻松用于多个列表中
??? 代码更容易维护
??? 可以使用 Flex Builder 的“设计”视图草拟出最初的 itemRenderer
??? MXML itemRenderer
??? 在第 1 部分中,您看到有一个复杂的 itemRenderer 用于 DataGrid:

<mx:DataGridColumn headerText="Title" dataField="title">
<mx:itemRenderer>
<mx:Component>
<mx:HBox paddingLeft="2">
<mx:Script>
<![CDATA[
override public function set data( value:Object ) : void {
super.data = value;
var today:Number = (new Date()).time;
var pubDate:Number = Date.parse(data.date);
if( pubDate > today ) setStyle("backgroundColor",0xff99ff);
else setStyle("backgroundColor",0xffffff);
}
]]>

</mx:Script>
<mx:Image source="{data.image}" width="50" height="50" scaleContent="true" />
<mx:Text width="100%" text="{data.title}" />
</mx:HBox>
</mx:Component>

</mx:itemRenderer>
</mx:DataGridColumn>



??? itemRenderer 基于 HBox,包含一个 Image 和一个 Text,并且根据项目记录的 pubDate 字段设置背景色。可以使用以下步骤将同一 itemRenderer 编写为一个外部文件:

??? 如果您使用 Flex Builder,请新建一个 MXML Component 文件 (我将我的文件命名为 GridColumnSimpleRenderer,您可以随意命名),将根标记设置为 HBox。不必担心大小。

??? 如果您只使用 SDK,请新建一个 MXML 文件 (将它命名为 GridColumnSimpleRenderer.mxml),将根标记设置为 HBox。
在文件打开时,复制 <mx:HBox> 与 </mx:HBox> 之间的所有内容,但不要复制那些标记,因为文件中已有它们。结果应该如下:


<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:Script>
<![CDATA[
override public function set data( value:Object ) : void {
super.data = value;
var today:Number = (new Date()).time;
var pubDate:Number = Date.parse(data.date);
if( pubDate > today ) setStyle("backgroundColor",0xff99ff);
else setStyle("backgroundColor",0xffffff);
}
]]></mx:Script>
<mx:Image source="{data.image}" width="50" height="50" scaleContent="true" />
<mx:Text width="100%" text="{data.title}" />
</mx:HBox>

??? 保存此文件。
??? 现在修改 DataGridColumn 定义,方法是删除内联 itemRenderer 并将它替换为以下内容:

<mx:DataGridColumn headerText="Title" dataField="title"
itemRenderer="GridColumnSimpleRenderer">

??? 现在运行这个应用程序。您会大吃一惊。因为行很高。这是因为 itemRenderer 上的 height="300"。

??? 决定 itemRenderer 的宽度和高度

??? List 控制始终设置 itemRenderer 的宽度。本例中将忽略明确的 width="400"。您应当编写自己的 itemRenderer,假设用户更改列或列表宽度是宽度会更改。

??? 高度则是另一回事。如果列表设置了明确的 rowHeight,它会将这个高度强加到各行,忽略您对 itemRenderer 设置的任何高度。但是,如果您将列表的 variableRowHeight 属性设置为 true,则列表会慎重考虑 itemRenderer 的高度。在本例中,高度明确设置为 300,所以各行为 300 像素高。

??? 要修复它,请从 itemRenderer 文件中删除明确高度,应用程序即可正确运行。

??? 动态更改 itemRenderer

??? 本例覆盖了 set data() 函数以检查数据并设置 itemRenderer 的 backgroundColor。这十分常见。覆盖 set data() 使您能截取为新行更改数据的时间,并且您可以作出样式更改。

??? 常见错误为:

??? 忘记调用 super.data = value;。这是致命错误-它会把 itemRenderer 弄乱。

??? 忘记重置样式 (如果任何测试失败)。当 pubDate 是将来时,可能只设置颜色会比较诱人,但您必须记住,itemRenderer 是循环使用的,所以 else 语句很有必要。

??? ActionScript itemRenderer

?? 现在,您将编写另一个 itemRenderer,这次使用 ActionScript 类。在上一篇文章中,有一个 TileList 包含这个内联 itemRenderer:

<mx:itemRenderer>
<mx:Component>
<mx:HBox verticalAlign="top">
<mx:Image source="{data.image}" />
<mx:VBox height="115" verticalAlign="top" verticalGap="0">
<mx:Text text="{data.title}" fontWeight="bold" width="100%"/>

<mx:Spacer height="20" />
<mx:Label text="{data.author}" />
<mx:Label text="Available {data.date}" />
<mx:Spacer height="100%" />
<mx:HBox width="100%" horizontalAlign="right">
<mx:Button label="Buy" fillColors="[0x99ff99,0x99ff99]">

<mx:click>
<![CDATA[
var e:BuyBookEvent = new BuyBookEvent();
e.bookData = data;
dispatchEvent(e);
]]>
</mx:click>
</mx:Button>

</mx:HBox>
</mx:VBox>
</mx:HBox>
</mx:Component>
</mx:itemRenderer>

??? 您将把它转变为一个 ActionScript 外部 itemRenderer。您需要执行以下步骤:

??? 新建一个 ActionScript 类。将它命名为 BookTileRenderer.as 并使它扩展 HBox,就像内联 itemRenderer 那样。

package
{
import flash.events.MouseEvent;

import mx.containers.HBox;
import mx.containers.VBox;
import mx.controls.Button;
import mx.controls.Image;
import mx.controls.Label;
import mx.controls.Spacer;
import mx.controls.Text;

public class BookTileRenderer extends HBox
{
public function BookTileRenderer()
{
super();
}

}
}

??? 创建成员变量,用于存放子组件的引用。

private var coverImage:Image;
private var titleText:Text;
private var spacer1:Spacer;
private var authorLabel:Label;
private var pubdateLabel:Label;
private var spacer2:Spacer;
private var buyButton:Button;
覆盖 createChildren() 函数以创建子组件,并将它们添加到 HBox。

override protected function createChildren():void
{
coverImage = new Image();
addChild(coverImage);

var innerBox:VBox = new VBox();
innerBox.explicitHeight = 115;
innerBox.percentWidth = 100;
innerBox.setStyle("verticalAlign","top");
innerBox.setStyle("verticalGap",0);
addChild(innerBox);

titleText = new Text();
titleText.setStyle("fontWeight","bold");
titleText.percentWidth = 100;
innerBox.addChild(titleText);

spacer1 = new Spacer();
spacer1.explicitHeight = 20;
innerBox.addChild(spacer1);

authorLabel = new Label();
innerBox.addChild(authorLabel);

pubdateLabel = new Label();
innerBox.addChild(pubdateLabel);

spacer2 = new Spacer();
spacer2.percentHeight = 100;
innerBox.addChild(spacer2);

var buttonBox:HBox = new HBox();
buttonBox.percentWidth = 100;
buttonBox.setStyle("horizontalAlign","right");
innerBox.addChild(buttonBox);

buyButton = new Button();
buyButton.label = "Buy";
buyButton.setStyle("fillColors",[0x99ff99,0x99ff99]);
buyButton.addEventListener(MouseEvent.CLICK,handleBuyClick);
buttonBox.addChild(buyButton);
}

??? 我准备通过这一代码显示父子关系。同时,确保在 Buy 按钮中包含一个事件侦听器。

??? 覆盖 commitProperties() 函数,并从数据设置用户界面控制。

override protected function commitProperties():void
{
super.commitProperties();

coverImage.source = data.image;
titleText.text = data.title;
authorLabel.text = data.author;
pubdateLabel.text = data.date;
}

??? 为 Buy 按钮添加单击事件处理函数。

private function handleBuyClick( event:MouseEvent ) : void
{
var e:BuyBookEvent = new BuyBookEvent();
e.bookData = data;
dispatchEvent(e);
}

??? 将主应用程序中的 TileList 修改为使用 itemRenderer ActionScript 类。只需删除 inlineItemRenderer 并将它替换为标记中的 itemRenderer 属性。

<mx:TileList id="mylist" x="29" y="542" width="694" itemRenderer="BookTileRenderer"
dataProvider="{testData.book}" height="232" columnWidth="275" rowHeight="135" >

??? 如果要使用一个现有容器类,如 HBox,我不会使用 ActionScript 这样做。您会发现它比使用 MXML 文件复杂,并且老实说,性能方面几乎没有任何优势。

??? 可重用的 itemRenderer
??? 以下是一个 itemRenderer 示例,它使用 CurrencyFormatter 显示一个数值。我称之为 PriceFormatter:

<?xml version="1.0" encoding="utf-8"?>
<mx:Text xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridListData;

[Bindable] private var formattedValue:String;

override public function set data(value:Object):void
{
super.data = value;

formattedValue = cfmt.format( Number(data[(listData as DataGridListData).dataField]) );

}
]]>
</mx:Script>

<mx:CurrencyFormatter precision="2" id="cfmt" />

<mx:text>{formattedValue}</mx:text>

</mx:Text>

??? 这个 itemRenderer 的关键部分以红色标出,设置可绑定变量 formattedValue。首先,您会发现 <mx:CurrentFormatter> 使用 id cfmt 定义为 MXML 标记 (如果您愿意,也可以使用 ActionScript 这样做)。在上例中,formattedValue 设置为 CurrentFormatter 的 format() 函数的调用结果。

??? 此函数将 Number 作为其参数类型,所以值被转换为 Number-这是因为列表的 dataProvider 是 XML 并且 XML 中的所有内容是文本; 如果为数据使用 Object 并且您有实际数值,执行 Number 转变将是无害的。

??? 如您所知,数据是存放 itemRenderer 所显示项目的属性。使用 [ ] 记号是访问数据项目字段的另一种方法。例如,data['price'] 是价格列。但是为了使这个 itemRenderer 可重用,您不能为特定字段编码,所以需要一种更普通的方法。

??? 此时,listData 登台亮相。实施 IDropInListItemRenderer 接口的所有 Flex 组件都有一个 listData 属性。

??? 注意: Text、Label、Button、CheckBox 等大多数控制都实施 IDropInListItemRenderer。HBox、Canvas 等大多数容器不实施此接口。如果要在扩展 Container 的 itemRenderer 中使用 listData,您必须自己实施 IDropInListItemRenderer; 我将在下一篇文章中讨论这个问题。

??? 除了其他内容,提供给 itemRenderer 的 listData 还包含 rowIndex 和控制,该控制拥有 itemRenderer-DataGrid、List 或 TileList。将 itemRenderer 用于 DataGrid 时,listData 实际上是一个 DataGridListData 对象-它包含 columnIndex 以及与 DataGridColumn 关联的 dataField。以下是上述语句的明细,从内部开始:

??? listData as DataGridListData-它将 listData 转换为 DataGridListData 对象,使您能访问它的 dataField
.dataField-该字段用于渲染的列。它使这个 itemRenderer 变得一般。可以将这个 itemRenderer 用于多个列。在本例中,dataField 是“price”。

??? data[ ... ]-它访问项目中特定字段的数据。在本例中,它是价格列。
Number( ... )-它将值转换为 Number,因为 format() 函数需要一个 Number 参数。
cfmt.format( ... )-它将值格式化为货币。

??? 后续工作

??? 实施 itemRenderer 时,可使用您喜欢的任何语言。一些人只适用 ActionScript,当然如果您具有 Flex 和 ActionScript 方面的经验,这很棒。MXML 也可以快速创建出简单的 itemRenderer。

来自: http://hi.baidu.com/ls%5Fmcx/blog/item/2d25f3e84829a236b80e2d0d.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读