[TOC]
http://flex.apache.org/tourdeflex/index.html
**MXML**
MXML 是一種基于XML標簽的標記語言,用于基于Flex的用戶界面的組件和數據資產的布局和設計
**默認命名空間:**
fx-引用特殊語言聲明性標簽
s-引用Flex4框架中引入的spark組件庫
mx-引用Flex3框架中引入的MXML組件庫,在Flex4中仍然堅持
### MXML 語法
* * * * *
#### **設置組件屬性**
MXML中組件屬性使用的命名約定和對應的ActionScript屬性相同。屬性名以小寫字母開頭,大寫字母區分屬性名中的單詞。
大多數組件屬性設置和標簽屬性一樣,形式如下:
~~~
<mx:Label width="50" height="25" text="Hello World"/>
所有組件屬性可以設置為子標簽,形式如下:
<mx:Label>
<mx:width>50</mx:width>
<mx:height>25</mx:height>
<mx:text>Hello World</mx:text>
</mx:Label>
~~~
使用常量設置屬性
很多組件屬性的有效值由靜態常量定義,這些靜態常量在ActionScript類中定義。MXML中可以使用靜態常量設置屬性值,也可以使用靜態常量值,如下所示:
~~~
<!-- 使用靜態常量設置屬性。 -->
<mx:HBox width="200" horizontalScrollPolicy="{ScrollPolicy.OFF}">
...
</mx:HBox>
~~~
#### **在String值中包含換行符**
對于String類型的屬性,有兩種方式在String中插入換行符:
* 在MXML的String值中插入 代碼
* 在ActionScript 用來初始化MXML 屬性的String變量中插入“/n”
要使用&\#13;代碼插入換行符,可以在MXML的屬性值中包含該代碼,如下所示:
`<mx:TextArea width="100%" text="Display Content"/>`
要使用ActionScript String變量插入換行符,可以創建一個ActionScript變量,然后使用數據綁定設置MXML中的屬性,如下所示:
~~~
<mx:Script>
<![CDATA[
[Bindable]
public var myText:String = "Display" + "/n" + "Content";
]]>
</mx:Script>
<mx:TextArea width="100%" text="{myText}"/>
~~~
本例中,TextArea控件的text屬性值被設置為包含一個換行符。
<font color="red">注意,本例中在屬性定義前有[Bindable]元數據標簽。</font>
元數據標簽指定了myText屬性可以作為數據綁定表達式的source。運行時當屬性變化時數據綁定會自動將一個對象的source屬性值復制給另一個對象的destination屬性。
如果你省略了元數據標簽,編譯器會發出警告,指出該屬性不能作為數據綁定的source。
#### **設置標量值數組**
當一個類以數組作為它的屬性值時,可以在MXML中使用子標簽表示該屬性。下面例子中的組件有一個dataProvider屬性,包含數字數組:
~~~
<mx:List width="150">
<mx:dataProvider>
<mx:Array>
<mx:Number>94062</mx:Number>
<mx:Number>14850</mx:Number>
<mx:Number>53402</mx:Number>
</mx:Array>
</mx:dataProvider>
</mx:List>
~~~
數組元素外的<mx:Array>和</mx:Array>標簽可選。因此,這個例子代碼也可以寫成以下所示:
~~~
<mx:List width="150">
<mx:dataProvider>
<mx:Number>94062</mx:Number>
<mx:Number>14850</mx:Number>
<mx:Number>53402</mx:Number>
</mx:dataProvider>
</mx:List>
~~~
本例中,因為dataProvider屬性的數據類型定義為數組,因此Flex會自動將三個數字定義轉換為一個三元素數組。
#### **設置Object 屬性**
當組件以對象作為屬性值時,可以在MXML中用含標簽屬性的子標簽表示該屬性:
以下示例給出了一個ActionScript類,定義了一個含Address類型屬性的PurchaseOrder組件:
~~~
import example.Address;
class PurchaseOrder {
public var shippingAddress:Address;
public var quantity:Number;
...
}
~~~
MXML中定義了PurchaseOrder組件,如下所示:(mynamespace 為自己的命名空間)
~~~
<mynamespace:PurchaseOrder quantity="3" xmlns:e="example">
<mynamespace:shippingAddress>
<mynamespace:Address name="Fred" street="123 Elm St."/>
</mynamespace:shippingAddress>
</mynamespace:PurchaseOrder>
~~~
#### **填充對象數組**
~~~
<fx:Declarations>
<!-- 將非可視元素(例如服務、值對象)放在此處 -->
<s:ArrayCollection id="sample">
<fx:Object label="Binding" cls="{BindingSample}"/>
<fx:Object label="Layout" cls="{LayoutSample}"/>
<fx:Object label="Binding" cls="{BindingSample}"/>
<fx:Object label="Layout" cls="{LayoutSample}"/>
<fx:Object label="Binding" cls="{BindingSample}"/>
<fx:Object label="Layout" cls="{LayoutSample}"/>
</s:ArrayCollection>
</fx:Declarations>
...
<s:ButtonBar width="100%" id="myButtonBar" change="indexChangeHandler(event)" dataProvider="{sample}"/>
~~~
效果圖:

