3
votes

I have a View component which initialises youtube cloud api using "http://www.youtube.com/apiplayer?version=3&modestbranding=1" url and plays the video fullscreen. It has play, pause and progress bar under s:actionContent, but I am trying to put "rewind", "play/pause", "forward" and a interactive progress bar on top of the chromeless player itself (transparent popup with image buttons for the same), like the below image. enter image description here

My View component which initialises youtube api does not have any items. (Removed s:actionContent to try out popup)

<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" title="YoutubeVideoPlay" viewActivate="init()" >
    <fx:Script source="YoutubePlayer.as"/>
    <fx:Script>
        <![CDATA[
            //navigator.addEventListener(TouchEvent.TOUCH_BEGIN,showPlayerControl);     How to add a event listener on the youtube player?
            public function showPlayerControl():void{
                PopUpManager.addPopUp(PlayerControls,player);
            }
        ]]>
    </fx:Script>
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
</s:View>

Need help with this popup manager to appear on top of chromeless player, when the user taps on the playing video.

<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009" 
     xmlns:s="library://ns.adobe.com/flex/spark" width="400" height="300">
    <fx:Script source="../YoutubePlayer.as"/>
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <fx:Style>
        @namespace s "library://ns.adobe.com/flex/spark";
        global
        {
            modal-transparency: 0.0;
            modal-transparency-color: white;
            modal-transparency-blur: 0;
        }
    </fx:Style>
    <fx:Script>
        <![CDATA[               
            import mx.managers.PopUpManager;
            /*[Bindable][Embed(source="view/assets/images/play32.png")]
            public static var iconPlay : Class;*/
            [Bindable][Embed(source="view/assets/images/pause32.png")]
            public static var iconPause : Class;
            [Bindable][Embed(source="view/assets/images/forward32.png")]
            public static var iconForward : Class;
            [Bindable][Embed(source="view/assets/images/rewind32.png")]
            public static var iconRewind : Class;               
            //addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE,removePlayerControls);
            /*private function removePlayerControls(event:FlexMouseEvent):void {
            PopUpManager.removePopUp(this);
            }*/             
            public function closeAndBackup():void {
                dispose();
                navigator.popView();                                
            }
            public function initAndPlay():void {                
                player.playVideo();

            }               
            private var _duration:String = "";

            [Bindable]
            public function get duration():String {
                return _duration;
            }               
            public function set duration(val:String):void {
                _duration = val;

            }
            protected function ytVideoSlider_changeHandler(event:Event):void
            {
                // TODO Auto-generated method stub
                trace(event.currentTarget.value);
                player.seekTo(event.currentTarget.value,true);              
            }
        ]]>     
    </fx:Script>
    <s:VGroup>
        <s:HGroup>
            <s:layout>
                <s:HorizontalLayout paddingTop="10" paddingLeft="10"/>
            </s:layout>
            <s:HSlider id="ytVideoSlider" 
                       liveDragging="true"
                       dataTipPrecision="1"
                       maximum="{duration}"
                       change="ytVideoSlider_changeHandler(event)"/>
            <s:Label text="{Math.round(ytVideoSlider.value)}"/>
        </s:HGroup>
        <s:Button icon="{iconRewind}" click="player.playVideo()"/>
        <s:Button icon="{iconPause}" click="player.pauseVideo()"/>
        <s:Button icon="{iconForward}" click="closeAndBackup()"/>
    </s:VGroup>
</s:Panel>

Any help will be appreciated. :)

I have just started with Flash Builder's spark components, so pardon me if my question is too lame.

Or Is there any link/tutorial available to place player controls on top of chromeless youtube player?

Update: I was able to solve my problem, and provided my solution too

