Flex4 SkinnableContainer,BorderContainer隐藏子内容

SkinnableContainer及其子类BorderContainer等在添加了子内容后,

即使子内容宽高超过了容器本身的宽高,子内容也会被正常显示出来,

SkinnableContainer是无法裁剪子内容的,而且也没有默认属性可以设置

但如果想实现容器裁剪子内容,可以用以下方法实现

<s: SkinnableContainer id=”myBC” creationComplete=”myBC.contentGroup.clipAndEnableScrolling = true”>

即:在容器创建完成后设置它的属性contentGroup的clipAndEnableScrolling为true

原理:

BorderContainer继承自SkinnableContainer,这两个组件都不是自身添加显示对象的,而是使用contentGroup作为子内容的容器,

而contentGroup实际上是一个Group对象 Group本身有一个属性:clipAndEnableScrolling,当它为true时,就会裁剪内容,默认是false

Flex User Group文档–AIR介绍

一个很有用的PPT,用于向不了解这技术的人介绍
点击下载

FlashFlex发布可访问本地的SWF

无论是Flex还是Flash编译后的SWF都只可方位网络或者只可访问本地数据,不可以同时访问二者,
Flex默认是只可访问网络,要把Flex编译后的SWF设为只可访问本地数据模式,要在Flex项目的编译参数中增加:-use-network=false
在Flash IDE中,设置方式:在菜单工具栏中选择File(文件)->Publish Settings(发布设置),在弹出窗口中选择Flash标签,在Local playback中选择需要的访问模式

Flex4动态加载和切换CSS

Flex4中动态加载CSS文件的方式已经和Flex3有了一定的区别

主要步骤如下:

1.编写不同的CSS文件

见后文

2.将CSS文件编译成SWF文件

在FlashBuilder中右键CSS文件,选择Compile CSS to SWF,
浏览完整全文 »

漫步PureMVC(一) 极简入门

PureMVC官方网站http://puremvc.org/有详细的多语言帮助文档(包括中文)和demo,
但即使是最简单的demo,也要建立N多类,很多朋友都抱怨PureMVC上手机要需要建立太多类,比较难入门
因此我做了下面这个Demo,只用了3个类,来说明PureMVC中Facade和View/Mediator的用法,
以及如何发送和响应notification
并且在以后的blog中,我会在这个demo基础上,逐步添加新的类和功能,逐步深入讲解PureMVC
Demo中有三个朋友列表,分别是全部朋友列表与组A/组B,添加/删除朋友时会同时添加/删除全部列表和指定组的列表
仅包含三个类:
FrinedList.mxml : 主程序,实例化多个MyList.mxml作为朋友列表,向Facade注册mediator,发送添加朋友的通知
views/MyList.mxml : 朋友列表的可视化组件,发送删除朋友的通知
views/MyListMediator.as : MyList.mxml的中介器,响应各种通知,控制MyList.mxml

主程序:FriendList.mxml

<?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/mx" minWidth="955" minHeight="600"
			   xmlns:views="views.*"
			    creationComplete="application1_creationCompleteHandler(event)">

	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;

			import org.puremvc.as3.multicore.interfaces.IFacade;
			import org.puremvc.as3.multicore.patterns.facade.Facade;

			import views.MyListMediator;

			protected var facade:IFacade = Facade.getInstance('');//获取Facade的单例

			protected function application1_creationCompleteHandler(event:FlexEvent):void
			{
				cbTypeId.textInput.editable = false
				//
				facade.registerMediator(new MyListMediator('all',this.list0));
				facade.registerMediator(new MyListMediator('group1',this.list1));
				facade.registerMediator(new MyListMediator('group2',this.list2));
				//添加几个个测试数据
				this.addNewFriend('Sven',1);
				this.addNewFriend('Lina',2);
				this.addNewFriend('Viper',1);
				this.addNewFriend('Chen',2);
				this.addNewFriend('Zeus ',4);//添加一个特殊typeId的组,测试例外数据的处理
			}

			protected function btnAdd_clickHandler($event:MouseEvent):void{
				this.addNewFriend(this.textName.text,this.cbTypeId.selectedItem.typeId);
				this.textName.text='';//清空名称输入栏,以免连续点击
			}

			protected function addNewFriend($name:String,$typeId:int):void{
				var $friend:Object = new Object();//创建一个新朋友的数据对象
				$friend.name = $name;//设置名称
				$friend.typeId = $typeId;//设置typeId
				facade.sendNotification('add',$friend);//发送通知
			}
		]]>
	</fx:Script>

	<s:HGroup>
		<s:Label text="Name:"/>
		<s:TextInput id="textName"/>
		<s:ComboBox id="cbTypeId" labelField="label" selectedIndex="0">
			<s:dataProvider>
				<s:ArrayCollection>
					<fx:Array>
						<fx:Object label='组A' typeId='1'/>
						<fx:Object label='组B' typeId='2'/>
						<fx:Object label='不分配组' typeId='0'/>
					</fx:Array>
				</s:ArrayCollection>
			</s:dataProvider>
		</s:ComboBox>
		<s:Button enabled="{this.textName.text!=''}" id="btnAdd" label="添加新Friend" click="btnAdd_clickHandler(event)"/>
	</s:HGroup>
	<views:MyList id="list0" x="10" title="全部好友" typeId="0" width="180" top="39" height="486">
	</views:MyList>
	<views:MyList id="list1" x="198" title="组A" typeId="1" width="180" top="39" height="213">
	</views:MyList>
	<views:MyList id="list2" x="198" title="组B" typeId="2" width="180" top="305" height="220">
	</views:MyList>
</s:Application>

朋友列表组件:views/MyList.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
		 xmlns:s="library://ns.adobe.com/flex/spark"
		 xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300"
		  >

	<fx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;

			import org.puremvc.as3.multicore.patterns.facade.Facade;

			[Bindable]
			public var title:String = '';

			public var typeId:int = 0;

			[Bindable]
			public var dataAC:ArrayCollection = new ArrayCollection();

			protected function btnDel_clickHandler(event:MouseEvent):void
			{
				if(this.list.selectedItem){
					Facade.getInstance('').sendNotification('delete',this.list.selectedItem);
				}
			}
		]]>
	</fx:Script>
	<s:Label text="{title}"/>
	<s:List id="list" dataProvider="{dataAC}" top="24" bottom="24" width="100%" labelField="name"/>
	<s:Button id="btnDel" enabled="{this.list.selectedItem}" label="删除所选" click="btnDel_clickHandler(event)" bottom="0" />
</s:Group>

中介器:MyListMediator.as

package views
{
	import org.puremvc.as3.multicore.interfaces.INotification;
	import org.puremvc.as3.multicore.patterns.mediator.Mediator;

	public class MyListMediator extends Mediator
	{
		public function MyListMediator(mediatorName:String=null, viewComponent:Object=null)
		{
			super(mediatorName, viewComponent);
		}
		private function get view():MyList{
			return this.viewComponent as MyList;
		}
		//可以接受的通知name
		override public function listNotificationInterests():Array{
			return ['delete','add'];
		}
		//响应通知
		override public function handleNotification(notification:INotification):void{
			var $friend:Object = notification.getBody();//获取通知的内容
			if(this.view.typeId==0 || this.view.typeId==$friend.typeId){
				//所持有的MyList如果是全部朋友的列表或指定typeId的列表,则执行以下操作,否则不执行
				switch(notification.getName()){//区分名称
					case 'delete':
						var $index:int = this.view.dataAC.getItemIndex($friend);
						this.view.dataAC.removeItemAt($index);//告知data删除指定friend object
						break;
					case 'add':
						this.view.dataAC.addItem($friend);//添加frined object
						break;
				}
			}
		}
	}
}

源文件下载 PureMvcDemoFriendList20100511.zip

Flex中的Base64加解密

Flex sdk3就内置了Base64的加/解密工具类
分别是
mx.utils.Base64Encoder
mx.utils.Base64Decoder