#### **在MXML中設置樣式和效果屬性**
MXML標簽中的樣式或效果屬性和其他屬性不同,因為它對應于ActionScript樣式或效果,而不是ActionScript類的屬性。
在ActionScript使用setStyle(stylename, value)方法設置這些屬性,而不是object.property=value。
比如,在MXML設置fontFamily樣式屬性,如下所示:
~~~
<mx:TextArea id="myText" text="hello world" fontFamily="Tahoma"/>
~~~
該 MXML 代碼等價于以下ActionScript 代碼:
~~~
myText.setStyle("fontFamily", "Tahoma");
~~~
#### **在MXML 中設置事件屬性**
MXML標簽的事件屬性允許你指定事件的事件監聽器。該屬性相當于在ActionScript中使用addEventListener()方法設置事件監聽器。
比如,你可以在MXML中設置creationComplete事件屬性,代碼如下所示:
~~~
<mx:TextArea id="myText" creationComplete="creationCompleteHandler()"/>
~~~
該 MXML 代碼等價于以下ActionScript 代碼:
~~~
myText.addEventListener("creationComplete", creationCompleteHandler);
~~~
#### **編寫ActionScript**
MXML文件經過編譯最后也是被轉換成AS來執行,在一個Flex程序中,主程序會被轉換為Application對象的子類,自定義對象會被轉換為父級對象的子類
在MXML中插入AS塊
~~~
<mx:Script>
<![CDATA[
//這里是AS代碼
]]>
</mx:Script>
~~~
此標簽可以放在根節點內的任何位置,同時必須用CDATA將代碼包起來。CDATA不能嵌套使用。
AS中的注釋是 //單行注釋
MXML中的注釋和XML一樣 <\!-- 注釋-->
#### **舉個栗子**
~~~
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx = http://www.adobe.com/2006/mxml fontSize="12">
<mx:Panel title="測試" width="400" height="200">
<mx:HBox width="300" height="150">
<mx:Button label="按鈕" x="20" y="30"/>
<mx:Label text="文本"/>
</mx:HBox>
</mx:Panel>
</mx:Application>
~~~
<mx:Application>
這里的<mx:Application>是mxml的最外一層的標簽做為根節點 根據xml的語法 需要一個命名空間“xmlns:mx”這就是一個命名空間
<mx:Panel>
這是面板組件 常用于其它組件的容器使用;使用title可以指定其標題名稱
<mx:HBox>
這是一個矩形容器組件 注:在 mxml中容器和容器之間可以相互嵌套。
<mx:Button>
這是一按鈕組件可以使用 label 指定其按鈕名稱
<mx:Label>
是一標簽組件 可以使用 text指定其中的內容

* * * * *
### 數據綁定
將一個任意對象上所做的任何更新和修改,自動反映到另一個對象上
* 直接綁定
~~~
<s:Label text="添加綁定(合并字符串)"/>
<s:HGroup>
<s:TextInput id="myText03"/>
<s:Label text="+"/>
<s:TextInput id="myText04"/>
<s:Label text="="/>
<s:TextInput id="myText05" text="{myText03.text + myText04.text}"/>
</s:HGroup>
~~~
* 標簽綁定
~~~
<s:Label text="綁定標簽(相互綁定)"/>
<fx:Binding source="myText06.text" destination="myText07.text" twoWay="true"/> <!--雙向綁定-->
<s:HGroup>
<s:TextInput id="myText06"/>
<s:Label text="="/>
<s:TextInput id="myText07"/>
</s:HGroup>
~~~
* AS變量綁定
~~~
<fx:Script>
<![CDATA[
[Bindable]
public var s:String = "";
]]>
</fx:Script>
<s:Label text="綁定AS變量"/>
<s:HGroup>
<s:TextInput id="myText08"/>
<s:Button label="update var" click="{s = myText08.text}"/>
<s:TextInput id="myText09" text="{s}"/>
</s:HGroup>
~~~
栗子:

