2009年4月30日星期四

Flex 4 Gumbo MXML 命名空間的問題   [+/-]

Ticore's Blog

最近開始測試 Flex 4 (Gumbo),發現它的 MXML Namespace 變的好複雜
看文件上寫的 Flex SDK - MXML 2009
Namespace 至少有以下這幾種

xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
xmlns="http://ns.adobe.com/fxg/2008"

搞到頭都昏了,誰知道哪個組件屬於哪個 Namespace 之下
文件上的範例有的打錯字,有的已經過期了
很多範例直接複製下來都無法編譯過
文件上解釋說明一堆,嘗試半天,還是失敗 ><"
不知道大家研究 Flex 4 Gumbo 時,有沒有類似的困擾啊?

Flex 2, 3 以前從來也沒這麼複雜,一個主版本裡面通常只有一種 Namespace
譬如

xmlns:mx="http://www.adobe.com/2006/mxml"
Flex 4 之所以會變成這樣,最主要的原因是想要與 Flex 3 組件相容並且能夠混搭使用
然後又把新增了 FXGSkinning 功能單獨為個別的 Namespace

聽起來好偉大的功能,不過開發工具還沒有支援自動產生語法以前
那真的會搞死人~

為了能夠成功測試 Flex 4 新功能,還是想辦法找出這些 Namespace Mapping 的規則
終於讓我找到了!
原來在 Flex SDK frameworks 目錄內,有一個 flex-config.xml 檔案
裡面會明確的宣告出有哪些 Namespace 可以用
每個 Namespace 包含一個 uri 與一個外部 manifest.xml 檔案路徑

...
  <namespaces>
     <namespace>
        <uri>http://ns.adobe.com/mxml/2009</uri>
        <manifest>mxml-2009-manifest.xml</manifest>
     </namespace>
     <namespace>
        <uri>library://ns.adobe.com/flex/spark</uri>
        <manifest>spark-manifest.xml</manifest>
     </namespace>
     <namespace>
        <uri>library://ns.adobe.com/flex/halo</uri>
        <manifest>halo-manifest.xml</manifest>
     </namespace>
     <namespace>
        <uri>http://www.adobe.com/2006/mxml</uri>
        <manifest>halo-manifest.xml</manifest>
     </namespace>
     <namespace>
        <uri>http://ns.adobe.com/fxg/2008</uri>
        <manifest>fxg-manifest.xml</manifest>
     </namespace>
  </namespaces>
...

而這些外部的 manifest.xml 檔案裡面
放的就是該 Namespace 下隸屬的 Class 與別名啦
以 fxg-manifest.xml 為例:

<?xml version="1.0"?>
<componentPackage>
    <component id="BitmapGraphic" class="spark.primitives.BitmapImage"/>
    <component id="CloseSegment" class="spark.primitives.pathSegments.CloseSegment"/>
    <component id="CubicBezierSegment" class="spark.primitives.pathSegments.CubicBezierSegment"/>
    <component id="Ellipse" class="spark.primitives.Ellipse"/>
    <component id="Graphic" class="spark.primitives.Graphic"/>
    <component id="Group" class="spark.components.Group"/>
......

透過以上的方式,總算可以很清楚找到 MXML Namespace 與 Class 對應關係
不用一直碰壁了!

相關連結:
Flex 4 SDK Gumbo Confluence
Download Flex 4 SDK Gumbo
Flex 4 Gumbo 雙向資料繫結測試
Flex SDK 馬歇爾計畫
AS3 技巧 - 利用 Flex Builder 編譯 Flash 相容 SWC 類別庫

Read more...

2009年4月29日星期三

網路使用者介面模式簡報   [+/-]

Ticore's Blog

最近看到一篇文章 Flex Design After Gumbo
裡面的簡報還挺有趣的 GUI After The Web

其中使用六種對立的特性

  • Open - Close
  • Active - Passive
  • Going - Staying
來分析目前網路上三大使用者模式
  • Linking
  • Watching
  • Doing
然後這三大使用模式對應到三種主要媒介
  • Hypertext
  • Broadcast
  • Application

簡報中還將現實中常用的 Flash、Ajax、Game、YouTube、Flex.... 套用到這 Model 內
還挺有趣的一個分析模式