Base64Encoder用法如下:
var $orgin:String = this.textOrigi.text;//获取原始字符串
var $base64:Base64Encoder = new Base64Encoder();
$base64.insertNewLines = false;//该值等于true时,输出的结果会自动换行,默认为true,
$base64.encodeUTFBytes($orgin);//这里注意,如果想加密中文就不要使用$base64.encode();
var $result:String = $base64.toString();//输出结果
Base64Decoder用法如下:
				var $origi:String = this.textEncodeResult.text;//获取原始字符串
				var $base64:Base64Decoder = new Base64Decoder();
				$base64.decode($origi);
				var $result:String = $base64.toByteArray().toString();//输出结果,decode类只能输出ByteArray类型的数据,因此要转换成string
完成代码:
<?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/mx" minWidth="955" minHeight="600">

	<fx:Script>
		<![CDATA[
			import mx.utils.Base64Decoder;
			import mx.utils.Base64Encoder;
			protected function btnEncode_clickHandler(event:MouseEvent):void
			{
				var $orgin:String = this.textOrigi.text;//获取原始字符串
				var $base64:Base64Encoder = new Base64Encoder();
				$base64.insertNewLines = false;//该值等于true时,输出的结果会自动换行,默认为true,
				$base64.encodeUTFBytes($orgin);//这里注意,如果想加密中文就不要使用$base64.encode();
				var $result:String = $base64.toString();//输出结果
				this.textEncodeResult.text = $result
			}

			protected function btnDecode_clickHandler(event:MouseEvent):void
			{
				var $origi:String = this.textEncodeResult.text;//获取原始字符串
				var $base64:Base64Decoder = new Base64Decoder();
				$base64.decode($origi);
				var $result:String = $base64.toByteArray().toString();//输出结果,decode类只能输出ByteArray类型的数据,因此要转换成string
				this.textDecodeResult.text = $result
			}

		]]>
	</fx:Script>

	<mx:Form width="100%">
		<mx:FormItem label="原始字符串:" width="100%">
			<s:TextArea editable="true" id="textOrigi" width="100%" text="在这里输入原始字符串"/>
		</mx:FormItem>
		<mx:FormItem>
			<s:Button id="btnEncode" label="Encode Base64" enabled="{this.textOrigi.text!=''}" click="btnEncode_clickHandler(event)"/>
		</mx:FormItem>
		<mx:FormItem label="Encode 结果:" width="100%">
			<s:TextArea editable="false" id="textEncodeResult" width="100%"/>
		</mx:FormItem>
		<mx:FormItem>
			<s:Button id="btnDecode" enabled="{this.textEncodeResult.text!=''}" label="Decode Base64" click="btnDecode_clickHandler(event)"/>
		</mx:FormItem>
		<mx:FormItem label="Decode 结果:" width="100%">
			<s:TextArea editable="false" id="textDecodeResult" width="100%" text="点击Decode Base64按钮后,这里的结果应该和原始字符串相同"/>
		</mx:FormItem>
	</mx:Form>
</s:Application>

FlexBuilder中使用代码片断工具

1.1 工具介绍

使用代码片断工具,您可以存储内容(文档中重复出现的代码如public function …( ):void{   }等)以便快速重复使用。多种软件都含有此工具(例如Dreamweaver),flexbuilder中此工具包含在CFEclipse插件中。

1.2 安装与使用

安装步骤:

a.  帮助       安装新软件;

b.  使用(W)一栏中输入地址   http://www.cfeclipse.org/update

c.  输入网址后按Enter,程序连接服务器,窗口显示“暂挂中”,连接完毕后窗口会显示出可供安装的程序,选择CFEclipse CFML Editor   点 下一步

d.  点 完成  开始下载   出现安全警告提示软件未签名 点击确定  之后按提示重启flex builder

e.  打开工具窗口(Snip Tree View);

f.   编辑代码片断   新建片断

g.  按钮插入该片断(只适用于AS代码文件)

h.  片断中适用参量:$${    }   如图中代码

在插入该片断时会出现提示框,要求输入$${}标记的参数值name  如图

确定后整段代码被插入

Air/Flex动态加载module及其依赖的RSL

有关Flex和Air中如何使用RSL网上教程很多,google一下即可,这里不多做叙述了

而这次遇到的问题是这样的:

发布时只发布一个主程序(Web或者Air方式),而不发布所需要的module及其依赖的swc,只在运行时根据需要加载module及其依赖的swc

1.       建立一个实验用的module工程:

先准备一个module工程,普通的Flex Project(web)即可,主程序名无所谓,因为这个工程只是为了编译module对象用的

在Properties->Flex Build Path中引入所要依赖的swc,这个例子中使用了TweenLite.swc

注意AIR project的默认Link TypeMerge into code,改成RSL。如图:

新建一个包modules并新建一个module程序:MyModule1.mxml

到Properties->Flex Modules中修改该module的optimize属性为none,如下图

点击Edit按钮,弹出下图

选择Do not optimize(…)

在MyModule1.xml中使用TweenLite做一个简单的动画:

TweenLite.to(<strong>this</strong>.goed,4,{x:500});

编译工程,

此时MyModule1.mxml被编译生成为MyModule1.swf

TweenLite.swc会被编译成TweenLite.swf

复制到要被加载的目录下,我的是

http://127.0.0.1/testflex/TweenLite.swf

http://127.0.0.1/testflex/modules/MyModule1.swf

2.       建立主工程(Flex Web):

新建一个Flex Project(web),不要使用引入TweenLite.swc

新建一个用来控制加载TweenLite的类:

tasks/TaskLoadRSL.as

在这个类中,使用URLLoader将TweenLite.swc从http://127.0.0.1/testflex/TweenLite.swf上加载下来,主要代码如下:

var loader:Loader = new Loader();
var context:LoaderContext = new LoaderContext();
context.applicationDomain = ApplicationDomain.currentDomain;//必须有这一句,RSL必须和主程序在同一个域中
loader.load(new URLRequest(this.web),context);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,localLoadCompleteHandler);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,localLoadIoErrorHandler);

加载完TweenLite后不需要任何操作,直接开始加载module即可

使用IModuleInfo或ModuleLoader加载module都可以,详见源代码

3.       建立主工程 (AIR):

Air中比Flex要麻烦,因为发布时只发布主程序,所以运行时需要先检测本地是否有swc和

module

如果有就直接加载运行(同Web)

如果没有就从网站上下载到本地,然后再加载

主要代码如下:

从网络地址上加载:

var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, loadFromWebCompleteHandler);
loader.addEventListener(IOErrorEvent.IO_ERROR, loadFromWebErrorHandler);
loader.load(new URLRequest(web))

加载完,保存到本地:

var loader:URLLoader = URLLoader($e.target);
var data:ByteArray = ByteArray(loader.data);
var file:File = new File(File.applicationDirectory.resolvePath(this.local).nativePath);
trace('save file to' + file.nativePath);
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(data);
fileStream.close();
this.loadFromLocalFile();

本地加载过程同Flex Web

更多内容参加源代码:DynamicTestLoadModuleAndRSL

httpservice request传参数的几种方式

mxml代码中 httpservice 组件,连接一php计算器

<s:Button click="this.hs.send();"/>
<fx:Declarations>
	<s:HTTPService id="hs" url="http://127.0.0.1/cal.php" method="GET">
		<s:request xmlns="">
			<calculator>plus</calculator>
			<param1>10</param1>
			<param2>23</param2>
		</s:request>
		<s:fault>
			<![CDATA[
				trace("")
			]]>
		</s:fault>
		<s:result>
			<![CDATA[
				trace(event.result.result.equals)
			]]>
		</s:result>
	</s:HTTPService>
</fx:Declarations>

httpService组件,在as块中传入参数

var param:Object = {calculator:"minus",param1:"23",param2:"13"}
httpServ.send(param)

<mx:HTTPService id="httpServ">
	<mx:resultFormat>text</mx:resultFormat>
	<mx:url>http://127.0.0.1/cal.php</mx:url>
	<mx:fault>Alert.show(event.toString(), event.type);</mx:fault>
