2

我正在使用 Flash CS4(以下简称“Flash”)构建视频播放器,以创建图形符号并使用 Flash Builder 4(“FB4”)进行编译和调试。以下是我在当前工作流程中采取的步骤:

--在Flash中创建图形符号。我为播放器创建了一些不同的符号,但我将只关注播放/暂停按钮(“ppbutton”)。

-- 在库面板中,我转到 ppbutton 元件的链接属性并链接到一个名为 assets.PlayPauseButtonAsset 的类,该类扩展了 MovieClip。我实际上没有资产包,也没有 PlayPauseButtonAsset 的类文件,因为 Flash 会在我发布时为我创建它们。

-- 在 Flash 的 Publish 设置中,我将项目设置为导出一个将在 FB4 中使用的 SWC,称为 VideoPlayerAssets.swc。

-- 创建 SWC 后,我创建名为“VideoPlayer”的 FB4 项目并将 SWC 添加到我的路径中。FB4 自动在默认包中创建类 VideoPlayer。

-- 在 VideoPlayer.as 中,我导入 assets.*,它导入了我在 Flash 中创建的所有符号类,可通过 VideoPlayerAssets.swc 获得。我现在可以实例化 ppbutton 并添加到舞台,如下所示:

var ppbutton:PlayPauseButtonAsset = new PlayPauseButtonAsset();
addChild(ppbutton);

此时 ppbutton 没有任何功能,因为我没有为它创建任何代码。所以我创建了一个名为 video.controls.PlayPauseButtonLogic 的新类,它扩展了 assets.PlayPauseButtonAsset。我添加了一些逻辑,现在我可以使用这个新类在舞台上放置一个工作 ppbutton:

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 在 controlbar 内时,仍然只链接到 PlayPauseButtonAsset,它没有任何逻辑。我不再实例化 ppbutton 对象,因为它是控制栏的一部分。

这就是我今天卡住的地方。我似乎无法简单地将控制栏的 ppbutton 重新转换为 PlayPauseButtonLogic,因为我收到类型错误。而且我不想创建一个必须实例化每个视频播放器控件的类,根据设计师放置它们的方式将它们放置在舞台上的 x 和 y 值,因为这需要我打开.fla 并检查符号的各种属性,然后将这些值添加到代码中。如果设计人员进行了更改,我每次都必须进入代码只是为了每次更新这些属性。不好。

如何重新转换嵌套符号以使用我创建的扩展资产类的逻辑类?请记住,解决方案不是将 Flash 符号链接到实际类,因此我不必继续重新编译 SWC,除非有一种方法可以做到这一点而无需重新编译 SWC。我希望设计师做他的事,发布 SWC,然后完成它。然后我可以获取他的 SWC,将我的逻辑应用于他的资产,并能够调试和编译最终的 SWF。

4

3 回答 3

4

这是我有时使用的解决方案:

不要PlayPauseButtonLogic扩展PlayPauseButtonAsset,而是使用这个类作为 PalyPauseButtonAsset 的变形器,使用组合而不是继承!; )。

你会在你的 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)
}

希望对你有帮助

于 2010-04-02T17:30:38.250 回答
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(皮肤)。它还使您可以更好地控制这些属性/方法。IE:

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() 方法在您的实例之后进行清理也是一个很好的方法,您可以确保删除所有添加的侦听器并将诸如计时器之类的东西设为空/停止, 声音等

于 2011-03-24T12:41:48.960 回答
0

哇,所有的流量,我们在终点线沉没......

好吧,像这样的东西呢

  1. 抽象按钮行为
  2. PlayButtonBehavior 扩展...
  3. 诀窍是,图形组件都应该实现一些接口,允许它们在实例化时传递行为,或者更好的是,在运行时传递行为。您只需插入登录,逻辑将始终保留在外部,而不良资产将不断询问或回答相同的接口调用,从而允许您在它们之外工作。

可能?。

于 2013-10-04T12:29:11.470 回答