### 布局
~~~
<s:BorderContainer id="container" width="100%" height="100%">
<s:layout>
<s:BasicLayout/> <!-- HorizontalLayout、VerticalLayout 、TileLayout -->
</s:layout>
<s:Label id="title" text="絕對布局"/>
<s:Button id="btn1" label="Button_01" width="300" mouseDown="{btn1.startDrag()}" mouseUp="{btn1.stopDrag()}"/>
<s:Button id="btn2" label="Button_02" width="300" mouseDown="{btn2.startDrag()}" mouseUp="{btn2.stopDrag()}"/>
<s:Button id="btn3" label="Button_03" width="300" mouseDown="{btn3.startDrag()}" mouseUp="{btn3.stopDrag()}"/>
</s:BorderContainer>
~~~
* BasicLayout(絕對布局)-- 手動定位坐標

* HorizontalLayout(水平布局)

* VerticalLayout(垂直布局)

* TileLayout(網格布局)

### 常用組件
* * * * *
# **Hello Again...**
* * * * *
### **視圖狀態(狀態機)**
##### **什么是狀態**
看起來是兩個不同的頁面,其實這是同一個自定義的組件。
它具有兩種狀態,Login狀態和Register狀態,狀態不同,呈現出來的東西就不同。
 
##### **定義狀態(寫在<s:states />)**
~~~
<s:states>
<s:State name="default"/>
<s:State name="Register"/>
</s:states>
~~~
##### **改變狀態**
UIComponent類定義了一個**currentState屬性**,通過改變這個屬性的值來更換狀態。
這個屬性的默認值是定義在需在<states></states>標簽內的第一個狀態.
<font color='red'>UIComponent 類是所有可視組件(交互式和非交互式)的基類。</font>
~~~
<s:Button id="b1" label="Change to State 1" click="currentState='State2';"/>
<s:Button id="b2" label="Change to the default" click="currentState='State1';"/>
~~~
##### **組件的狀態**
通過點語法來設定一個組件屬于某個狀態的屬性值
~~~
<s:Button id="loginButton" label="Login" label.Register="Register"/>
~~~
對于事件也一樣可以用點語法,例如:
~~~
<s:Button id="b0" label="Default State" />
<s:Button id="b1" label="Click Me" click="b0.label='hello'" click.state_01="b0.label='goodbye'"/>
~~~
##### **添加或移除組件**
組件多了兩個屬性,includeIn和excludeFrom。
includeIn, 表示這個組件要被添加到屬性值所指的狀態,
excludeFrom,表示這個組件要從屬性值所指的狀態中刪除,
includeIn和 excludeFrom不能在同一個組件標簽里出現,他們的值可以是多個狀態,之間用逗號隔開。
~~~
<s:states>
<s:State name="default"/>
<s:State name="state_01"/>
<s:State name="state_02"/>
<s:State name="state_03"/>
</s:states>
<s:CheckBox id="myCB" label="Checkbox" includeIn="state_01, state_03"/>
<s:TextArea text="Exclude from addTextInput" excludeFrom="state_02"/>
~~~
##### **更改一個組件的父元素**
~~~
<s:Panel id="Panel1" height="100" width="100" title="Panel 1">
<s:Button id="sonButton" includeIn="Parent1" label="son"/>
</s:Panel>
<s:Panel id="Panel2" height="100" width="100" title="Panel 2">
<fx:Reparent target="sonButton" includeIn="Parent2"/>
</s:Panel>
~~~
我們要換父親的組件就是sonButton。
includeIn="Parent2"告訴我們了,在狀態Parent2時,就要換了sonButton的父元素,換成fx:Reparent的父元素,即第二 個panel。
### **拖放**
##### **基本的拖放**
指定組件的mouseDown事件為 startDrag()方法
指定組件的mouseUp事件為 stopDrag()方法(否則組件會一直處于可拖放狀態)
~~~
<s:Button id="btn01" label="這是一個按鈕" mouseDown="{btn01.startDrag()}" mouseUp="{btn01.stopDrag()}"/>
<s:Image id="img01" x="300" source="temp.jpg" mouseDown="{img01.startDrag()}" mouseUp="{img01.stopDrag()}"/>
~~~
##### **列表類組件中拖放**
在列表類組件中拖放在,只需要將組件的dropEnabled,dragEnabled 屬性都設為true就可以
dragMoveEnabled 屬性 默認為false 表示拖動數據項時默認執行復制操作
~~~
<s:List id="selecte" height="100%" allowMultipleSelection="true" dropEnabled="true" dragEnabled="true" dragMoveEnabled="true"/>
<s:List id="draged" height="100%" dropEnabled="true" dragEnabled="true"/>
~~~
效果:

