自己做Flex换肤器

xiaohuli 2012-04-26

自己做Flex换肤器

1人收藏此文章,我要收藏

发表于1年前,已有748次阅读共0个评论

今天周末,昨晚看电影睡得很迟,早上直接起床吃中饭。本来和朋友约好一起吃饭的,可是老天下雨,上网打了几把魔兽,把把被虐。这下火大了,打开资料看,忽然看见自己以前做的Ext的换肤器,当时时根据EXT论坛上别人写的一些代码,把它整理了下,最后跑成功了。

最近我们在搞Flex,我就想我可以做个Flex换肤器啊。

OK,说干就干。首先把以前Ext那个看了下,大致知道需要很多个CSS,这些CSS用于皮肤切换,一个下拉列表框,供用户选择皮肤,最后用户选择后的信息保存到客户端cookies里面,程序启动加载cookies里面的东西,根据它来决定加载哪个CSS效果。

那就开始仿照吧。

要下拉列表框是吧?这个不难,咱用Flex做一个。如下:

[Bindable]

privatevarcssSource:Array=[

{label:'默认',data:''},

{label:'样式1',data:'BlueTan.css},

{label:'样式2',data:'Brauwny.css'},

{label:'样式3',data:'kingnarestyle.css},

{label:'样式4',data:'shadow.css'},

{label:'样式5',data:'SunNight.css'}

];

<mx:ComboBoxid="cssCB"dataProvider="{cssSource}"/>

OK第一步搞定。

页面需要加载CSS,那开始写吧,于是加入如下:

<mx:Stylesource="”/>

这里的source指定要加载的CSS路径。我一开始想我给这个对象一个id,然后我选择下拉列表里面那个值,让这个控件的source换成哪个值不就好了嘛。可是问题来了,我写个id,它就编译不了,原来这玩意不支持id属性,我晕死。

怎么办?怎么办?

对了,Flex不是有绑定变量的功能嘛,我定义个绑定变量,然后让这里的source绑定到它不就成了?

于是我写了如下代码:

[Bindable]

privatevarcssName:String;

<mx:Stylesource="{cssName}”/>

我晕,再次看见红叉叉,说明是不支持编译期间绑定。我晕,这个也不支持,那个也不支持,你个破Flex这么垃圾啊。

到此我已经没有头绪了,只好找来Flex3cookbook开始看第9章:皮肤和样式。

看着看着忽然眼前一亮,看到了对我有用的一句代码。

StyleManager.loadStyleDeclarations(cssName,true);//可以运行时动态加载css效果

有了这个就好办啊,页面加载完成我就调个函数,动态加载用户保存的CSS啊,在运行期间用户通过下拉列表框切换

了皮肤,我再用这个来动态加载啊。

思路对了,下面就要按照要求来实现了。原来这家伙不支持加载CSS,只加载swf文件,教程中说了要用

mxmlcmain.css

这样的命令来把CSS文件转换为swf文件。OK照着干,把用到的CSS文件转换,再修改代码。

修改后代码为:

[Bindable]

privatevarcssSource:Array=[

{label:'默认',data:''},

{label:'样式1',data:'BlueTan.swf'},

{label:'样式2',data:'Brauwny.swf'},

{label:'样式3',data:'kingnarestyle.swf'},

{label:'样式4',data:'shadow.swf'},

{label:'样式5',data:'SunNight.swf'}

];

下面的问题是得给下拉列表框一个位置和一个选择后的函数,于是又写了个函数:

<mx:ComboBoxid="cssCB"x="20"y="30"dataProvider="{cssSource}"close="closeHandler(event);"/>

privatefunctioncloseHandler(event:Event):void{

varresult:String=ComboBox(event.target).selectedItem.data;

trace(result);

if(result!=""){//为空的情况不用加载任何swf文件,空是默认皮肤

StyleManager.loadStyleDeclarations(result,true);

}

这下问题简单多了,用户通过下拉列表选择了皮肤,我动态加载,貌似已经实现了。但是问题又来了,

你不可能让用户每次进来都要选一次吧?老大我要是就喜欢红色,我希望每次进来都红色,能行嘛?

是的,这个问题也比较严重,要考虑到与用户使用和交互的友好性。OK,改吧。

现在用户已经选择了他喜欢的皮肤,我得保存起来,存哪里?服务端?客户端?以前Ext人家是放入客户端cookies里面的,那我们Flex没有必要放到数据库的表里面吧!好的,我们也放入客户端系统中。

难道要存入文件中?用Flex/ActionScript来操作文件?晕,不会吧,这可怎么写啊。

于是乎,偶又打开了ActionScript3.0cookbook这本书,我就看目录,果然在第17章发现了个很好的目录名:

存储持久化数据

仔细一看就是讲如何把数据保存在客户端的,看来这个就是我要找的了。花了点心思看玩了数据写入和读出,好啦,

万事俱备,开始最后收尾了。用户选择后我要写入到本地共享对象中。代码加入:

privatefunctioncloseHandler(event:Event):void{

varresult:String=ComboBox(event.target).selectedItem.data;

trace(result);

if(result!=""){

StyleManager.loadStyleDeclarations(result,true);

}

//写入客户端共享对象

varcssData:SharedObject=SharedObject.getLocal("UserCss");

cssData.data.cssName=result;

cssData.flush();

}

既然数据保存了,那么初次启动肯定要用到这些数据啊,来吧,收工吧,加入最后代码:

<mx:Applicationxmlns:mx="http://www.adobe.com/2006/mxml"layout="absolute"initialize="initCollections()"

creati>

privatefunctionloadStyle():void{

//从客户端共享对象读取保存的CSS数据

varcssData:SharedObject=SharedObject.getLocal("UserCss");

if(cssData.data.cssName){//css名字存在就加载相应的CSS

trace(cssData.data.cssName);

switch(cssData.data.cssName){

case'BlueTan.swf':

cssCB.selectedIndex=1;

break;

case'Brauwny.swf':

cssCB.selectedIndex=2;

break;

case'kingnarestyle.swf':

cssCB.selectedIndex=3;

break;

case'shadow.swf':

cssCB.selectedIndex=4;

break;

case'SunNight.swf':

cssCB.selectedIndex=5;

break;

default:cssCB.selectedIndex=0;

}

if(cssData.data.cssName!=""){

StyleManager.loadStyleDeclarations(cssData.data.cssName,true);

}

}

else{

cssCB.selectedIndex=0;

}

}

大功告成!

每天进步一点点就好,其实在实际扩展过程中会有很多问题,还会报很多异常。

如果大家开发前台最好装个debug模式的flashpalyer,主要可以断点调试,通过

trace();打印信息。自己扩展成功了发现代码也不过寥寥数行,但是整个过程差不多花了

我一个半小时。但是这1个半小时却带给了我很多惊喜和快乐。

其实Flex和ActionScript还是很强大的,呵呵。

/////////////////////////////////////////////////////////////////////////

刚刚写完这个帖子,我又仔细的运行了下,又发现一个BUG。

原来你每次调用:

StyleManager.loadStyleDeclarations(result,true);//这里的true表示加载完成后立马更新页面效果

来加载新的css时并没有去掉先前的css因此整合页面不稳定,有时候显示正确,有时候却是2种css效果的叠加。

修改后的代码为:

[Bindable]

privatevarlastCssName:String;//上次加载的CSS名称

[Bindable]

privatevarcssSource:Array=[

{label:'默认',data:''},

{label:'样式1',data:'BlueTan.swf'},

{label:'样式2',data:'Brauwny.swf'},

{label:'样式3',data:'kingnarestyle.swf'},

{label:'样式4',data:'shadow.swf'},

{label:'样式5',data:'SunNight.swf'}

];

privatefunctionloadStyle():void{

//从客户端共享对象读取保存的CSS数据

varcssData:SharedObject=SharedObject.getLocal("UserCss");

lastCssName=cssData.data.cssName;

if(lastCssName){//css名字存在就加载相应的CSS

trace(lastCssName);

switch(lastCssName){

case'BlueTan.swf':

cssCB.selectedIndex=1;

break;

case'Brauwny.swf':

cssCB.selectedIndex=2;

break;

case'kingnarestyle.swf':

cssCB.selectedIndex=3;

break;

case'shadow.swf':

cssCB.selectedIndex=4;

break;

case'SunNight.swf':

cssCB.selectedIndex=5;

break;

default:cssCB.selectedIndex=0;

}

if(lastCssName!=""){

StyleManager.loadStyleDeclarations(lastCssName,true);

}

}

else{

cssCB.selectedIndex=0;

}

}

privatefunctioncloseHandler(event:Event):void{

varresult:String=ComboBox(event.target).selectedItem.data;

trace(result);

if(result!=""){

//先除去旧的再加载新的

StyleManager.unloadStyleDeclarations(lastCssName,false);//这里false先不更新,等下面加载完了再更新

StyleManager.loadStyleDeclarations(result,true);

lastCssName=result;

}

else{//如果选择的是默认,则去除旧的就OK了

StyleManager.unloadStyleDeclarations(lastCssName,true);

lastCssName=result;

}

//写入客户端共享对象

varcssData:SharedObject=SharedObject.getLocal("UserCss");

cssData.data.cssName=result;

cssData.flush();

}

红色代码是更改后加的,主要是加载当前皮肤时先除去之前的皮肤效果,

并且把之前皮肤效果的名称换成当前皮肤效果名称。

相关推荐

aSuncat / 0评论 2020-08-18