Read more...

2009年4月28日星期二

一行 AS3 程式讓 Flash Player 10 死機 Part 5   [+/-]

Ticore's Blog

又發現一行 AS3 程式讓 Flash Player Crash 的方法了
這次是從別人網站上發現的 撒旦 Flash 毒药收集
既然都寫過那麼多次了
就引用回來延續之前的主題吧

只要對 Matrix3D 呼叫 append or prepend 並傳入 null 參數
就會造成 Flash Player Crash 了

new Matrix3D().append(null);
new Matrix3D().prepend(null);

以上 Bug 至少會在以下的 Flash Player 版本發生
Flash Player 10.0.1.218
Flash Player 10.0.2.54
Flash Player 10.0.12.10
Flash Player 10.0.12.29
Flash Player 10.0.12.36
Flash Player 10.0.22.87
Flash Player 10.0.32.18

相關連結:
撒旦 Flash 毒药收集
一行 AS3 程式讓 Flash Player 9 死機 Part 4
一行 AS3 程式讓 Flash Player 9 死機 Part 3
一行 AS3 程式讓 Flash Player 9 死機 Part 2
一行 AS3 程式讓 Flash Player 9 死機
用 @* 指定 Attributes 造成 Flash Player 9 Crash

Read more...

2009年4月26日星期日

ActionScript 3 Migration Cookbook   [+/-]

Ticore's Blog

Adobe 最近推出新的線上文件 - ActionScript 3 Migration Cookbook
主要是針對 Flash CS4 有一些開發經驗的設計師或是開發者
面臨一般常用的程式功能上
提供 ActionScript 3.0 新 API 與語法的快速介紹與比較
減少開發人員的疑惑與混淆
讓仍然在使用 ActionScript 2.0 的人能夠比較容易升級至 AS3.0

該單元同時提供了線上 HTML 文件與離線 PDF 文件下載
ActionScript 3 migration cookbook (PDF, 600K)

PDF 文件還特別排版過耶~
實在是跟當年學 AS3.0 的情況差太多了

Read more...

2009年4月25日星期六

Flex 4 Gumbo 雙向資料繫結測試   [+/-]

Ticore's Blog

Flex 4 (Gumbo) 其中之一新特色是雙向資料繫結 (Two-Way Data Binding)
只要在 DataBinding Expression 前面加上 @
編譯器就會自動替你加上雙向的 DataBinding
而且這是由開發者社群提出的新功能要求

聽起來好像挺不錯的,實際來測試看看

注意,以下的程式需要 Flex SDK 4
測試環境 Flex SDK 4.0.0.4904
測試環境 Flex SDK 4.0.0.6310

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    verticalAlign="middle">
 <mx:Panel title="Two-Way Data Binding" layout="vertical"
   verticalAlign="middle" horizontalAlign="center"
   paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
  <mx:HSlider id="slider1" liveDragging="true" value="@{slider2.value}"/>
  <mx:HSlider id="slider2" liveDragging="true" />
 </mx:Panel>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

真的挺方便的,只要在資料來源的一邊撰寫表示式就可以
那萬一不小心兩邊都寫了會怎樣?
順便再加上 trace 觀察 DataBinding 觸發的情況

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    verticalAlign="middle">
 <mx:Panel title="Two-Way Data Binding" layout="vertical"
   verticalAlign="middle" horizontalAlign="center"
   paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
  <mx:HSlider id="slider1" liveDragging="true"
     value="@{trace('binding event'), slider2.value}"/>
  <mx:HSlider id="slider2" liveDragging="true"
     value="@{trace('binding event'), slider1.value}"/>
 </mx:Panel>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

看起來還是能夠正常運作
不過每次每一邊資料只要一變動,Data Binding 馬上會被觸發四次
再深入使用 -keep-generated-actionscript=true (or -keep=true) 保留中間程式碼
就會發現 Flex Compiler 笨笨的加上 2 * 2 = 4 次 Binding
真的是『Event 四起』 (雙關語...有點冷...呵...)
這樣實在不是很有效率啊
希望正式版 Flex SDK 會聰明一點

