理解 Flex itemRenderer - 第 2 部分: 外部渲染器
http://www.adobe.com/cn/devnet/flex/articles/itemrenderers_pt2.html In?Part 1 of this series?I showed you how to make an inline itemRenderer—that is,an itemRenderer whose MXML tags and ActionScript code are in the same file as the list using the itemRenderer. The code is inline with the rest of the code in the file. You'll also recall that I said you should think of inline itemRenderers are being separate classes. The Flex compiler in fact extracts that inline code and makes a class for you. The benefit of inline itemRenderers is that the code is in the same place as the list,but that's also a drawback when the itemRenderer becomes complex. What I'm going to show you in this article is how to make the class yourself. Extracting the itemRenderer into an external file has several benefits:
This series includes the following articles:
An MXML itemRendererIn Part 1 you saw there was a complex itemRenderer used for a 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> The itemRenderer is based on an HBox,contains an Image and a Text,and the background color is set according to the?
<?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>
Now modify the DataGridColumn definition by removing the inline itemRenderer and replacing it with this: <mx:DataGridColumn headerText="Title" dataField="title"itemRenderer="GridColumnSimpleRenderer">
Now run the application. You'll get a surprise. The surprise is how tall the rows are. That's because of the presence of?
Determining an itemRenderer's width and height The List control always sets the itemRenderer's width. In this example,the explicit? The height is a different matter. If the list has an explicit? To fix this,remove the explict height from the itemRenderer file and the application will work correctly.
Dynamically Changing the itemRenderer In this example the? Common mistakes are:
An ActionScript itemRendererNow you'll write another itemRenderer,this time using an ActionScript class. In the previous article there is a TileList with this inline 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>
You'll make that into an ActionScript external itemRenderer. You'll need to follow these steps:
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;
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);}
I've indented the code to show the parent-child relationships. Also,make sure you include an event listener on the Buy button.
override protected function commitProperties():void{super.commitProperties();coverImage.source = data.image;titleText.text = data.title;authorLabel.text = data.author;pubdateLabel.text = data.date;}
private function handleBuyClick( event:MouseEvent ) : void{var e:BuyBookEvent = new BuyBookEvent();e.bookData = data;dispatchEvent(e);}
<mx:TileList id="mylist" x="29" y="542" width="694" itemRenderer="BookTileRenderer" dataProvider="{testData.book}" height="232" columnWidth="275" rowHeight="135" >
If you are going to use an existing container class,such as HBox,I wouldn't bother doing this in ActionScript. You can see it is more complex than using an MXML file and,quite frankly,there is little performance benefit to it. Reusable itemRenderersHere's an example of an itemRenderer that displays a numeric value using the CurrencyFormatter. I call it 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>
The key to this itemRenderer is shown in?red,setting the bindable variable? The function takes a Number as its parameter type,so the value is cast to?Number—that's because the dataProvider for the list is XML,and everything in XML is text; if you use a Object for your data and you have real numeric values,doing the Number cast will be harmless. As you know,data is the property that holds the item being displayed by the itemRenderer. Using? That's where? Note:?Most controls,such as Text,Label,Button,CheckBox,and so forth,implement IDropInListItemRenderer. Most containers,Canvas,etc.?do not?implement that interface. If you want to use? The?
Where to go from hereUse whatever makes you comfortable when implementing itemRenderers. Some people only work in ActionScript,which is great when you've got experience with Flex and ActionScript. MXML makes quick work of simple itemRenderers,too. In Part 3 (coming soon) I'll discuss more communication between itemRenderers and the rest of the application. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |