如果您还不熟悉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

 

 

 

 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