3
Especially since you put a bounty on the question you should comment on the answers, to clarify what they are missing.Mark Fox
@MarkFox: Actually I was able to solve my problem just after putting a bounty on this question. It's similar to answer given by Colin. I'll post my answer too.AabinGunz
Classic problem solving conundrum. Asking the question helps me self-solve problems all the time.Mark Fox
@MarkFox: Yes :) I added my solution.AabinGunz

3 Answers

1
votes

You should be able to add a click listener to the entire view. While I have never used this API before, I would imagine it would look something like this:

<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
xmlns:s="library://ns.adobe.com/flex/spark" title="YoutubeVideoPlay"
viewActivate="init()" click="showPlayerControl()">

<fx:Script source="YoutubePlayer.as"/>
<fx:Script>
    <![CDATA[
        public function showPlayerControl():void{
            PopUpManager.addPopUp(PlayerControls,player);
        }
    ]]>
</fx:Script>
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>

1
votes

So you're nearly there. What you need to remember is that the YouTube player has its own interactions, eg when the user clicks the video it usually pauses/resumes. Now you can get around this by placing an invisible Sprite on top of the video as this'll allow you to capture the user's mouse movements and clicks.

The only issue with this is the current state of autoplaying; at the moment (and for the future I guess) autoplays don't count as views against the video. The user needs to press the play button on the YouTube video to actually make that count as a view.

So what I do is only add this invisible Sprite once playback has commenced. You can then also be clever and send pause/resume events to the player itself when the user clicks on your invisible Sprite.

Regarding the UI components that you're after: they're very easy to put together, you can always grab standard UI Flash/Flex components and hook them up to the player API (I see you've made a start); it's always a good idea, though, to get a design in you head rather than sketching out UIs over and over again in code.

As a footnote: you're always welcome to use my middleware class for the YouTube player on github: https://github.com/ahmednuaman/AS3/blob/master/com/firestartermedia/lib/as3/display/component/video/YouTubePlayerAS3.as

0
votes

Solution to my question

I have a PlaylistsView.mxml which has a List with all the videos. Once clicked it pushes a new view called YtPlayView.mxml

<!--YtPlayView.mxml-->  
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:popup="views.popup.*"
    title="{data.title}" viewActivate="init()" viewDeactivate="deactivateYoutubePlayer()">
    <fx:Script source="ytfeeds/YoutubePlayer.as"/>
    <fx:Script>
        <![CDATA[
            public function deactivateYoutubePlayer():void{
                PopUpManager.removePopUp(ytcPopup);
                dispose();
            }
        ]]>
    </fx:Script>
</s:View>

In YoutubePlayer.as, onPlayerReady(event:Event) I add a mouseclick eventlistener player.addEventListener(MouseEvent.CLICK,showPlayerControl);

    <!--YoutubePlayer.as contents-->
public function showPlayerControl(event:MouseEvent):void{
    ytcPopup=new PlayerControls();
    ytcPopup.player=player;
    ytcPopup.duration=data.duration;                
    ytcPopup.currentPosition="00:00:00";        
    ytcPopup.open(this,true);
    ytcPopup.width = this.stage.width;
    ytcPopup.setStyle("modalTransparency",0);
    ytcPopup.setStyle("modalTransparencyBlur",3);
    ytcPopup.setStyle("modalTransparencyColor", "#ff0000");
    if(ytcPopup.player.getPlayerState()==1){        
        ytcPopup.playPauseBtn.setStyle("icon",ytcPopup.iconPause);
    }
    else if(ytcPopup.player.getPlayerState()==2){       
        ytcPopup.playPauseBtn.setStyle("icon",ytcPopup.iconPlay);
    }
    ytcPopup.y = this.stage.height-195;
    PopUpManager.bringToFront(ytcPopup);        
    if(player.getCurrentTime()!=0)
        ytcPopup.ytVideoSlider.value=player.getCurrentTime();       
}

Which gives me something like below (It's a portrait view, on Landscape view it comes on top of the video)

If anyone wants more source code or help, i'll be happy to help :) Just drop a comment.

enter image description here