💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、豆包、星火、月之暗面及文生图、文生视频 广告
[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值中插入&#13;代码 * 在ActionScript 用来初始化MXML 属性的String变量中插入“/n” 要使用&\#13;代码插入换行符,可以在MXML的属性值中包含该代码,如下所示: `<mx:TextArea width="100%" text="Display&#13;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}"/> ~~~ 效果图: ![](https://box.kancloud.cn/5a2a40a1a4d1adda316debc4d26bd73b_814x106.png) #### **在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指定其中的内容 ![](https://box.kancloud.cn/da9f4496745d81adee17030740c038f4_415x206.png) * * * * * ### 数据绑定 将一个任意对象上所做的任何更新和修改,自动反映到另一个对象上 * 直接绑定 ~~~ <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> ~~~ 栗子: ![](https://box.kancloud.cn/6f240fc430cf0faa01403e8d6bbb6f18_587x242.png) ### 布局 ~~~ <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(绝对布局)-- 手动定位坐标 ![](https://box.kancloud.cn/ad23f4884a18c294f27fb1e2a37ffe82_519x173.png) * HorizontalLayout(水平布局) ![](https://box.kancloud.cn/c4ff75f7d92ee157bde7dcd29b1770eb_789x148.png) * VerticalLayout(垂直布局) ![](https://box.kancloud.cn/78f908823e6322a5e105750148c5fe98_326x126.png) * TileLayout(网格布局) ![](https://box.kancloud.cn/8f5629a9b440c1e944dcb76828f3adeb_773x113.png) ### 常用组件 * * * * * # **Hello Again...** * * * * * ### **视图状态(状态机)** ##### **什么是状态** 看起来是两个不同的页面,其实这是同一个自定义的组件。 它具有两种状态,Login状态和Register状态,状态不同,呈现出来的东西就不同。 ![](https://box.kancloud.cn/ab409b7c44a1bf8f990f7bdb4afac5cb_331x165.png) ![](https://box.kancloud.cn/a2010f8c01977a4608d9410fec728039_330x207.png) ##### **定义状态(写在<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"/> ~~~ 效果: ![](https://box.kancloud.cn/6f769fc45519b6d143152bc16ae0ba5f_318x197.png)![](https://box.kancloud.cn/8bea85757ac14390e8c621685ff8fd34_337x255.png) ##### **在非列表类组件中拖放** 其一:需要将拖放的组件的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; //设定组件的位置 } ~~~ 效果: ![](https://box.kancloud.cn/116f49031e306acddb02192d3fafbc36_316x396.png)![](https://box.kancloud.cn/c94b267bdcfd17c882d3b67eaf8c9d2d_339x408.png) ~~~ ~~~ ### **动画** ##### **简单示范** 使用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组件,只简单的显示一行文本) ![](https://box.kancloud.cn/f27d509de1eba5b16b503e4fa89843b3_113x169.png) ##### **自定义项渲染器** 通过自定义,用户可以添加图片,按钮,选项框等等组件,来实现多样的功能。 通过传入复杂的数据,还可以完成复杂的数据显示。 下面就是一个自定义的例子:(包含原有的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> ~~~ ![](https://box.kancloud.cn/39e5cd632c093927430c3ca0141e31e8_312x299.png)