Flex 4 新體驗

  直到最近纔開始真正使用Flash Builder4來開發Flex應用。開始還是用Flex3的思想來進行開發,後來才逐漸發現原來自己Out了,完全沒有用上Flex4的特性。下面僅說一下我用到的Flex4的新特性,當然這不全是Flex4所有新特性。
  1.Spark控件和Skin
  舊的控件仍然在mx命名空間之下,新增加的Spark控件體系也是在UIComponent基類擴展的。所以其根本並沒有動搖,這樣就可以在最大程度上使得mx控件和spark控件最大程度兼容。但是爲什麼要有Spark空間呢,而且多數都是與mx中原有控件一一對應的?目的只有一個那就是要將邏輯和樣式分開。邏輯交給ActionScript負責,而樣式則由Skin來負責。在Skin中可以利用各種flex4提供的繪圖控件,如Path,Rect,Line等等,而有了這些就可以爲控件提供背景色和邊框等樣式,因此Spark控件多數都沒有mx控件所有的backgroundColor,border之類的style屬性。
  你可以在這裏找到關於Spark的架構。在spark體系中,增加Group這個常見的Container,這個有些類似於mx中的Box.因此可以想象會有類似VBox和HBox的VGroup和HGroup。Spark中的容器默認是BasicLayout,當然你可以設置爲HorizantalLayout或者VerticalLayout。在給spark控件的Skin增加Rect或者Line的時候就要注意了,通常是在BasicLayout當中進行繪圖,這樣座標才起作用,而在HorizantalLayout或者VerticalLayout則會影響你所設置的座標。
  對於Spark中的Button等SkinableComponent是如何做到跟Skin結合的呢?我沒有深入研究,但是根據一些粗淺的猜測可能是這樣的:用Button來舉例,利用FlexSpy觀察出來,Button在顯示的時候,它的子節點並不像原來那麼單純,可能就是一個label來顯示文本,spark button的子節點卻是一個ButtonSkin(注意Skin也是從UIComponent繼承下來的),而在ButtonSkin的子節點下面纔會有個Labe文本。因此當我們在ButtonSkin增加各種樣式的時候也就反應到Button。在Button中你可以看到有一個labelDisplay的對象,也就是用於顯示文本的Label,如果在ButtonSkin中我們不包含這個控件,則你的Button即使設置了label也不會顯示任何東西。再提一點,這個labelDisplay在Button中會用SkinPart元素據標明,在Button源代碼中你並沒有看到labelDisplay被顯示地創建。而在mx的button源代碼中我們可以發現有一個textField在createChildren函數中被創建出來,它就是用來顯示button的文本。那怎麼將spark中Button的labelDispaly於Skin中的labelDisplay(注意這兩者的名字必須一致)關聯起來呢?你可以發現在SkinableComponent中有一個PartAdded的方法,而所有子類在繼承該類的時候都會override這個方法以加入自己特定的SkinPart,如果存在SkinPart的話。順着這個方法,你可以找到在該類的attachSkin方法會調用findSkinParts,而findSkinParts則會將Skin中定義的labelDisplay賦值給Button中定義的labelDisplay變量。但實際上這個labelDisplay控件還是Skin的子節點,而不是Button的子節點。
  還要注意對於SkinnableComponent來說存在兩中不同的state,一個是控件本身的,如Button的down,up等狀態,還有就是相應的ButtonSkin的down,up狀態。這兩者是不一樣的。如果你設置了Button的狀態,而不是更新了Skin的狀態,那麼你的Skin中不同狀態的樣式並不會起作用。SkinnalbeComponent中有一個方法是getCurrentSkinState,這個方法的返回值決定了Skin的State,因此你可以發現Button實際上覆蓋了這個方法以返回Skin的不同狀態。爲了判斷Skin的State,Button實際上是監聽了MouseEvent,從而判斷當前處於什麼Skin State。爲了真正使Skin State起作用,還需要調用invalidateSkinState方法。
  2.FXG
  定義了很多基本的圖形如Rect, Line, Path等,對於fxg創建的控件你可以在MXML中直接引用。其實所有fxg控件都有對應的MXML控件。不過兩者之間有個很重要的區別:MXML控件(如s:Rect, s:Line等)會在編譯的時候轉化爲對應的ActionScript類,但是Fxg控件則會轉成更低級別的flash player 指令。也就是說Fxg對應的控件爲被優化,出於性能考慮可以儘量用fxg。從以下鏈接可以找到更多關於Fxg的有用信息。
  DataGroup會提供ItemRender,這個render比原來mx中datagrid的render有所改進,譬如可以得到data和itemIndex,而且可以賦值labelFunction。不過不能提供Skin。因此如果你想要用Skin的話就意味着你需要自己創建一個SkinableComponent,然後將它放入renderer。這樣就遇到一個問題如何使得SkinnableComponent的Skin State會隨着Renderer的state變化而變化。照理來說Renderer的State應該對應的是UIComponent的currentState,但是好像這個值也可以控制Renderer裏面定義的樣式,譬如可以設置某個Rect.includeIn="selected",這樣選中的時候該Rect將顯示。關於Renderer的State是個比較特殊的問題,你可以在官方文檔中找到更多說明:http://help.adobe.com/en_US/flex/using/WS03d33b807 6db57b9-23c04461124bbeca597-8000.html#WS05A80398-9D D3-445a-BD33-A7D9FD695FA3
  itemRendererFunction也是一個好東西,你可以根據情況選擇不同的ItemRenderer。對於
  With virtual layout disabled (useVirtualLayout=false), the DataGroup and SkinnableDataContainer containers create one instance of the item renderer for each child. With virtual layout enabled, the container only creates enough item renderers to display its currently visible children. Virtual layout greatly reduces the overhead required to use the DataGroup and SkinnableDataContainer containers.
  4.Css選擇符
  可以支持子類選擇等特性增加進來。我印象中這個原來就有了。具體我也不熟悉。但是有一點要提醒的是,如果你自定義了一個控件mycomp,在這個控件中引用了一個List,你想對這個List增加樣式,並把樣式設置爲
  local|mycomp s|List{****}
  顯然在mycomp裏面引用該css,這樣任何地方引用mycomp都可以得到一樣的外觀。但是實際上在mycomp中引用css文件的時候會報錯,說什麼List的選擇符不支持。但是我們如果在Application下面引入該css就一切正常。原因沒有深究,但是解決方案就是如果你要在mycomp中引用該css文件,那麼就不要定義類型選擇符,而是用類型選擇符或者id選擇符,如給List增加styleName="list",mycomp增加styleName="mycomp"
  .mycomp .list{*****}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章