我正在使用Flash CS4(以下简称“Flash”)构建一个视频播放器来创建图形符号,并使用Flash Builder 4(“FB4”)进行编译和调试。以下是我在当前工作流程中采取的步骤:
- 在Flash中创建图形符号。我为玩家创建了一些不同的符号,但我会在这里只关注播放/暂停按钮(“ppbutton”)。
- 在“库”面板中,我转到ppbutton符号的Linkage属性,并链接到一个名为assets.PlayPauseButtonAsset的类,该类扩展了MovieClip。我实际上没有资产包,也没有PlayPauseButtonAsset的类文件,因为Flash会在我发布时为我创建它们。
- 在Flash的发布设置中,我将项目设置为导出将在FB4中使用的SWC,名为VideoPlayerAssets.swc。
- 创建SWC后,我创建了名为“VideoPlayer”的FB4项目,并将SWC添加到我的路径中。 FB4会自动在默认包中创建VideoPlayer类。
- 在VideoPlayer.as中,我导入资产。*,它导入我在Flash中创建的所有符号类,并通过VideoPlayerAssets.swc提供。我现在可以实例化ppbutton并添加到舞台上,如下所示:
var ppbutton:PlayPauseButtonAsset = new PlayPauseButtonAsset();
addChild(ppbutton);
此时ppbutton没有任何功能,因为我没有为它创建任何代码。所以我创建了一个名为video.controls.PlayPauseButtonLogic的新类,它扩展了assets.PlayPauseButtonAsset。我添加了一些逻辑,现在我可以使用这个新类在舞台上放置一个有效的按钮:
var ppbutton:PlayPauseButtonLogic = new PlayPauseButtonLogic();
addChild(ppbutton);
这很好用,但你可能会问我为什么不首先将Flash中的ppbutton符号链接到video.controls.PlayPauseButtonLogic类。原因是我有一个设计师在Flash中创建UI,我不想每次在逻辑上进行更改时都必须从Flash重新发布SWC。基本上,我希望我的设计师能够在Flash中创建符号,将该符号链接到Linkage属性中的逻辑命名类,然后导出SWC。除非设计师对符号或布局进行更改,否则我不想再次触摸.fla文件。我也在为项目使用版本控制系统,确保只有设计师触摸.fla文件更清晰。
所以,最后,这是我遇到的问题:
- 随着设计变得越来越复杂,设计师正在嵌套符号以将视频控件定位在控制栏上。他创建了一个控制栏符号并将其链接到assets.ControlBarAsset。控制栏符号包含ppbutton符号。
- 设计师发布SWC和ControlBarAsset现在可在FB4中使用。我创建了一个名为video.controls.ControlBarLogic的新类,它扩展了assets.ControlBarAsset,所以我可以向控制栏添加一些逻辑,然后将控制栏添加到舞台:
var controlbar:ControlBarLogic = new ControlBarLogic();
addChild(controlbar);
- 这有效,但ppbutton没有做任何事情。那是因为ppbutton虽然在控制栏内,但仍然只链接到PlayPauseButtonAsset,后者没有任何逻辑。我不再实例化一个ppbutton对象,因为它是控制栏的一部分。
那是我今天被困的地方。我似乎不能简单地将控制栏的pp按钮重新投射为PlayPauseButtonLogic,因为我得到了一个Type错误。而且我不想创建一个必须实例化每个视频播放器控件的类,根据设计者放置它们的方式将它们放在舞台上的x和y值,因为这需要我打开.fla并检查符号的各种属性,然后将这些值添加到代码中。如果设计师做了改变,我每次只需更新这些属性就必须进入代码。不好。如何重新嵌套嵌套符号以使用我创建的扩展资产类的逻辑类?请记住,解决方案不是将Flash符号链接到实际类,因此我不必继续重新编译SWC,除非有办法在不重新编译SWC的情况下执行此操作。我希望设计师做他的事情,发布SWC,并完成它。然后,我可以使用他的SWC,将我的逻辑应用于他的资产,并能够调试和编译最终的SWF。
答案 0 :(得分:4)
以下是我有时使用的解决方案:
不要使PlayPauseButtonLogic
扩展PlayPauseButtonAsset
,而是使用此类作为PalyPauseButtonAsset的warpper,使用合成而不是继承! ; )。
您将在ControlBarLogic类中获得类似的内容:
//constructor exemple
public function ControlBarLogic(){
//all logic of PPButton is inside PlayPauseButtonLogic
//you just pass a reference to the PlayPauseButtonAsset button contained inside ControlBarAsset
var ppButtonLogic: PlayPauseButtonLogic=new PlayPauseButtonLogic(refToButtonAsset)
//the warper class can extends EventDispatcher so you will be able to listen to custom or redisatched events
ppButtonLogic.addEventListener("ppPause",onPause)
}
希望它会帮助你
答案 1 :(得分:2)
你可以有两个类,一个持有功能,另一个提供图形实现(资产/皮肤)
让PlayPauseButtonLogic扩展AssetWrapper。
解决有关事件侦听器问题的简单方法,您可以执行以下操作:
package {
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.IEventDispatcher;
public class AssetWrapper implements IEventDispatcher {
private var _skin:DisplayObjectContainer;
public function AssetWrapper( skin:DisplayObjectContainer = null ) {
if ( skin ) setSkin(skin);
}
public function setSkin(skin:DisplayObjectContainer):void{
_skin = skin;
}
public function dispatchEvent(event:Event):Boolean{
_skin.dispatchEvent(event);
}
public function hasEventListener(type:String):Boolean{
return _skin.hasEventListener(type);
}
public function willTrigger(type:String):Boolean{
return _skin.willTrigger(type);
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
_skin.removeEventListener(type, listener, useCapture);
}
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
_skin.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
}
}
编辑: 然后,您可以向AssetWrapper添加尽可能多的属性/方法,根据需要委派给DisplayObject(外观)。它还使您可以更好地控制这些属性/方法。 即:
public function get x( ):Number {
return _skin.x;
}
public function set x( v:Number ):void {
if ( _skin.x = v ) return;
if ( _useWholePixels ) _skin.x = Math.round(v);
else _skin.x = v;
}
这样,例如,您可以直接补间您的AssetWrapper实例。此外,您可以控制是否要将其放置在整数(x = 100)或不放(x = 100.5)
对于方法,只有相同的想法:
public function addChild( child:DisplayObject ):DisplayObject {
return _skin.addChild( child );
}
然后使用它,您将扩展AssetWrapper并实现具体行为:
package {
import flash.display.DisplayObjectContainer;
import flash.events.MouseEvent;
public class SimpleButton extends AssetWrapper {
public function SimpleButton( skin:DisplayObjectContainer = null ) {
super(skin)
}
override public function setSkin( skin:DisplayObjectContainer):void {
super.setSkin( skin );
addEventListener(MouseEvent.ROLL_OVER, _onRollOver );
addEventListener(MouseEvent.ROLL_OUT, _onRollOut );
}
protected function _onRollOver(e:MouseEvent):void {
_skin.alpha = .5;
}
...
}
你会按如下方式使用它:
//you can get your graphical assets in many different ways
var buttonSkin:Sprite = new LibraryButtonSkin
//or
var ButtonSkinClass:Class = this.loaderInfo.applicationDomain.getDefinition("SimpleButtonSkin") as Class;
buttonSkin = new ButtonSkinClass;
var button:SimpleButton = new SimpleButton(buttonSkin);
button.addEventListener(MouseEvent.CLICK, _handleButton);
它只是一个指南,在实际实现中,您要确保检查诸如皮肤是否已存在之类的内容,然后删除所有添加的侦听器。您可能会听取ADDED_TO_STAGE事件并触发初始化方法...... 通过实现一个destroy()方法来清理你的实例之后也很棒,你可以确保删除所有添加的侦听器,并停止/停止定时器,声音等等。
答案 2 :(得分:0)
哇所有的流量,我们沉没在终点线......
好吧,这样的事情
可能是?。