</mx:HTTPService>

as代码中,使用httpservice类

public var httpservice:mx.rpc.http.HTTPService = new mx.rpc.http.HTTPService();
public var param:Object={calculator:"minus",param1:"23",param2:"13"};
public function send_data():void{
	httpservice.url ="http://127.0.0.1/cal.php";
	httpservice.method = "POST";
	httpservice.addEventListener(ResultEvent.RESULT, resultHandler);
	httpservice.addEventListener(FaultEvent.FAULT, this.HttpErrorHandle);
	httpservice.send(param);
		}

as代码中使用urlloader

public function Temp()
		{
			var url:String = "http://127.0.0.1/cal.php"
			var urlVariables:URLVariables = new URLVariables();
			urlVariables.decode("calculator=plus&param1=10&param2=22");
			var request:URLRequest = new URLRequest(url);
			request.data = urlVariables;
			request.method = URLRequestMethod.POST

			var loader:URLLoader = new URLLoader()
			loader.dataFormat = URLLoaderDataFormat.TEXT
			loader.addEventListener(Event.COMPLETE, onComplete)
			loader.load(request);

		}
		public function onlistener(event:Event):void{
			var xml:XML = new XML(event.target.data)

			trace(xml..equals)
		}

偶遇FLEX 4中容器之间复制数据方法

偶遇书上容器之间的复制数据方法。通过拖拽功能实现不同容器间的数据复制,能优化交互功能。小试成功,令闻此方法可能小有用处,故将此方法发于此,方便大家讨论及指正。主要代码如下所示。

在.mxml中添加组件:

<s:HGroup>
<s:HGroup>
<s:Label text="可选专辑" fontSize="14"/>
<mx:DataGrid id="srcgrid" dragEnabled="true" fontSize="12">
<mx:columns>
<mx:DataGridColumn dataField="Artist" headerText="Singer"/>
<mx:DataGridColumn dataField="Album" headerText="Album"/>
<mx:DataGridColumn dataField="Price" headerText="Price"/>
</mx:columns>
</mx:DataGrid>
</s:HGroup>
<s:HGroup>
<s:Label text="已经选购的专辑" fontSize="14"/>
<mx:DataGrid id="destgrid" dropEnabled="true" fontSize="12" dragDrop="destgrid_dragDropHandler(event)">
<mx:columns>
<mx:DataGridColumn dataField="Artist1" headerText="Singer"/>
<mx:DataGridColumn dataField="Album1" headerText="Album"/>
<mx:DataGridColumn dataField="Price1" headerText="Price"/>
</mx:columns>
</mx:DataGrid>
</s:HGroup>
</s:HGroup>

fx:Script中的代码:

protected function application1_creationCompleteHandler(event:FlexEvent):void     //createcomplete函数,为datagrid赋值
{
srcgrid.dataProvider = new ArrayCollection([
{Artist:'English',Album:'Learn',Price:1},
{Artist:'Chinese',Album:'Try',Price:3},
]);
destgrid.dataProvider = new ArrayCollection();
// TODO Auto-generated method stub
}

protected function destgrid_dragDropHandler(event:DragEvent):void     //拖拽时调用的方法
{
if (event.dragSource.hasFormat("items"))
{
event.preventDefault();                         //取消默认行为

//获取拖放的目标对象
var droptarget:DataGrid = DataGrid(event.currentTarget);

//隐藏鼠标下方允许拖放的指示条

droptarget.hideDropFeedback(event);

//获取复制的数据集
var itemsArray:Array = event.dragSource.dataForFormat("items") as Array;

//复制数据
var tempItem:Object = {
Artist1:itemsArray[0].Artist,
Album1:itemsArray[0].Album,
Price1:itemsArray[0].Price
};

//获取拖放的目标对象的位置
var droploc:int = droptarget.calculateDropIndex(event);

IList(droptarget.dataProvider).addItemAt(tempItem,droploc);

}

}

运行效果如下: