天天看點

Flex 4與自定義布局

如果您還不熟悉Flex 4的最新功能,那麼有些内容肯定是您想要了解的。Flex 4/Spark元件架構的新功能之一是可以定制一個容器的布局而不必改變容器本身。您需要做的就是定義一個自定義布局。

Flex 4/Spark架構中的容器并不控制它們自己的布局。相反,每種容器具有一個布局屬性,用于确定如何在螢幕上設定子元素的布局。可以使用一個單獨的Group容器,并賦予其一個垂直布局、水準布局或平鋪布局,這取決于您将如何建立它。代碼很簡單,如下所示:

<s:layout>

         <s:VerticalLayout/>

</s:layout>

不過真正的好處在于您不必局限于架構中定義的預設布局。您可以輕松定制BaseLayout類來實作自己定制的布局邏輯。下面是一個簡單的例子,顯示了如何實作一個在原點周圍順時針放置元件的布局。隻要單擊左下方的按鈕就可以将更多按鈕添加到布局。

下面是主應用程式檔案的代碼。可以看到,代碼相當簡單。這就是一個DataGroup,有點像一個重複程式(repeater),它包含一組按鈕。這個容器的布局基于一個自定義布局實作。在creationComplete中,填充DataGroup的資料提供程式,進而在布局中建立按鈕執行個體。

<?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/halo"

  xmlns:local="*">

  <s:creationComplete>

    <![CDATA[

      for ( var x:int = 0; x < 10; x++ ){

         dataSource.addItem( dataSource.length );

       }

    ]]>

  </s:creationComplete>

  <fx:Declarations>

    <mx:ArrayCollection id="dataSource" />

  </fx:Declarations>

  <s:DataGroup

    width="100%" height="100%"

    dataProvider="{ dataSource }"

    itemRenderer="SimpleItemRenderer">

    <s:layout>

      <local:CircularLayout />

    </s:layout>

  </s:DataGroup>

  <mx:Button

    left="5" bottom="5"

    label="Click to Add a Button"

    click="dataSource.addItem( dataSource.length )" />

</s:Application>

可以看到,DataGroup執行個體的布局受CircularLayout類控制(該類如下所示)。該類隻是循環周遊datagroup對象的子對象并将它們按順時針方向放在一個圓圈内。我檢視了VerticalLayout類的源代碼,弄清了它的工作方式,并由此開始建構自己的布局實作。

package

{

   import mx.core.ILayoutElement;

   import spark.layouts.supportClasses.LayoutBase;

   public class CircularLayout extends LayoutBase

   {

      override public function updateDisplayList(w:Number, h:Number):void

      {

           super.updateDisplayList(w, h);

           if (!target)

             return;

           var layoutElement:ILayoutElement;

           var count:uint = target.numElements;

           var angle : Number = 360/count;

           var radius : Number = Math.min( target.width/2, target.height/2 ) - 25;

           var w2 : Number = target.width/2;

           var h2 : Number = target.height/2;

           for (var i:int = 0; i < count; i++)

           {

              layoutElement = target.getElementAt(i);

              if (!layoutElement || !layoutElement.includeInLayout)

                continue;

              var radAngle : Number = (angle * i) * (Math.PI / 180) ;

              var _x : Number = Math.sin( radAngle );

              var _y : Number = - Math.cos( radAngle );

              layoutElement.setLayoutBoundsPosition( w2 + (_x * radius) - 25, h2 + (_y * radius) - 10 );

            }

       }

    }

}

這個示例中使用的項目渲染器實際上是最基本的。它是一個隻包含一個按鈕的ItemRenderer執行個體,簡單明了并且很容易看到産生的結果。

<s:ItemRenderer

  xmlns:fx="http://ns.adobe.com/mxml/2009"

  xmlns:s="library://ns.adobe.com/flex/spark"

  xmlns:mx="library://ns.adobe.com/flex/halo">

  <s:states>

    <s:State name="normal"/>

    <s:State name="hovered"/>

  </s:states>

  <s:layout>

    <s:BasicLayout/>

  </s:layout>

  <s:Button label="{ data }" baseColor.hovered="#FF0000" />

</s:ItemRenderer>

這個例子使用從以下網址得到的4.0.0.7052每日建構(nighly build)版本進行建立:

http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4

英文原文:http://www.insideria.com/2009/05/flex-4-custom-layouts.html

繼續閱讀