另外還發現了雙向資料繫結
根本無法對值作運算,否則 Compiler 會出現錯誤訊息

Error 1050: 無法指定給非參考值。

這也挺合理的,因為做了運算,值就不一樣了
Two-Way Data Binding 馬上變成一種無窮迴圈跑不完!

萬一又想要在 3, 4, 5... 多個組件上同步資料
只要用了雙向資料繫結 (Two-Way Data Binding)
不管再怎樣小心,一定會出現多餘 Binding Event
還不如用回舊的單向資料繫結,加上獨立的 Model 設計

總體來看,雙向資料繫結似乎只是省開發人員一行程式碼
但是有可能會產生多餘的 Event 甚至無窮迴圈
感覺上好像不是那麼有用~

相關連結:
Flex 4 Gumbo MXML 命名空間的問題
Flex 技巧 - 將資料綁定封裝起來
Flex - 純手工設定 DataBinding 的方式
Flex 技巧 - BindingManager 使用方式
Flex 技巧 - 觀察 Data Binding 資料變化
Flex Tip - 在 Data Binding 內使用 [...] 運算子
Flex 2 Bindable Metadata Tag 背後實際作用
Flex 2.0 - 以 ActionScript 3.0 動態設置 Data Binding

Read more...

2009年4月23日星期四

Flex DataGridHeader Styles Bug   [+/-]

Ticore's Blog

最近在開發能夠切換 Theme 的 Flex App.
大部分的外觀元素都能夠抽象化,放置到 Style CSS 內作動態切換
可是作到 DataGrid Header Background Skin 時,卻遇上了問題
以下是精簡後的 Bug Demo 程式

