您应该还记得我说过, 应该将内联 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 >
<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 >
<?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" >
<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
语句很有必要。