9.17.从SWF 文件中生成动态皮肤

9.17.1. 问题
你想在Flash IDE 中创造一个按钮,它的每个状态有不同的动作。
9.17.2. 解决办法
创建一个FLA 并在此FLA 中创建一个意味着有多个帧和动作的输出的MovieClip 元件。

利用生成的SWF 和MovieClip 名称,在源代码和元件引用中通过利用[Embed] 元数据标记将MovieClip 为你动作的拓展。把一个mx.core.UIComponent子类当作mx.controls.Button实例的皮肤,然后利用继承的currentState 属性控件当前状态并在Button 实例内修改MovieClip 的动作帧。
9.17.3. 讨论
应用SWF 文件中的动画皮肤类似于在组件声明阶段应用编程实现的皮肤。两者之间皮肤的生成不同于,前者的动作由元件中帧提供,相反后者则是编程实现组件的动作元素。

若要生成待嵌入的动态皮肤,从一个FLA 文件的库中使用MovieClip 元件,该FLA 文件中帧标签的定义与其状态相关。当你为FLA 库中的元件指定链接属性时,元件随后在类声明中被嵌入进去。你然后通过引用类将动态皮肤添加到显示列表中,动作效果由基于组件状态阶段的前向帧控制。

若要生成动态皮肤,首在Flash IDE 中添加一个新的MovieClip 元件,然后添加许多命名了的帧以及帧与帧之间沿时间线的动作,如下图9-3.

图9-3. 创建一些命名的帧及其间的动作.


只要你喜欢,你的动作当然可以比本例中所含的动作复杂得多。重要的是记住帧标签名是逻辑的,与五个主要的按钮状态相关: 弹起、按下、选中、经过和失效。在图9-3 的FLA中,每个状态都添加两个帧标签: 一个表示当前状态动作的开始,一个则表示结束(例如OverBegin 和OverEnd)。响应状态阶段的自定义类会利用那些标签预定相应帧。下一步就是从Flash 中导出元件,以便Flex 编译器能够使用它。

为允许访问SWF 文件中元件的帧,基类属性定义为flash.display.MovieClip 类的一个实例且指定了类名。观察下图9-4, 先前创建的多帧的MovieClip 元件被赋予类名ButtonClip 并以此导出。

图9-4. 利用唯一的类名导出剪辑


要从生成的SWF 文件中导入元件,需在类声明阶段使用[Embed]元数据标记。source 属性定义为SWF 文件的位置,然后用导出的元件所赋的类名去定义symbol 属性,如下:
+展开
-ActionScript
package oreilly.cookbook {
import flash.display.MovieClip;
[Embed(source="assets/styles/FLAExample.swf",symbol="ButtonClip")]
public class ButtonClass extends MovieClip{}
 }

该类会作为自定义元素添加到显示列表中,从列表中可利用帧标签浏览先前定义的两者。

ButtonClass 实例不能直接添加到Flex 程序的显示列表中,因为它是Flash 组件的一个子类并没用实现mx.core.IFlexDisplayObject。若要将此类的实例添加到显示列表中,应将其变成mx.core.UIComponent 的子类。

将ButtonClass 实例添加到显示中的自定义UIComponent 类同样会依据对currentState属性的更新而预先获取动作帧。下面例子是一个应用于Button 实例的自定义皮肤:
+展开
-ActionScript
package oreilly.cookbook {
import flash.display.MovieClip;
import flash.events.Event;
import mx.core.UIComponent;
public class ButtonAnimatedSkin extends UIComponent {
private var _state:String;
private var _movieClipAsset:MovieClip;
public function ButtonAnimatedSkin() {
super();
}
//当我们创建子类时, 实际上实例化了我们的ButtonClass
override protected function createChildren():void {
super.createChildren();
_movieClipAsset = new ButtonClass();
_movieClipAsset.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
addChild(_movieClipAsset);
}
//我们需要确认有一个固态背景to hit detection against.
// 即使我们看不见,那也是必要的。
override protected function updateDisplayList( unscaledWidth:Number,unscaledHeight:Number ):void {
graphics.clear();
graphics.beginFill( 0x000000, 0 );
graphics.drawRect( 0, 0, _movieClipAsset.width,_movieClipAsset.height );
graphics.endFill();
//确保剪辑总是放置在0,0像素
_movieClipAsset.x = _movieClipAsset.width/2;
_movieClipAsset.y = _movieClipAsset.height/2;
}
//按钮状态发生变化时会调用该方法。
override public function set currentState(value:String):void{
_state = value;
//有一些值我们现在还没有用到;但是如果我们希望,
//我们当然应该创建不能的动画和剪辑。
if (_state == "selectedUp" ) _state = "selected";
if(_state == "selectedDown") _state = "down";
if(_state == "selectedOver") _state = "over";
switch( _state ){
case "over":
//对于每个状态我们仅简单地gotoAndPlay
//相应状态的正确帧
_movieClipAsset.gotoAndPlay("OverBegin");break;
case "down":
_movieClipAsset.gotoAndPlay("DownBegin");break;
case "selected":_movieClipAsset.gotoAndPlay("SelectedBegin");break;
case "up":_movieClipAsset.gotoAndPlay("EnabledBegin");break;
case "disabled":_movieClipAsset.gotoAndPlay("DisabledBegin");break;
}
}
//我们每次输入一个帧时, 我们希望判断是否处在每个状态时
//我们某个动作的结尾,如果是在结尾,我们要将剪辑调回
//生命周期的开始。
private function enterFrameHandler(event:Event):void {
switch(_state){
case "over":
if(_movieClipAsset.currentLabel == "OverEnd"
  _movieClipAsset.gotoAndPlay("OverBegin");
break;
case "down":
if (_movieClipAsset.currentLabel == "DownEnd" ) {
_movieClipAsset.gotoAndPlay("DownBegin" );
}
break ;
case "up" :
if (_movieClipAsset.currentLabel == "EnabledEnd" ) {
_movieClipAsset.gotoAndPlay("EnabledBegin" );
}
break ;
case "selected" :
if (_movieClipAsset.currentLabel == "SelectedEnd" ) {
_movieClipAsset.gotoAndPlay("SelectedBegin" );
}
break ;
case "disabled" :
// 由于disabled 状态只有一帧,不需要做任何事情
break;
}
}
}
}

在重载createChildren 方法过程中,实例化了一个ButtonClass 新实例并添加到显示列表中。每次在Button 中更新当前状态时, ButtonAnimatedSkin 类用一个新的状态通知ButtonClass 获取指定的帧。在enterFrameHandler 方法中生成一个循环来判断按钮是否在动画的结尾。如果动画已经到了结束帧,影片将回到状态动画的开始。

正如通过在皮肤样式属性中定义类以应用编程实现的皮肤,同样可以这样应用ButtonAnimatedSkin :
+展开
-XML
<mx:Button toggle="trueskin="oreilly.cookbook.ButtonAnimatedSkiny="300x="300"/>

加支付宝好友偷能量挖...


评论(0)网络
阅读(135)喜欢(0)flash/flex/fcs/AIR