第1章 入门
为什么要用Flex 4
第l课 Flex初识
汗,第一课一上来书上代码就打错了,怎么继续.......
第2课 分派和侦听事件
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="application1_initializeHandler(event)"> <fx:Script> <![CDATA[ import mx.events.FlexEvent; private function button23_clickHandler(event:MouseEvent):void { if(event.target==button2){ label.text+='Button 2 clicked\n'; }else if(event.target==button3){ label.text+='Button 3 clicked\n'; } } private function application1_initializeHandler(event:FlexEvent):void { button3.addEventListener(MouseEvent.CLICK,button23_clickHandler); } ]]> </fx:Script> <s:VGroup width="100%"> <s:Button id="button1" label="Button 1" click="label.text+='Button 1 clicked\n'"/> <s:Button id="button2" label="Button 2" click="button23_clickHandler(event)"/> <s:Button id="button3" label="Button 3" /> <s:Label id="label"/> </s:VGroup> </s:Application>
上述代码中给出了三种触发事件的方法。
<![CDATA[和]]>中就不必考虑特殊的XML字符序列了
第3课 可绑定注解和数据绑定
package { public class Task { [Bindable] public var name:String; [Bindable] public var nameDou:String; public function Task( name:String="",nameDou:String="") {this.name=name; this.nameDou=nameDou; } } }
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
[Bindable]
private var _task:Task=new Task("leard binding","double binding");
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout paddingTop="50" paddingLeft="100" />
</s:layout>
<!-- 两次单向数据绑定实现双向绑定 -->
<s:Label text=" 两次单向数据绑定实现双向绑定"/>
<s:TextInput id="textInput1" text="{textInput2.text}" />
<s:TextInput id="textInput2" text="{textInput1.text}" />
<s:Label text="# cahrs: {textInput1.text.length}"/>
<!-- flex4引入了双向绑定-->
<s:Label text="flex4引入了双向绑定"/>
<s:TextInput id="textInput3" text="@{textInput4.text}" />
<s:TextInput id="textInput4" />
<s:Label text="# cahrs: {textInput3.text.length}"/>
<s:Label text="# cahrs: {textInput4.text.length}"/>
<!-- 对模型单向数据绑定-->
<s:Label text="对模型单向数据绑定"/>
<s:TextInput id="textInput5" text="{_task.name}" focusOut="_task.name=textInput5.text" />
<s:TextInput id="textInput6" text="{_task.name}" focusOut="_task.name=textInput6.text"/>
<!-- 对模型双向数据绑定-->
<s:Label text="对模型双向数据绑定"/>
<s:TextInput id="textInput7" text="@{_task.nameDou}" />
<s:TextInput id="textInput8" text="{_task.nameDou}"/>
</s:Application>
数据绑定将一个属性的值复制给另一个属性,是因为使用了PropertyChangeListener。
要让数据绑定生效(不生成编译器警告),必须在数据绑定的源属性上使用可绑定注释[Bindable],而且在涉及引用具有源属性的Object的变量上,也要使用[Bindable]注释。
第4课 Flex应用程序结构概述
第5课 Spark组件、Halo组件和Flex4命名空间
接下来的内容
第2章 ActionScript 3、XML和E4X
第6课 变量、函数、类型和范围
package model { public class Task { public var name:String; public var something:*; protected var someDate:Date; internal var anInt:int; private var _aNumber:Number; public function Task(name:String = "") { this.name = name; something = "Ostrich"; someDate = new Date(); anInt = Math.random() * 10; _aNumber = Math.random() * 10; } public function getDate():Date { return someDate; } public function getAnInt():int { return anInt; } public function get aNumber():Number { return _aNumber; } public function set aNumber(value:Number):void { _aNumber = value; } } }
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%" initialize="init()"> <fx:Script> <![CDATA[ import model.Task; private function init():void { var task:Task = new Task("learn ActionScript 3"); outputTA.text = "Name: " + task.name + "\n" + "Something: " + task.something + "\n" + "Date: " + task.getDate() + "\n" + "Int: " + task.getAnInt() + "\n" + "Number: " + task.aNumber; task.something = 5; outputTA.text += "\nNow something is: " + task.something; task.aNumber = 3.14; outputTA.text += "\nNow aNumber is: " + task.aNumber; } ]]> </fx:Script> <s:TextArea id="outputTA" width="100%" height="100%"/> </s:Application>
访问控制:public(任何类可以访问),protected(类本身或他的子类,于java不同,protected不允许访问同一包中的类),internal(默认,同一包中的类可以访问),private(类本身可以访问)
可以用特殊类型*表示任何类型。也可以跳过这个类型声明,但那样会生成编译器警告
ActionScript中的基本类型Boolean(true/false),int(32位有符号整数),uint(32位无符号整数),Number(64位浮点数),String(保存文本)
getter和setter用来为私有变量提供像属性一样的访问方式,从外部看和变量一样。按照约定,set函数的参数总是称为value。
第7课 对象、数组、集合和循环
一个函数里的变量都在同一个范围里,即没有块范围的概念。
for each...in循环,他迭代集合中的值
for ...in循环,他迭代集合(或是Object)中的键,可以用这个键来得到值。
可以用new Object()或者{键1:值1, .... }构造对象。
第8课 接口、类型转换、is操作符和as操作符
与java接口不同的是在ActionScript3接口不允许加入常量,但他还是支持getter和setter方法,这点很重要,否则它们对于属性为中心的Flex就没有价值了。
不需要指定接口方法的访问控制,因为接口中的所有函数都是共有的(public)。
类型转换与java也不同,如将Object转换为Person,在java中(Person)Object,在ActionScript3中,Person(Object)。
is操作符:可以转换返回true,反之false。
as操作符:在类型转换可能失败的地方(对象类型不对),可以安全地使用as操作符,如果类型不匹配,只是返回null,所以我们使用了null检查。所以可以用as而不作is测试。
第9课 继承
ActionScript3中没有抽象类,可以用下面方法伪造抽象类:
package model { //定义接口,关键字nterface public interface IThing { function get name():String; function set name(value:String):void; function getPoints():int; } }
package model { //定义的伪造抽象类,实现接口关键字implements。定义类关键字class public class Thing implements IThing { protected var _name:String; public function Thing(name:String = "") { this.name = name; } //如果没有实现的方法,则抛出一Error public function getPoints():int { throw new Error("Unimplemented getPoints method"); } public function set name(value:String):void { _name = value; } public function get name():String { return _name; } } }
package model { //继承类关键字 extends public class Task extends Thing { public var points:int; public var due:Date; public static const ONE_DAY_IN_MSEC:Number = 1000*60*60*24; public function Task(name:String = "") { super(name);//父类的构造函数 due = new Date(); due.setTime(due.getTime() + ONE_DAY_IN_MSEC); } //覆盖函数时,需要使用override关键字 public override function getPoints():int { return points; } } }
第10课 E4X、XML、XNLList和XMLListCollection
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="50%" height="100%" initialize="init()"> <fx:Script> <![CDATA[ //下面三个都是Flex的框架类 import mx.collections.Sort; import mx.collections.SortField; import mx.collections.XMLListCollection; private var _projectsXML:XML= <projects> <project id="1" name="Proj1"> <task id="1"> <name>Understand E4X</name> <notes>cool, for XML anyway</notes> </task> <task id="2"> <name>Learn XMLList</name> <notes>simple</notes> </task> </project> <project id="2" name="Proj2"> <task id="3"> <name>Learn XMLListCollection</name> </task> <task id="4"> <name>Get a coffee</name> <notes>very necessary</notes> </task> </project> </projects>; private function init():void{ var output:String="开始\n"; output+="Full XML:\n"+_projectsXML; output+="\n\nUsing E4X and XMLList:\n"; //可以用E4X按索引得到子节点,也可以通过搜索特性值得到子节点 output+=_projectsXML.project[0].task[0].name+"\n"; output+=_projectsXML.project.(@name=="Proj2").task.(@id==3).name; //获取一个XML对象的孩子节点时,就得到一个XMLList集合。 var projects:XMLList=_projectsXML.children(); for each(var project:XML in projects){ //可以用句号(.)语法检索E4X、特性和子元素值,对于特性值只需添加@前缀即可 output+="Project:" +project.@name+"\n"; for each(var task:XML in project.task){ output+="Task"+task.@id+":"+task.name; if(task.hasOwnProperty('notes')){ output+="("+task.notes+")"; } output+="\n"; } } output+="\nLearning XMLListCollection and Sorting:\n" //通过获取名为task的根节点的全部子元素,构建一个包含所有任务的新XMLListCollection集合。请注意,这个集合不包含文本节点,XML注释,处理指令和特性。 var allTasks:XMLListCollection=new XMLListCollection(_projectsXML.descendants("task")); var sort:Sort=new Sort(); sort.fields=[new SortField("name",true)]; allTasks.sort=sort; allTasks.refresh(); for each (var sortedTask:XML in allTasks) { output += sortedTask.name + "\n"; } outputTA.text = output; } ]]> </fx:Script> <s:TextArea id="outputTA" width="100%" height="100%"/> </s:Application>
ArrayCollection和XMLListCollection都扩展自ListCollectionView,ListCollectionView实现了IList接口和ICollectionView接口。
接下来的内容
第3章 Spark入门:基本类型、组件、FXG和MXML图形、视频
第11课 Spark基本类型
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"> <fx:Script> <![CDATA[ import mx.graphics.SolidColorStroke; private const _scs:SolidColorStroke=new SolidColorStroke(0x000000,5,1.0); ]]> </fx:Script> <s:Panel width="80%" height="80%" title="Primitives!"> <s:Ellipse x="12" y="39" width="50" height="40" stroke="{_scs}" /> <s:Rect x="127" y="40" width="50" height="40" stroke="{_scs}"/> <s:Line xFrom="90" yFrom="80" xTo="60" yTo="140" stroke="{_scs}"/> <s:Path data="M30 168L132 186 162 144 88 165 44 122" stroke="{_scs}"/> <s:Label text="In session 16 we'll take this further!" x="190" y="130" rotation="-30"/> <s:RichEditableText text="(select and type!)" x="260" y="120"/> <s:BitmapImage x="221" y="145" source="@Embed('HF4.png')"/> </s:Panel> </s:Application>
Spark基本类型是构建Spark组件的构造块。
能够有笔画的类扩展自StrokedElement,能够有填充的类扩展子FliiedElement。
交互性的类扩展自InteractiveObject
下面的继承层次结构展示了所有这些组件之间的关系:
第12课 简单的Spark组件
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%"> <fx:Script> <![CDATA[ [Bindable] private var _theory:String=""; [Bindable] private var _bread:Number = 4; ]]> </fx:Script> <fx:Declarations> <s:RadioButtonGroup id="moralityRBG"/> <s:RadioButtonGroup id="restaurantRBG" selectedValue="{_theory.length%2==0?'smoking':'non'}"/><!--注意--> </fx:Declarations> <s:Panel width="100%" height="100%" title="Simple Components!"> <s:layout> <s:HorizontalLayout paddingLeft="5" paddingTop="5"/> </s:layout> <s:VGroup> <s:TextArea id="textArea" width="200" height="50" text="@{_theory}"/> <s:TextInput id="textInput" width="200" text="@{_theory}"/> <s:HSlider minimum="0" maximum="11" id="hSlider" liveDragging="true" width="200" value="@{_bread}" /> <s:VSlider id="vSlider" minimum="0" maximum="11" liveDragging="true" height="50" value="@{_bread}"/><!--这里做的双向关联就死机,记得_bread要初始化一个值,不要设为Number.NaN--> <s:Button label="{_theory}" width="200" color="{alarmTB.selected ? 0xFF0000 : 0}" click="_bread = Math.min(_theory.length, 11)"/> <s:CheckBox id="checkBox" selected="{_bread % 2 == 0}" label="even?"/> </s:VGroup> <s:VGroup> <s:RadioButton label="Good" value="good" group="{moralityRBG}"/> <s:RadioButton label="Evil" value="evil" group="{moralityRBG}"/> <s:RadioButton label="Beyond" value="beyond" group="{moralityRBG}"/> <s:RadioButton label="Smoking" value="smoking" group="{restaurantRBG}"/> <s:RadioButton label="Non-Smoking" value="non" group="{restaurantRBG}"/> <s:ToggleButton id="alarmTB" label="ALARM!"/> <s:NumericStepper id="numericStepper" value="@{_bread}" minimum="0" maximum="11" stepSize="1"/> <s:Spinner id="spinner" value="@{_bread}" minimum="0" maximum="11" stepSize="1"/> </s:VGroup> </s:Panel> </s:Application>
这个代码和书上的不同,貌似书上的有点问题,主要就是那个做双向关联和值的初始化问题。
第13课 数据驱动的Spark组件(列表)
第14课 FXG和MXML图形——制作一个游戏
第15课 摄像头和视频——个假的twitter客户端
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%" applicationComplete="onApplicationComplete(event)"> <fx:Script> <![CDATA[ import mx.controls.Alert; import mx.events.FlexEvent; import flash.media.Camera; import flash.media.Video; private function onApplicationComplete(event:FlexEvent):void { var camera:Camera = Camera.getCamera();//获取Camera if (camera == null) { Alert.show("Buy a Mac.", "No Camera!"); return; } var video:Video = new Video(320,240);//建立一个Video对象来显示视频 video.attachCamera(camera);//将Camera连接上Video videoHolder.addChild(video); focusManager.setFocus(tweetTA);//TextArea获得焦点 } ]]> </fx:Script> <s:Panel x="50" y="50" width="1000" height="310" title="Forget everybody else, what are you doing?"> <s:SpriteVisualElement id="videoHolder" width="100%" height="100%"/> <s:TextArea id="tweetTA" x="340" y="10" width="640" height="170" maxChars="280"/> <s:Button label="Tweet" x="340" y="190" width="640"/> </s:Panel> </s:Application>
以上实现在Flex应用程序中使用Flash的Camera和Video
接下来的内容
第4章 Spark容器、视图状态、特效和样式
第16课 Spark容器和布局
布局和容器在Spark中已经解耦。
容器和布局的类层次结构图:
1.四种布局概述
在Flex SDK 4(Gumbo)的spark组件库里面增加了一个page:spark.layouts。
其中包括了比较重要的四个布局class,分别是:BasicLayout、HorizontalLayout、TileLayout、VerticalLayout
1、BasicLayout:(默认属性,当不指定定位后,则是绝对定位布局)
这是spark组件默认Flex SDK 3的布局方式,即绝对定位布局。
在Flex SDK 3 里面对应的是:layout="absolute"
2、HorizontalLayout:
这是spark组件库里面的水平布局方式。
在里面对应的是:layout="horizontal"
3、VerticalLayout:
这是spark组件库里面的竖直布局方式。
在Flex SDK 3 里面对应的是:layout="vertical"
4、TileLayout:
这是spark组件库新增的布局方式,即格子布局方式。
TileLayout布局方式可以说是HorizontalLayout和VerticalLayout结合的方式。
请注意,在高度不确定的时候,TileLayout只使用一列。
还有一点是需要注意的:
paddingLeft、paddingRight、paddingTop、paddingBottom
这四个属性已经转移到了HorizontalLayout、VerticalLayout里面。这点也与Flex SDK 3有些区别。也就是说,在spark组件中的容器,已经不具备paddingLeft、paddingRight、paddingTop、 paddingBottom属性了。
第17课 视图状态
自定义组件HPanel(H代表标题)
<?xml version="1.0" encoding="utf-8"?> <s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="onCreationComplete()"> <fx:Metadata> [Event(name="headerClick")] </fx:Metadata> <fx:Script><![CDATA[ import flash.events.Event; import spark.skins.spark.PanelSkin; private function onCreationComplete():void { var panelSkin:PanelSkin = skin as PanelSkin; if (panelSkin == null) return; panelSkin.addEventListener(MouseEvent.CLICK, onHeaderClick); } private function onHeaderClick(event:MouseEvent):void { if (event.currentTarget is PanelSkin) { var ps:PanelSkin = PanelSkin(event.currentTarget); if (event.localY < 30) { dispatchEvent(new Event("headerClick")); } } } ]]></fx:Script> <s:layout> <s:VerticalLayout paddingLeft="10" paddingTop="10" paddingBottom="10" paddingRight="10"/> </s:layout> </s:Panel>
测试应用程序,监听HPanel的headerClick事件,并做出相应的响应
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:comp="components.*" width="100%" height="100%"> <fx:Script><![CDATA[ private function toggleState(newState:String):void { currentState = (currentState == newState) ? '' : newState; } ]]></fx:Script> <s:layout><s:BasicLayout/></s:layout> <s:states> <s:State name="default"/> <s:State name="stateOne" stateGroups="[noStateTwo, noStateThree]"/> <s:State name="stateTwo" stateGroups="[noStateOne, noStateThree]"/> <s:State name="stateThree" stateGroups="[noStateOne, noStateTwo]"/> </s:states> <comp:HPanel id="stateOnePanel" title="State One Panel" left="10" top="10" width="200" right.stateOne="10" height="100" bottom.stateOne="10" excludeFrom="noStateOne" headerClick="toggleState('stateOne')"> <s:Label text="松尾 芭蕉" fontSize="20" fontSize.stateOne="140"/> </comp:HPanel> <comp:HPanel id="stateTwoPanel" title="State Two Panel" left="10" bottom="10" top="115" top.stateTwo="10" width="200" right.stateTwo="10" excludeFrom="noStateTwo" headerClick="toggleState('stateTwo')"> <s:Label width="100%" height="100%" fontStyle="italic" text="(I am trusting that the following pages http://en.wikipedia.org/wiki/Matsuo_Bash%C5%8D and http://en.wikisource.org/wiki/Frog_Poem have the Kanji of Matsuo Bashō's name and famous poem correct.)"/> </comp:HPanel> <comp:HPanel id="stateThreePanel" title="State Three Panel" excludeFrom="noStateThree" top="10" left="220" left.stateThree="10" right="10" bottom="10" headerClick="toggleState('stateThree')"> <s:Label fontSize="50" fontSize.stateThree="70" text="古池や 蛙飛びこむ 水の音"/> <s:Label text="--Matsuo Bashō The ancient pond A frog leaps in The sound of the water. --Donald Keene"/> </comp:HPanel> </s:Application>
第18课 特效和动画
第19课 CSS样式
第20课 MXML的内在原理
第21课 Spark组件的生命周期
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" preinitialize="onPreinitialize(event)" initialize="onInitialize(event)" creationComplete="onCreationComplete(event)" elementAdd="onElementAdd(event)" elementRemove="onElementRemove(event)" applicationComplete="onApplicationComplete(event)" width="100%" height="100%"> <fx:Script><![CDATA[ import spark.events.ElementExistenceEvent; import mx.events.FlexEvent; [Bindable] private var _text:String = ""; protected function onPreinitialize(event:FlexEvent):void { _text += "onPreinitialize: " + event + "\n"; } protected function onInitialize(event:FlexEvent):void { _text += "onInitialize: " + event + "\n"; } protected function onCreationComplete(event:FlexEvent):void { _text += "onCreationComplete: " + event + "\n"; } protected function onApplicationComplete( event:FlexEvent):void { _text += "onApplicationComplete: " + event + "\n"; } protected function onElementAdd(event:ElementExistenceEvent): void { _text += "onElementAdd: " + event + ", target = " + event.element + "\n"; } protected function onElementRemove( event:ElementExistenceEvent):void { _text += "onElementRemove: " + event + "\n"; } ]]></fx:Script> <s:layout> <s:VerticalLayout paddingLeft="10" paddingTop="10" paddingRight="10" paddingBottom="10"/> </s:layout> <s:Button id="kenny" label="Mmmph!" click="removeElement(kenny)"/> <s:TextArea id="debugTA" text="{_text}" width="100%" height="100%"/> </s:Application>
运行:
点击“Mmmph!”按钮:
接下来的内容
第5章 Flex4的Halo组件:使用DataGrid、导航容器
和弹出窗口
第22课 List和DataGrid
package model { [Bindable] public class Task { public var name:String; public var notes:String; public var due:Date; public function Task( name:String = "", notes:String = "", due:Date = null) { this.name = name; this.notes = notes; this.due = due == null ? new Date() : due; } } }
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%"> <fx:Script> <![CDATA[ import model.Task; import mx.collections.ArrayCollection; [Bindable] private var _tasks:ArrayCollection = new ArrayCollection([ new Task("Learn Flex 4", "This book is helping!",new Date(1999)), new Task("Lose weight", "Exercise? Fad diet? Both?"), new Task("Buy groceries", "Including vegetables this time!"), new Task("Eat"), new Task("Drink"), new Task("Be Merry") ]); private function formatTask(task:Task):String { return task.name + (task.notes == "" ? "" : (" (" + task.notes + ")")) + ", due on " + dateFormatter.format(task.due) + "."; } private function formatDate(item:Object, column:DataGridColumn):String { var task:Task = item as Task; return task == null ? "" : dateFormatter.format(task.due); } ]]></fx:Script> <fx:Declarations> <mx:DateFormatter id="dateFormatter" formatString="YYYY-MM-DD"/> </fx:Declarations> <s:layout> <s:HorizontalLayout paddingLeft="10" paddingTop="10" paddingBottom="10" paddingRight="10"/> </s:layout> <mx:List dataProvider="{_tasks}" labelFunction="formatTask" alternatingItemColors="[#EEEEEE, #FFFFFF]" variableRowHeight="true" wordWrap="true" width="250" height="150"/> <mx:DataGrid width="100%" height="150" dataProvider="{_tasks}"> <mx:columns> <mx:DataGridColumn headerText="Name" dataField="name" width="150"/> <mx:DataGridColumn headerText="Due" dataField="due" width="100" labelFunction="formatDate"/> <mx:DataGridColumn headerText="Notes" dataField="notes"/> </mx:columns> </mx:DataGrid> </s:Application>
第23课 TabNavigator、ViewStack和Accordion
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%" initialize="init()"> <s:layout> <s:VerticalLayout paddingLeft="10" paddingTop="10" paddingRight="10" paddingBottom="10"/> </s:layout> <mx:Panel width="100%" height="100%" title="I See Your Halo..."> <mx:LinkBar dataProvider="{vs}" width="100%"/> <mx:ViewStack id="vs" width="100%" height="100%"> <mx:TabNavigator width="100%" height="100%" paddingLeft="5" label="Tab Navigator"> <mx:VBox label="One" width="100%" height="100%"> <mx:Label text="Here's a button:"/> <mx:Button label="A Halo Button"/> </mx:VBox> <mx:VBox label="Two" width="100%" height="100%"> <mx:Label text="Shameless self-promotion:"/> <mx:Image source="http://www.manning.com/armstrong/armstrong_cover150.jpg"/> </mx:VBox> <mx:VBox label="Three" width="100%" height="100%"> <mx:Label text="Stuff inside Three"/> </mx:VBox> </mx:TabNavigator> <mx:Accordion width="100%" height="100%" label="Accordion"> <mx:VBox label="Four" width="100%" height="100%"> <mx:Label text="Stuff inside Four"/> </mx:VBox> <mx:VBox label="Five" width="100%" height="100%"> <mx:Label text="Stuff inside Five"/> </mx:VBox> <mx:VBox label="Six" width="100%" height="100%"> <mx:Label text="Stuff inside Six"/> </mx:VBox> </mx:Accordion> </mx:ViewStack> </mx:Panel> </s:Application>
Halo导航容器(像ViewStack,TabNavigator,Accordion)只能包含Halo容器子组件(像VBox,HBox,Box或Canvas)。不能将Spark的Group直接放在导航容器内,也不能将Spark或Halo的TextInput直接放在任何导航容器内。
第24课 Alert.show PopupManager
<?xml version="1.0" encoding="utf-8"?> <mx:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" layout="vertical" title="TestTitleWindow" width="600" height="400" showCloseButton="true" close="PopUpManager.removePopUp(this);"> <fx:Script> <![CDATA[ import mx.managers.PopUpManager; ]]> </fx:Script> <s:Group width="100%"> <s:Label text="You can put a lot in a TitleWindow!"/> </s:Group> <mx:RichTextEditor id="richTextEditor" width="100%" height="100%"/> </mx:TitleWindow> <!--在TitleWindow这个容器内,既能使用Spark的Group,也可以使用Halo组件。-->
<?xml version="1.0" encoding="utf-8"?>
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%" height="100%"
initialize="init()">
<fx:Script><![CDATA[
import mx.events.CloseEvent;
import mx.controls.Alert;
import mx.managers.PopUpManager;
private function showAlert(event:MouseEvent):void {
Alert.show('That was easy!', 'Alert!');
}
private function showPopUp(event:MouseEvent):void {
var titleWindow:TestTitleWindow = TestTitleWindow(
PopUpManager.createPopUp(this, TestTitleWindow, true));//modal 如果为 true,则该窗口为模态窗口,也就是说在删除该窗口之前,用户将无法与其它弹出窗口交互。
titleWindow.x = 50;
titleWindow.y = 50;
titleWindow.addEventListener(CloseEvent.CLOSE, onCloseTTW);
}
private function onCloseTTW(event:CloseEvent):void {
var ttw:TestTitleWindow = TestTitleWindow(event.target);
richEditableText.text = ttw.richTextEditor.htmlText;
}
]]></fx:Script>
<s:layout>
<s:VerticalLayout paddingLeft="10" paddingTop="10"
paddingRight="10" paddingBottom="10"/>
</s:layout>
<s:Button label="Show Alert" click="showAlert(event)"/>
<s:Button label="Show TestTitleWindow" click="showPopUp(event)"/>
<s:Label text="HTML from TestTitleWindow RichTextEditor:"
fontWeight="bold"/>
<s:RichEditableText id="richEditableText" width="100%"
height="100%"/>
</s:Application>
接下来的内容
第6章 用Flex格式化器和验证器构建用户友好的表单
第25课 格式化器和验证器
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%"> <fx:Script><![CDATA[ protected function moneyTIFocusOutHandler(event:FocusEvent):void {//当发生focusOut事件时,这个函数格式化输入框的文本 var formattedText:String = currencyFormatter.format(moneyTI.text); //格式化器在失败的时候返回空字符串,所以一定要检查 if (formattedText != "") {//只有在格式化成功后才将文本框中的文本赋值给moneyTI moneyTI.text = formattedText; } } ]]></fx:Script> <fx:Declarations> <mx:CurrencyFormatter id="currencyFormatter" precision="2" rounding="nearest"/> <mx:CurrencyValidator id="currencyValidator" precision="2" source="{moneyTI}" property="text" triggerEvent="focusOut"/> </fx:Declarations> <s:layout> <s:VerticalLayout paddingTop="10" paddingLeft="10"/> </s:layout> <s:TextInput id="moneyTI" focusOut="moneyTIFocusOutHandler(event)"/> <s:Button label="Really, I'm just here for the focus..."/> </s:Application>
第26课 真实的表单、格式化器和验证器
接下来的内容
第7章 Cairngorm实践:SocialStalkr(twitter+雅虎地图)
创建SocialStalkr项目
twitter入门
雅虎地图入门
Caimgorm
Caimgorm的历史和动机
下载和安装Caimgorm 2.2.1
Cairngorm事件顺序概述
创建主应用程序
创建ModelLocator
创建控制包
SocialStalkrController.as
创建CairngormUtils和ServiceUtils
创建TwittefDelegate
创建命令
创建可视组件
接下来的内容