Flex DataGrid Header Style Bug Demo 程式碼:

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*"
  fontSize="11" paddingLeft="5" paddingRight="5" paddingTop="5" paddingBottom="5"
  backgroundColor="#FFFFFF">
 <mx:Style>
  DataGrid.MyStyle1 {
   headerColors: #FFFFFF, #8080FF;
  }
  DataGrid.MyStyle2 {
   headerBackgroundSkin: ClassReference("headerBgSkin");
  }
 </mx:Style>
 
 <mx:Component className="headerBgSkin">
  <mx:Container backgroundColor="#FF8080" />
 </mx:Component>
 
 <mx:HBox width="100%">
  <mx:Button label="Switch Style 1" click="dg.styleName='MyStyle1'" />
  <mx:Button label="Switch Style 2" click="dg.styleName='MyStyle2'" />
 </mx:HBox>
 
 <mx:XMLList id="employees">
  <employee>
   <name>Christina Coenraets</name><phone>555-219-2270</phone>
   <email>ccoenraets@fictitious.com</email>
  </employee>
  <employee>
   <name>Joanne Wall</name><phone>555-219-2012</phone>
   <email>jwall@fictitious.com</email>
  </employee>
  <employee>
   <name>Maurice Smith</name><phone>555-219-2012</phone>
   <email>maurice@fictitious.com</email>
  </employee>
  <employee>
   <name>Mary Jones</name><phone>555-219-2000</phone>
   <email>mjones@fictitious.com</email>
  </employee>
 </mx:XMLList>

 <mx:Panel title="DataGrid Header Change Style Bug" height="100%" width="100%"
   paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
  <mx:DataGrid id="dg" width="100%" height="100%" rowCount="5"
     dataProvider="{employees}" >
   <mx:columns>
    <mx:DataGridColumn dataField="name" headerText="Name"/>
    <mx:DataGridColumn dataField="phone" headerText="Phone"/>
    <mx:DataGridColumn dataField="email" headerText="Email"/>
   </mx:columns>
  </mx:DataGrid>
  <mx:ControlBar>
   <mx:Text width="100%" textAlign="right">
    <mx:htmlText>
     <![CDATA[<a target="_blank" href="http://ticore.blogspot.com/">]]>
     <![CDATA[Ticore's Blog - http://ticore.blogspot.com/</a>]]>
    </mx:htmlText>
   </mx:Text>
  </mx:ControlBar>
 </mx:Panel>
</mx:Application>

Flex DataGrid Header Style Bug 線上範例:

DataGrid Header 背景色有兩種設定方式
一種是用 Header Colors 指定兩個漸層色
另一種是 Header Background Skin 指定背景圖
實際測試就會發現,根本無法動態切到 Header Background Skin

修復的方式其實不難
只要覆寫 DataGrid.styleChanged 方法
通知 header.styleChanged 就好了

package {
 import mx.controls.DataGrid;

 public class MyDataGrid extends DataGrid {
  public function MyDataGrid() {
   super();
  }
  override public function styleChanged(styleProp:String):void {
   if (header) {
    header.styleChanged("headerBackgroundSkin");
    header.styleChanged("headerSeparatorSkin");
   }
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

Flex DataGrid Header Style Fix 線上範例:

Flex SDK 版本:3.1、3.2、3.3

PS. 上面的 Bug Demo 程式除了展示 Bug 以外
眼尖的人或許會發現到,我直接在同一支 MXML 內宣告了 Container Component
並且指定了背景色,指定給 CSS Style 使用
主要是為了省事,不過這樣的技巧還挺方便的 Read more...

Flex AdvancedDataGrid 技巧 - 移除浮水印   [+/-]

Ticore's Blog

Flex AdvancedDataGrid 雖然有提供完整的試用功能
不過編譯完成的 Application 會加上浮水印

Flex Data Visualization Trial

以上的浮水印其實是以 AS3 動態加上的
既然是 AS,那事情就簡單了
只要在 Flex Project 內自行加上以下 Class

package mx.controls.advancedDataGridClasses {
 public class DMVLicenseHandler {
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

然後在 MXML 內明確引用該 Class,或是用 Metadata Tag 強迫編譯
這樣就可以去除浮水印了~!

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
        <![CDATA[
            [Frame(extraClass="mx.controls.advancedDataGridClasses.DMVLicenseHandler")]
            
            import mx.collections.ArrayCollection;
            
            [Bindable]
            private var dpFlat:ArrayCollection = new ArrayCollection([
              {Region:"Southwest", Territory:"Arizona", 
                  Territory_Rep:"Barbara Jennings", Actual:38865, Estimate:40000}, 
              {Region:"Southwest", Territory:"Arizona", 
                  Territory_Rep:"Dana Binn", Actual:29885, Estimate:30000},  
              {Region:"Southwest", Territory:"Central California", 
                  Territory_Rep:"Joe Smith", Actual:29134, Estimate:30000},  
              {Region:"Southwest", Territory:"Nevada", 
                  Territory_Rep:"Bethany Pittman", Actual:52888, Estimate:45000},  
              {Region:"Southwest", Territory:"Northern California", 
                  Territory_Rep:"Lauren Ipsum", Actual:38805, Estimate:40000}, 
              {Region:"Southwest", Territory:"Northern California", 
                  Territory_Rep:"T.R. Smith", Actual:55498, Estimate:40000},  
              {Region:"Southwest", Territory:"Southern California", 
                  Territory_Rep:"Alice Treu", Actual:44985, Estimate:45000}, 
              {Region:"Southwest", Territory:"Southern California", 
                  Territory_Rep:"Jane Grove", Actual:44913, Estimate:45000}
            ]);
        ]]>
    </mx:Script>

    <mx:Panel title="AdvancedDataGrid Control Example"
         width="100%" height="100%" layout="horizontal"
         paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">

        <mx:AdvancedDataGrid id="myADG" width="100%" height="100%" initialize="gc.refresh();">        
            <mx:dataProvider>
                <mx:GroupingCollection id="gc" source="{dpFlat}">
                    <mx:grouping>
                        <mx:Grouping>
                            <mx:GroupingField name="Region"/>
                            <mx:GroupingField name="Territory"/>
                        </mx:Grouping>
                    </mx:grouping>
                </mx:GroupingCollection>
            </mx:dataProvider>        
            
            <mx:columns>
                <mx:AdvancedDataGridColumn dataField="Region"/>
                <mx:AdvancedDataGridColumn dataField="Territory"/>
                <mx:AdvancedDataGridColumn dataField="Territory_Rep"
                   headerText="Territory Rep"/>
                <mx:AdvancedDataGridColumn dataField="Actual"/>
                <mx:AdvancedDataGridColumn dataField="Estimate"/>
            </mx:columns>
       </mx:AdvancedDataGrid>
    </mx:Panel>
</mx:Application>

相關連結:
Flex Chart 技巧 - 移除浮水印

Read more...

2009年4月20日星期一

Flex 3.3 線上文件下載   [+/-]

Ticore's Blog

最近 Adobe 將線上文件註解功能改為 Ajax 方式
由另一個 domain 提供 comments 服務
與文件本身解耦合了~

所以這次收集線上文件時,特別去修改 Javascript
將 Live Comment 功能保留下來
能夠在本地端快速的翻閱文件
又能夠看到最新的 Comments

本次文件主要包含兩個部份

下載網址:
Flex_3.3_LiveDocs_20090420.part1.rar
Flex_3.3_LiveDocs_20090420.part2.rar
Flex_3.3_LiveDocs_20090420.part3.rar

Read more...

2009年4月18日星期六

AIR Javascript Alert Issue   [+/-]

Ticore's Blog

測試 Adobe AIR 時,發現 Javascript 產生的 Alert 視窗會有問題
使用以下的測試程式打包為 AIR App 進行測試

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>AIR Javascript Alert Issue</title>
</head>
<body>
<script type="text/javascript">
function doAlert() {
 var msg = "AIR Javascript Alert\n";
 var app = runtime.flash.desktop.NativeApplication.nativeApplication;
 msg += "runtime version : " + app.runtimeVersion;
 window.alert(msg);
}
// Ticore's Blog - http://ticore.blogspot.com/
</script>
<input type="Button" value="Button" onclick="doAlert();" />
</body>
</html>

執行之後,按下 Button 就會跳出一個 Alert 對話方塊

可以看到 Alert 視窗居然會出現在 windows 工作列上
一般正常的 Alert 應該是不會出現在工作列上的

更扯的是,在工作列上兩個 AIR 項目來回點
居然可以把 Alert 視窗擠到背景去了

AIR App 主視窗已經可以被切到最上層了
此時去點 AIR App 主視窗的 Close Button
由於主程序已經被暫停,無法正常關閉
windows 就跳出來終止程序的警告~

這個問題只有在 windows 上遇到
Linux 上居然正常,還真少見

以上的 Bug 至少會發生在以下版本的 AIR runtime:
Adobe AIR 1.5.1.8210 win

Read more...

2009年4月17日星期五

AS3 SimpleButton 型別檢查漏洞   [+/-]

Ticore's Blog

另一個與 AS3 HTML 文字欄位的型別檢查漏洞 類似的問題
AS3 SimpleButton 也有型別檢查的漏洞
SimpleButton 一樣不屬於 DisplayObjectContainer
但是卻可以藉由指定 upState、overState、downState 屬性
將一個 Sprite 放在 SimpleButton 內
然後可以再透過 Sprite.parent 屬性拿到 SimpleButton~~

package {
 import flash.display.*;
 
 [SWF(width=300, height = 200, backgroundColor = "#FFFFFF")]
 public class main extends MovieClip {
  
  public function main() {
   
   var btn1:SimpleButton = new SimpleButton();
   btn1.upState = new Sprite();
   
   var btn2:DisplayObjectContainer = btn1.upState.parent;
   trace(btn2); // [object SimpleButton]
   trace(btn2 is DisplayObjectContainer) // false
   trace(btn2 as DisplayObjectContainer) // null
   with({}) {
    trace(btn1 == btn2); // true
    trace(btn1 === btn2); // true
   }
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

相關連結:
AS3 HTML 文字欄位的型別檢查漏洞

Read more...

2009年4月16日星期四

Flash Telnet Tool   [+/-]

Ticore's Blog

昨天發現一個超好用的小工具 flashterm_
簡單說,它就是一個 Flash AS3 做出來的 Telnet Client
可以用來連上 BBS..
最主要還是依賴 ActionScript 3.0 ByteArray 與 Socket 連線功能
這樣的工具才能誕生

在網頁上就能連上 BBS,真的太酷了!

甚至可以用來連上 Linux Telnet Server 作為遠端 Console 使用
純粹只是測試,這是不建議的作法喔!

Read more...

2009年4月14日星期二

Flash or HTML/Ajax ?   [+/-]

Ticore's Blog

看到 Albert 的這篇文章 Flash 為什麼被人嫌棄
標題是有點危言聳聽了
個人卻非常同意 Marc 的意見
>這是策略問題, html/full flash site各有長處.

其實策略性、選擇性的問題都還是很其次的
最大問題是 HTML/Ajax 死氣沉沉,欠缺生命力!
為什麼會這樣說? 仔細想一想就知道
Ajax 其實很多年前就已經支援的舊技術
只是這幾年觀念革新才提出來的新定義名詞

受限於各家瀏覽器支援度分歧
造成 HTML/Ajax 進步緩慢
即使某一家瀏覽器增加新功能
也沒有網站敢去使用

結果只能在 framework 上做文章
算一算 Ajax framework 至少有上百種吧~
選擇太多,功能太少
這樣只是徒增開發人員的困擾

更血淋淋更精確的比喻應該是這樣
HTML/Ajax 核心功能死氣沉沉,欠缺生命力!
各種 Browser 與 Ajax framework 卻像惡性腫瘤一樣增生
不斷的吃掉 RD 的時間精力
這擺明就是癌末病患嘛!
要救活它也不是不可能
假如有那麼一天的話,大道之行天下為公之日恐怕也不遠了~

要它掛掉也不太容易,畢竟它是必需品
只是照這樣發展下去,經過多年以後
HTML/Ajax 也很難有什麼進步的空間
屆時恐怕變成一種『傳統產業』!

反觀 Flash 技術,很少有跨平台、跨瀏覽器的問題
這幾年新版本推出,都能在幾個月就達到 80% 普及率
而且普及速度越來越快~
當然新功能也是越來越多 (除非不愛學習新東西啦)
生命力真的非常旺盛

所以我自己的學習態度是
對於 Flash Player 感興趣新功能,馬上就去看去學
真的不用擔心以後用不到
可是 HTML/Ajax framework~~
實在太多了,學了可能也不一定用上
等它局勢穩定下來或是工作上要用到再學也不遲

相關連結:
CSS3 SVG Demo Page
用 Google 預測某項產品的死亡?

Read more...

2009年4月9日星期四

ViewStack selectedIndex, selectedChild 屬性初始化的 Bug   [+/-]

Ticore's Blog

Flex 內的 ViewStack 組件有一個很嚴重的 Bug
連帶的影響到繼承 ViewStack 的 TabNavigator
那就是直接在 Tag 上指定 selectedIndex, selectedChild 會失敗

而且這個臭蟲似乎存在很久了
從 Flex 2.01 到 3.3 都會發生

直接在 TabNavigator attribute 指定 selectedIndex 的 Bug

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
  layout="vertical" verticalAlign="middle" backgroundColor="#FFFFFF" fontSize="12">
 <mx:TabNavigator width="320" height="100" backgroundColor="#FFFFFF"
    borderStyle="inset" selectedIndex="2">
  <mx:Canvas label="Tab 0">
   <mx:Label text="Canvas 00" />
  </mx:Canvas>
  <mx:Canvas label="Tab 1">
   <mx:Label text="Canvas 01" />
  </mx:Canvas>
  <mx:Canvas label="Tab 2">
   <mx:Label text="Canvas 02" />
  </mx:Canvas>
  <mx:Canvas label="Tab 3">
   <mx:Label text="Canvas 03" />
  </mx:Canvas>
  <mx:Canvas label="Tab 4">
   <mx:Label text="Canvas 04" />
  </mx:Canvas>
 </mx:TabNavigator>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

執行結果如下圖所示,selectedIndex 根本沒有效果

接下來再看 selectedChild 的 Bug

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
  layout="vertical" verticalAlign="middle" backgroundColor="#FFFFFF" fontSize="12">
 <mx:TabNavigator width="320" height="100" backgroundColor="#FFFFFF"
    borderStyle="inset" selectedChild="{tab2}">
  <mx:Canvas label="Tab 0" id="tab0">
   <mx:Label text="Canvas 0" />
  </mx:Canvas>
  <mx:Canvas label="Tab 1" id="tab1">
   <mx:Label text="Canvas 1" />
  </mx:Canvas>
  <mx:Canvas label="Tab 2" id="tab2">
   <mx:Label text="Canvas 2" />
  </mx:Canvas>
  <mx:Canvas label="Tab 3" id="tab3">
   <mx:Label text="Canvas 3" />
  </mx:Canvas>
  <mx:Canvas label="Tab 4" id="tab4">
   <mx:Label text="Canvas 4" />
  </mx:Canvas>
 </mx:TabNavigator>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

這個執行結果更慘,出現以下 Error Message

ArgumentError: Error #2025: 提供的 DisplayObject 必須是呼叫者的子系。
 at flash.display::DisplayObjectContainer/getChildIndex()
 at mx.core::Container/getChildIndex()
 at mx.containers::ViewStack/set selectedChild()
 at MethodInfo-652()
 at Function/http://adobe.com/AS3/2006/builtin::call()
 at mx.binding::Binding/innerExecute()
 at Function/http://adobe.com/AS3/2006/builtin::apply()
 at mx.binding::Binding/wrapFunctionCall()
 at mx.binding::Binding/execute()
 at mx.binding::Binding/watcherFired()
 at mx.binding::Watcher/notifyListeners()
 at mx.binding::PropertyWatcher/eventHandler()
 at flash.events::EventDispatcher/dispatchEventFunction()
 at flash.events::EventDispatcher/dispatchEvent()
 at mx.core::UIComponent/dispatchEvent()
 at main/set tab2()
 at mx.core::UIComponent/createReferenceOnParentDocument()
 at mx.core::Container/createComponentFromDescriptor()
 at mx.containers::ViewStack/createComponentsFromDescriptors()
 at mx.core::Container/createChildren()
 at mx.containers::TabNavigator/createChildren()
 at mx.core::UIComponent/initialize()
 at mx.core::Container/initialize()
 at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
 at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
 at mx.core::Container/addChildAt()
 at mx.core::Container/addChild()
 at mx.core::Container/createComponentFromDescriptor()
 at mx.core::Container/createComponentsFromDescriptors()
 at mx.core::Container/createChildren()
 at mx.core::UIComponent/initialize()
 at mx.core::Container/initialize()
 at mx.core::Application/initialize()
 at main/initialize()
 at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
 at mx.managers::SystemManager/initializeTopLevelWindow()
 at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::docFrameHandler()
 at mx.managers::SystemManager/docFrameListener()

只要去追蹤原始碼,就會發現這問題是由於 ViewStack 與子物件建立順序有關
當 ViewStack 開始建構初始化 selectedIndex 數值時
內部的子物件根本都還沒建立,結果導致 selectedIndex 賦值無效~

那要怎樣改善呢? 其實想辦法把 selectedIndex 賦值動作往後延就好
最簡單的方式就是直接用 creationComplete 事件了

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
  layout="vertical" verticalAlign="middle" backgroundColor="#FFFFFF" fontSize="12">
 <mx:TabNavigator width="320" height="100" backgroundColor="#FFFFFF"
    borderStyle="inset" creationComplete="event.target.selectedIndex = 2;">
  <mx:Canvas label="Tab 0">
   <mx:Label text="Canvas 00" />
  </mx:Canvas>
  <mx:Canvas label="Tab 1">
   <mx:Label text="Canvas 01" />
  </mx:Canvas>
  <mx:Canvas label="Tab 2">
   <mx:Label text="Canvas 02" />
  </mx:Canvas>
  <mx:Canvas label="Tab 3">
   <mx:Label text="Canvas 03" />
  </mx:Canvas>
  <mx:Canvas label="Tab 4">
   <mx:Label text="Canvas 04" />
  </mx:Canvas>
 </mx:TabNavigator>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

這樣就可以成功初始化 selectedIndex, selectedChild 屬性了

已知該 Bug 至少會在以下版本 Flex SDK 發生
Flex SDK version:2.01, 3.1, 3.2, 3.3

相關的 Bug Report:
http://bugs.adobe.com/jira/browse/SDK-15101
http://bugs.adobe.com/jira/browse/SDK-14157
http://bugs.adobe.com/jira/browse/SDK-15974

Read more...