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

理解 Flex itemRenderer - 第 1 部分: 内联渲染器

发布时间:2020-12-15 05:01:32 所属栏目:百科 来源:网络整理
导读:http://www.adobe.com/cn/devnet/flex/articles/itemrenderers_pt1.html ? Flex 提供许多控制,它们可以按不同方式显示大量数据。List 控制自己、DataGrid、Tree 以及包括图表和 AdvancedDataGrid 在内的可视类。默认情况下,Flex 列表控制将提供的数据显示为


http://www.adobe.com/cn/devnet/flex/articles/itemrenderers_pt1.html

?

Flex 提供许多控制,它们可以按不同方式显示大量数据。List 控制自己、DataGrid、Tree 以及包括图表和 AdvancedDataGrid 在内的可视类。默认情况下,Flex 列表控制将提供的数据显示为简单文本。但 Flex 的能耐远不止此,列表控制提供了一种使用 itemRenderer 对其内容进行自定的方式。通过允许您使用 itemRenderer 完全控制列表每行 (或单元格) 的内容,Flex 使您能够编写出更引人注目、更具创意、更实用的应用程序。

本系列讨论 Flex itemRenderer 以及如何高效、有效地使用它们。本系列的第一部分侧重于内联 itemRenderer,它们写入描述 List 控制的 MXML 标记中。之后的文章讨论使用 MXML 和 ActionScript 且更为复杂的 itemRenderer。

?

循环使用渲染器

人们经常尝试从列表外访问 itemRenderer。例如,由于您刚从服务器那里收到新数据,您可能要将 DataGrid 中第五行的第四列变为绿色。获取那个 itemRenderer 实例并在外部修改它对于 Flex 框架和组件模型而言是一个大工程。

要理解 itemRenderer,您必须理解它们为何变成现在这样以及我们当初设计它们时的目的。在此,当我用到“我们”时,我指的是 Adobe Flex 设计小组。我与它没有关系。言归正传,假设您要显示 1,000 条记录。如果您认为列表控制会创建 1,000 个 itemRenderer,您就错了。如果列表只显示 10 行,它会创建约 12 个 itemRenderer-这些足以显示各个可见行,多出的几个则用于缓冲和性能。列表最初显示行 1–10。当用户滚动这个列表时,它现在可能显示行 3-12。但那 12 个 itemRenderer 仍在那里: 及时滚动列表后,也不会新建任何 itemRenderer。

以下是 Flex 执行的操作。滚动列表时,那些依然显示相同数据 (行 3-10) 的 itemRenderer 将向上移动。它们并未发生任何变化,只是移到了新位置。之前显示行 1 和 行 2 数据的 itemRenderer 现在移到行 10 的 itemRendere 下。然后,为那些 itemRenderer 提供行 11 和 行 12 的数据。换言之,除非您调整列表大小,否则将重用/循环使用那些相同的 itemRenderer-它们只是移到新位置并且现在显示新数据。

Flex 的这一行为在特定编程环境中使情况变得更复杂。例如,如果要更改第五行的第四列中某个单元格的背景色,请注意如果用户滚动了该列表,则该单元格的 itemRenderer 现在可能显示第二十一行的内容。

那么怎样进行这类更改呢?

itemRenderer 必须根据给它们显示的数据更改自己。如果列表的 itemRenderer 要根据数据值更改其颜色,它必须查看获得的数据并更改自己。

内联 itemRenderer

我在本文中使用内联 itemRenderer 说明如何解决这个问题。内联 itemRenderer 直接写入 MXML 文件中列表控制出现的位置。我在下一篇文章中将说明如何编写外部 itemRenderer。内联 itemRenderer 最简单,一般用于十分简单的渲染器或用于为较大的应用程序构建原型。内联 itemRenderer 本身并没有问题,但随着代码变得复杂,最好将它提取到自己的类中。

