Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 46 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
46
Dung lượng
180,17 KB
Nội dung
220 | Chapter 10: Managing State define the overrides property as an array before you can add overrides to a state using ActionScript: stateA.overrides = new Array( ); Once you’ve defined the overrides property as an array, you can add overrides to the array: stateA.overrides.push(exampleAddChild); Adding and Removing Child Elements You can add and remove child elements in MXML using the <mx:AddChild> and <mx:RemoveChild> tags. The corresponding ActionScript classes are mx.states. AddChild and mx.states.RemoveChild. When you want to add child elements using the AddChild class, you must first con- struct a new instance: var addChild:AddChild = new AddChild( ); When using MXML, nest the component tag within the <mx:AddChild> tag. When using ActionScript, you must assign a component reference to the target property of the AddChild object: var button:Button = new Button( ); button.label = "Example"; addChild.target = button; If you want to specify a parent, you can use the relativeTo property. Simply assign a reference to the relativeTo component: addChild.relativeTo = vbox; Also, just as you can specify where you want to add the child element using the position attribute of the <mx:AddChild> tag, you can use the position property of the AddChild class. The property accepts the same values (firstChild, lastChild, before, and after) as the corresponding attribute. The values have the same effects as when working with MXML. When you specify a value of firstChild or lastChild, the child element is added as a child of the target. When you specify a value of before or after, the child element is added as a sibling of the target. If you don’t specify any value or you assign a value of null, the default behavior is that the component is added as the last child of the target: addChild.position = "firstChild"; When you want to remove a child element, use the RemoveChild object and specify the child using the target property: var removeChild:RemoveChild = new RemoveChild( ); removeChild.target = button; Using ActionScript to Define States | 221 Setting Properties and Styles To set properties and styles with ActionScript you use the mx.states.SetProperty and mx.states.SetStyle classes. Each class has properties that correspond exactly to the attributes of the <mx:SetProperty> and <mx:SetStyle> tags. Both classes define target, name, and value properties. To simplify things you can also pass the target, name, and value to the constructors. The following examples illustrate how to use the SetProperty and SetStyle classes: var setProperty:SetProperty = new SetProperty(button, "width", 200); var setStyle:SetStyle = new SetStyle(button, "color", 0xFF00FF); Setting Event Handlers The mx.states.SetEventHandler class corresponds to the <mx:SetEventHandler> tag for setting event handlers. The class defines target and name properties that corre- spond to the target and name attributes of the <mx:SetEventHandler> tag. To make things even simpler, the SetEventHandler constructor allows you to pass the target and name parameters: var setEventHandler:SetEventHandler = new SetEventHandler(button, "click"); When you use the <mx:SetEventHandler> tag, you use the handler attribute to specify the ActionScript to call when the event occurs. However, when working with a SetEventHandler object, you use the handlerFunction property. The handlerFunction property requires a reference to a function/method. Flash Player then calls that func- tion/method when the event occurs. The following instructs Flash Player to call a function named clickHandler when the user clicks the button: setEventHandler.handlerFunction = clickHandler; Using Dynamic States To better understand how to use ActionScript’s dynamic states created at runtime, let’s look at an example. Example 10-9 builds a multipage form from XML data and loads it at runtime. The form is composed of states for each page. For the purposes of this example, the following XML data is used and saved in a file called forms.xml. Example 10-9. forms.xml <forms> <form id="1" label="Name"> <item type="textinput" name="firstName" label="First Name" /> <item type="textinput" name="lastName" label="Last Name" /> </form> <form id="2" label="Address"> <item type="textinput" name="address" label="Street Address" /> <item type="textinput" name="city" label="City" /> 222 | Chapter 10: Managing State To work with the data, you can define several classes: CustomFormItem, CustomForm, and CustomFormManager. The CustomFormItem class can be used to represent an item from the form. An item can consist of a label and a form control such as a text input, text area, or check- box. Example 10-10 defines the CustomFormItem class. <item type="textinput" name="state" label="State" /> <item type="textinput" name="postalCode" label="Postal Code" /> </form> <form id="3" label="Phone and Email"> <item type="textinput" name="phone" label="Phone Number" /> <item type="textinput" name="email" label="Email" /> </form> <form id="4" label="Address"> <item type="textarea" name="agreement" label=""> Example Corporation reserves all rights. </item> <item type="checkbox" itemName="city" label="I agree" /> </form> </forms> Example 10-10. CustomFormItem.as package com.oreilly.programmingflex.states { public class CustomFormItem { private var _type:String; private var _label:String; private var _name:String; private var _value:String; public function CustomFormItem(type:String, label:String, name:String, value:String) { _type = type; _label = label; _name = name; _value = value; } public function getType( ):String { return _type; } public function getLabel( ):String { return _label; } public function getName( ):String { return _name; } Example 10-9. forms.xml (continued) Using ActionScript to Define States | 223 The CustomForm class (Example 10-11) is essentially a collection of form items with the addition of a method that constructs a new state based on the form. public function getValue( ):String { return _value; } public static function parseFromXML(xml:XML):CustomFormItem { var type:String = xml.@type; var label:String = xml.@label; var name:String = xml.@itemName; var value:String = null; if(type == "textarea") { value = xml.children()[0].toString( ); } return new CustomFormItem(type, label, name, value); } } } Example 10-11. CustomForm.as package com.oreilly.programmingflex.states { import mx.states.State; import mx.containers.GridRow; import mx.containers.GridItem; import mx.controls.Label; import mx.core.UIComponent; import mx.controls.TextInput; import mx.controls.CheckBox; import mx.controls.TextArea; import mx.states.AddChild; import com.oreilly.programmingflex.states.CustomFormItem; import mx.containers.Grid; public class CustomForm { private var _label:String; private var _items:Array; public function CustomForm(label:String, items:Array) { _label = label; _items = items; } public function getLabel( ):String { return _label; } Example 10-10. CustomFormItem.as (continued) 224 | Chapter 10: Managing State public function getItems( ):Array { return _items.concat( ); } public function toState(parent:Grid):State { var state:State = new State( ); state.overrides = new Array( ); var gridRow:GridRow; var gridItem:GridItem; var count:uint = _items.length; var i:uint; var type:String; var label:Label; var component:UIComponent; var item:com.oreilly.programmingflex.states.CustomFormItem; var addChild:AddChild; for(i = 0; i < count; i++) { item = _items[i]; gridRow = new GridRow( ); type = item.getType( ); if(type != "checkbox" && item.getLabel( ).length > 0) { label = new Label( ); label.text = item.getLabel( ); gridItem = new GridItem( ); gridItem.addChild(label); gridRow.addChild(gridItem); } if(type == "textinput") { component = new TextInput( ); } else if(type == "checkbox") { component = new CheckBox( ); CheckBox(component).label = item.getLabel( ); } else if(type == "textarea") { component = new TextArea( ); component.width = 200; TextArea(component).text = _items[i].getValue( ); } component.id = "component"; gridItem = new GridItem( ); gridItem.addChild(component); gridRow.addChild(gridItem); addChild = new AddChild( ); addChild.relativeTo = parent; addChild.target = gridRow; state.overrides.push(addChild); } return state; } Example 10-11. CustomForm.as (continued) Using ActionScript to Define States | 225 The CustomFormManager class (Example 10-12) is a Singleton class that loads the XML data and provides an interface to a collection of forms. public static function parseFromXML(xml:XML):CustomForm { var label:String = xml.@label; var items:Array = new Array( ); var i:uint; for(i = 0; i < xml.children().length( ); i++) { items.push(CustomFormItem.parseFromXML(xml.children( )[i])); } return new CustomForm(label, items); } } } Example 10-12. CustomFormManager.as package com.oreilly.programmingflex.states { import flash.events.Event; import flash.events.ProgressEvent; import flash.events.IOErrorEvent; import flash.net.URLRequest; import flash.net.URLLoader; import flash.events.EventDispatcher; public class CustomFormManager extends EventDispatcher { private static var _instance:CustomFormManager; private var _forms:Array; private var _index:uint; public function CustomFormManager(enforcer:SingletonEnforcer) { } public static function getInstance( ):CustomFormManager { if(_instance == null) { _instance = new CustomFormManager(new SingletonEnforcer( )); } return _instance; } public function load(url:String):void { var request:URLRequest = new URLRequest(url); var loader:URLLoader = new URLLoader( ); loader.load(request); loader.addEventListener(Event.COMPLETE, dataHandler); } Example 10-11. CustomForm.as (continued) 226 | Chapter 10: Managing State The MXML (with embedded ActionScript) in Example 10-13 illustrates how to use the preceding code to construct dynamic states based on XML data. public function hasNextForm( ):Boolean { return _index < _forms.length; } public function getNextForm( ):CustomForm { if(_index >= _forms.length) { return null; } return _forms[_index++]; } public function hasPreviousForm( ):Boolean { return _index > 0; } public function getPreviousForm( ):CustomForm { if(_index < 0) { return null; } return _forms[_index ]; } private function dataHandler(event:Event):void { _index = 0; _forms = new Array( ); var xml:XML = new XML(event.target.data); var forms:XMLList = xml.children( ); var i:uint; var form:CustomForm; for(i = 0; i < forms.length( ); i++) { form = CustomForm.parseFromXML(forms[i]); _forms.push(form); } dispatchEvent(new Event(Event.COMPLETE)); } } } class SingletonEnforcer {} Example 10-13. Dynamic states <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="initializeHandler(event)"> <mx:Script> <![CDATA[ import mx.states.SetProperty; import mx.states.SetEventHandler; Example 10-12. CustomFormManager.as (continued) Using ActionScript to Define States | 227 import mx.states.State; import com.oreilly.programmingflex.states.CustomForm; import com.oreilly.programmingflex.states.CustomFormManager; private var _stateIndex:uint; private var _stateCount:uint; private function initializeHandler(event:Event):void { var formManager:CustomFormManager = CustomFormManager.getInstance( ); formManager.load("forms.xml"); formManager.addEventListener(Event.COMPLETE, dataHandler); } private function dataHandler(event:Event):void { _stateIndex = 1; _stateCount = 0; var formManager:CustomFormManager = CustomFormManager.getInstance( ); var form:CustomForm; states = new Array( ); var state:State; var index:uint = 1; var setProperty:SetProperty; var hasPreviousForm:Boolean; while(formManager.hasNextForm( )) { hasPreviousForm = formManager.hasPreviousForm( ); _stateCount++; form = formManager.getNextForm( ); state = form.toState(grid); setProperty = new SetProperty(next, "visible", formManager.hasNextForm( )); state.overrides.push(setProperty); setProperty = new SetProperty(previous, "visible", hasPreviousForm); state.overrides.push(setProperty); state.name = "form" + index++; states.push(state); } currentState = "form1"; } private function nextForm( ):void { currentState = "form" + ++_stateIndex; } private function previousForm( ):void { currentState = "form" + _stateIndex; } ]]> </mx:Script> <mx:VBox id="vbox"> <mx:Label id="formLabel" /> Example 10-13. Dynamic states (continued) 228 | Chapter 10: Managing State Managing Object Creation Policies (Preloading Objects) By default, components added by nonbase states aren’t instantiated until the state is first requested. The MXML in Example 10-14 illustrates this. The trace( ) statement outputs null because button is not yet defined when the application first starts. However, you can manage when components added by states are instantiated using a creation policy. The default creation policy setting is auto, which means the compo- nent is instantiated when the state is first requested. You can set creation policies for each added component using the creationPolicy attribute of the <mx:AddChild> tag, or the creationPolicy property of the AddChild class. The possible values are auto (default), all, and none. When you set the creation policy of an added component to all, the component is instantiated when the application first starts. The MXML in Example 10-15 illustrates how that works. Because the creation policy of the button is now set to all, the trace( ) statement outputs the reference to the component. <mx:HBox> <mx:Button id="previous" label="Previous" visible="false" click="previousForm( )" /> <mx:Button id="next" label="Next" click="nextForm( )" /> </mx:HBox> <mx:Grid id="grid"> </mx:Grid> </mx:VBox> </mx:Application> Example 10-14. Understanding object creation policies: default policy <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="initializeHandler(event)"> <mx:states> <mx:State name="example"> <mx:AddChild> <mx:Button id="button" label="Example" /> </mx:AddChild> </mx:State> </mx:states> <mx:Script> <![CDATA[ private function initializeHandler(event:Event):void { trace(button); } ]]> </mx:Script> </mx:Application> Example 10-13. Dynamic states (continued) Managing Object Creation Policies (Preloading Objects) | 229 When the creation policy is set to none, the component isn’t instantiated until you explicitly call the createInstance( ) method of the AddChild object. If you’re defining the AddChild object using the <mx:AddChild> tag, you must assign an id. Example 10-16 illustrates how the none creation policy works. The first trace( ) statement outputs null because the component hasn’t been instantiated. The second trace( ) statement outputs the reference to the component because it is called imme- diately following the call to createInstance( ). Example 10-15. Understanding object creation policies: policy all <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="initializeHandler(event)"> <mx:states> <mx:State name="example"> <mx:AddChild creationPolicy="all"> <mx:Button id="button" label="Example" /> </mx:AddChild> </mx:State> </mx:states> <mx:Script> <![CDATA[ private function initializeHandler(event:Event):void { trace(button); } ]]> </mx:Script> </mx:Application> Example 10-16. Understanding object creation policy: policy none <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="initializeHandler(event)"> <mx:states> <mx:State name="example"> <mx:AddChild creationPolicy="none" id="exampleAddChild"> <mx:Button id="button" label="Example" /> </mx:AddChild> </mx:State> </mx:states> <mx:Script> <![CDATA[ private function initializeHandler(event:Event):void { trace(button); exampleAddChild.createInstance( ); trace(button); } ]]> </mx:Script> </mx:Application> [...]... id="windowA" click="currentState='A'" /> Creating Custom Effects | 24 7... name="x" value= "20 0"/> name="y" value="333"/> name="x" value= "23 "/> name="y" value="19"/> name="x" value="373"/> name="y" value="333"/> 24 6 | Chapter 11: Using Effects and Transitions Example 11-9 Flag... time the effect is played just once rather than four times Example 11 -2 Applying an effect to many targets ... version="1.0" encoding="utf-8"?> 2; rotateEffect.originY = event.currentTarget.height / 2; rotateEffect.play( ); } ]]> ... version="1.0" encoding="utf-8"?> 2; rotateEffect.originY = event.currentTarget.height / 2; rotateEffect.play( ); } ]]> . 10- 12. CustomFormManager.as (continued) Using ActionScript to Define States | 22 7 import mx.states.State; import com.oreilly.programmingflex.states.CustomForm; import com.oreilly.programmingflex.states.CustomFormManager; . listeners. 23 2 Chapter 11 CHAPTER 11 Using Effects and Transitions 11 Flex applications always consist of one or more user interface and/or container com- ponents. At a minimum, a Flex application. )[i])); } return new CustomForm(label, items); } } } Example 10- 12. CustomFormManager.as package com.oreilly.programmingflex.states { import flash.events.Event; import flash.events.ProgressEvent;