##### **在非列表類組件中拖放**
其一:需要將拖放的組件的mouseDown事件設置為初始化的 dragSource()函數;
~~~
protected function dragSource(event:MouseEvent):void
{
var dragInitiator:Button = Button(event.currentTarget);
var dragSource:DragSource = new DragSource();
var screenshot:BitmapData = new BitmapData(dragInitiator.width,dragInitiator.height);
screenshot.draw(this);
var proxy:Image = new Image();
proxy.source = new Bitmap(screenshot.clone()); // 演示如何抓取拖動組件的 “屏幕截圖”
dragSource.addData({"x":event.localX,"y":event.localY},"button");
DragManager.doDrag(dragInitiator,dragSource,event,proxy); //proxy 是拖放代理 用來顯示拖放狀態的圖片
}
~~~
其二:需要給放置的組件設置 dragEnter 事件,事件里判斷是否接受拖動
~~~
protected function onEnter(event:DragEvent):void
{
if(event.dragSource.hasFormat("button"))
{
if(event.target is Panel)
DragManager.acceptDragDrop(Panel(event.target)); //接受拖動
else{
event.preventDefault(); //阻止使用默認的事件功能
}
}
}
~~~
其三:需要在放置的組件里設置放下的事件 dragEnter
~~~
protected function onDrop(event:DragEvent):void
{
var myData:Object = new Object();
myData = event.dragSource.dataForFormat("button");
btn.x = this.mouseX - myData.x;
btn.y = this.mouseY - myData.y; //設定組件的位置
}
~~~
效果:

~~~
~~~
### **動畫**
##### **簡單示范**
使用Animate來來創建和使用特效是很簡答的:
* 首先要一個目標對象,以及這個對象的某些屬性的名字,
* 這些屬性會被Animate類修改來達到動畫的效果。
* 還有些可選的參數,比如效果持續的時間。
* 一切都設置好后,調用play()來播放就是了
簡單的例子:
我們給一個按鈕應用了動畫效果,動畫的內容是把按鈕向右移動100個像素。
~~~
<fx:Declarations>
<s:Animate id="mover" target="{button}">
<s:SimpleMotionPath property="x" valueFrom="0" valueTo="100"/>
</s:Animate>
</fx:Declarations>
<s:Button id="button" click="mover.play()"/>
~~~
我們還可以通過設置valueBy來設置移動的相對值。也可以只設置valueTo屬性。當然出來的效果是不一樣的。
如果你只設置了valueBy,那每次都是從當前位置再移動一段距離。
如果只設置了valueTo,那按第一次后,以后再按就沒效果了
你可以在一個Animate里設置多個SimpleMotionPath來達到同時往不同方向移動的效果。比如下面這段代碼:
~~~
<s:Animate id="mover" target="{button}" duration="1000">
<s:SimpleMotionPath property="x" valueFrom="0" valueTo="100"/>
<s:SimpleMotionPath property="y" valueTo="100"/>
<s:SimpleMotionPath property="width" valueBy="20"/>
</s:Animate>
~~~
##### **基本特效**
* 移動特效
就比如上面的例子可以用Move類來改寫:
`<s:Move id="mover" target="{button}" xTo="100" yTo="200"/>`
* Resize特效
`<s:Resize id="resizer" widthTo="100" heightTo="50" target="{button}"/>`
* 變形特效:移動,旋轉,伸縮
~~~
<s:Parallel id="transformer" target="{button}">
<s:Move xFrom="50" xTo="150" autoCenterTransform="true"/>
<s:Rotate angleFrom="0" angleTo="90" autoCenterTransform="true"/>
<s:Scale scaleXFrom="1" scaleXTo="2" autoCenterTransform="true"/>
</s:Parallel>
~~~
#### **項渲染器 itemRanderer**
##### **什么是項渲染器?**
指顯示每一條數據時采用的形式
通過自定義的項渲染器,可以很方便的設置列表,表格的條目樣式。
默認的List的渲染器:(類似label組件,只簡單的顯示一行文本)

##### **自定義項渲染器**
通過自定義,用戶可以添加圖片,按鈕,選項框等等組件,來實現多樣的功能。
通過傳入復雜的數據,還可以完成復雜的數據顯示。
下面就是一個自定義的例子:(包含原有的label,添加了復選框以及圖片)
實現了一些小功能(左滑出現選項款,右滑出現刪除等等)
~~~
<s:List id="myList" height="100%" itemRenderer="itemRanderer.render01"/>
...
myList.dataProvider = new ArrayCollection([
{label:"new message...0"},
{label:"new message...1"},
{label:"new message...2"}]};
...
<s:Group id="myGroup">
<s:CheckBox id="check" x="-50" y="{(height-check.height)/2}"/>
<s:Label id="lab" text="{data.label}" fontSize="24" y="{(height-lab.height)/2}"/>
<s:Image x="{width}" source="assert/delete.png"/>
</s:Group>
~~~