我将在所有示例中使用相同的数据: 一组书籍相关信息-作者、书名、出版日期和缩览图图像等。每个记录是一段 XML 代码,如下:

<book>
    <author>Peter F. Hamilton</author>
    <title>Pandora's Star</title>
    <image>assets/pandoras_star_.jpg</image>
<date>Dec 3,2004</date>
</book>

我将从使用?<mx:List>?控制的一个简单 itemRenderer 开始。这里将列出作者,后跟书名。

<mx:List x="29" y="67" dataProvider="{testData.book}" width="286" height="190">
    <mx:itemRenderer>
        <mx:Component>
            <mx:Label text="{data.author}: {data.title}" />
        </mx:Component>
    </mx:itemRenderer>
</mx:List>

这个 itemRenderer 太简单了,可能使用 labelFunction 会更好,但它至少允许您专注于重要部分。首先,内联 itemRenderer 使用?<mx:itemRenderer>?标记定义它。这个标记包含?<mx:Component>?标记。这个标记必须放在这里,因为它会告诉 Flex 编译器您正在定义一个组件内联。我马上会说明这到底是什么意思。

您在?<mx:Component>?标记中定义 itemRenderer。对于本例,它是一个?<mx:Label>?并且文本字段设置为一个数据绑定表达式:?{data.author}: {data.title}这点很重要。List 控制通过设置 itemRenderer 的?data?属性,为每个 itemRenderer 实例提供 dataProvider 的记录。对于上述代码,它意味着对于任何给定列表行,内联 itemRenderer 实例将自己的?data?属性设置为?<book>?XML 节点 (如以上节点)。当您滚动列表时,?data?属性也会更改,因为 itemRenderer 被循环用于新行。

换言之,行 1 的 itemRenderer 实例现在可能将其?data.author?设置为“Peter F. Hamilton”,但当它滚出视图时,itemRenderer 被循环使用并且 (该 itemRenderer) 的data?属性现在可能将其?data.author?设置为“J.K. Rowling”。滚动列表时,所有这一切都会自动进行-您不必操心。

以下是复杂一些的内联 itemRenderer,它还是使用?<mx:List>?控制:

<mx:List x="372" y="67" width="351" height="190" variableRowHeight="true" dataProvider="{testData.book}">
   <mx:itemRenderer>
       <mx:Component>
           <mx:HBox >
               <mx:Image source="{data.image}" width="50" height="50" scaleContent="true" />
               <mx:Label text="{data.author}" width="125" />
               <mx:Text  text="{data.title}" width="100%" />
           </mx:HBox>
       </mx:Component>
   </mx:itemRenderer>
</mx:List>

确实区别不大。这次不是?<mx:Label>,itemRenderer 是一个?<mx:HBox>?并包含?<mx:Image><mx:Label>?和<mx:Text>?控制。数据绑定依然将可视与记录关联在一起。

数据网格

也可以将内联 itemRenderer 用于 DataGrid。以下是应用于列的一个示例:

<mx:DataGrid x="29" y="303" width="694" height="190" dataProvider="{testData.book}" variableRowHeight="true">
    <mx:columns>
        <mx:DataGridColumn headerText="Pub Date" dataField="date" width="85" />
        <mx:DataGridColumn headerText="Author" dataField="author" width="125"/>
        <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:columns>
</mx:DataGrid>

如您所见,这次比前两个要复杂得多,但结构相同:?<mx:itemRenderer>?包含一个?<mx:Component>?定义。

<mx:Component>?是为了提供一个 MXML 语法,用于在代码中创建一个 ActionScript 类。想象一下,剪切<mx:Component>?块中出现的代码并将它放入一个单独文件中并提供一个类名称。当您查看内联 itemRenderer 时,它看上去就像一个完整的 MXML 文件,不是吗?有根标记 (本例中为?<mx:HBox>),甚至?<mx:Script>?块。

本例中的?<mx:Script>?块用于覆盖 set data 函数,使得 itemRenderer 的背景色可以更改。在本例中,无论书籍的未来出版数据为何时,背景将从白色更改为其他颜色。记住,itemRenderer 是循环使用的,所以如果测试失败,还必须将颜色设置回白色。否则,当用户滚动列表时,所有 itemRenderer 最终将变为紫色。

outerDocument

scope?也更改了。我的意思是,从?<mx:Component>?中定义的变量仅作用于那个组件/内联 itemRenderer。同样,<mx:Component>?外的内容在不同的作用范围内,就像这个组件是在另一个文件中定义的那样。例如,假设您为这个 itemRenderer 添加了一个 Button,允许用户从在线零售商那里购买书籍。Button 调用它们的?click?事件上的函数,所以您可以如下定义这个按钮:

<mx:Button label="Buy" click="buyBook(data)" />

如果在文件的?<mx:Script>?块中定义?buyBook()?函数,会显示一个错误,指出?buyBook()?是一个未定义的方法。这是因为?buyBook()?是在文件的作用范围内而不是在?<mx:Component>?的作用范围内定义的。由于这是一个典型用例,使用?outerDocument?标识符可以避开这个问题:

<mx:Button label="Buy" click="outerDocument.buyBook(data)" />

outerDocument?标识符将作用范围更改为查找文件或外部文档,并引用?<mx:Component>。现在请注意: 这个函数必须是公共函数,而不是受保护或私有函数。记住,250)"><mx:Component>?被视为外部定义的类。

冒泡事件

现在我们来看另一个更复杂的示例。这是一个使用相同数据的 TileList。

<mx:TileList x="29" y="542" width="694"
dataProvider="{testData.book}" height="232" columnWidth="275"
rowHeight="135" >
    <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="[0×99ff99,0×99ff99]">
                           <mx:click>
                           <mx:Script>
                            <![CDATA[
                                var e:BuyBookEvent = new BuyBookEvent();
                                e.bookData = data;
                                dispatchEvent(e);
                            ]]>
                            </mx:Script>
                            </mx:click>
                        </mx:Button>
                    </mx:HBox>
                </mx:VBox>
            </mx:HBox>
        </mx:Component>
    </mx:itemRenderer>
</mx:TileList>

当应用程序运行时,itemRenderer 看上去如图 1:

图 1.在 TileList 中实施一个 itemRenderer。

这个 itemRenderer 与 DataGrid 中使用的那个十分相似,但“购买”按钮的?click?事件不使用?outerDocument?调用函数。在本例中,250)">click?事件会创建一个自定事件,后者通过 TileList 从 itemRenderer 中出,并由可视链中的较高组件接收。

这是一个很常见的问题: 您有一个 itemRenderer,而它包含一些交互控制,通常是 Button、LinkButton 或其他单击时会导致发生特定动作的组件。可能是删除行或是本例中的购买书籍。

指望 itemRenderer 完成这个工作并不合理。毕竟,itemRenderer 只负责让列表看上去美观。事件 bubbling 允许 itemRenderer 将这个工作转交给他人。自定事件此时派上了用场,因为这个事件与行中的数据相关;为何不将数据包含在事件中呢?如果那样,事件接收方就不必苦苦搜寻它了。

结论

使用内联 itemRenderer 是一种快速自定列表外观的好方法。考虑将内联 itemRenderer 作为单独的 ActionScript 类-它们毕竟像有作用范围一样。如果必须引用包含文件中的函数或属性,可使用?outerDocument?标识符更改作用范围。如果需要根据与 itemRenderer 的交互结果传达传递信息,可使用自定冒泡事件。

并且记住:?不要试图抓住 itemRenderer 不放-它们将循环使用。它们只负责处理收到的数据。

我在下一篇文章中将讨论外部 itemRenderer。

(编辑:李大同)

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

    推荐文章
      热点阅读