Une application AIR transparente

8 09 2008

Je développe en ce moment un prototype qui nécessite de personnaliser le look de la fenêtre, « le chrome », de l’application. Il est très simple de réaliser une application AIR transparente avec Flex Builder et je vais vous expliquer dans cet article comment faire. Néanmoins, je me suis retrouvé confronté à un comportement innatendu que j’ai réussi à contourner. Je souhaite que la taille de mon application AIR prenne automatiquement la taille de l’écran de l’utilisateur (car je dois faire évoluer des particules sur tout l’écran). Voici comment procéder:

Lorsque l’on crée une application AIR sous Flex builder, l’élément principal est un <mx:WindowedApplication>. Le fond de la fenêtre est un PNG transparent que j’ai réalisé sous PhotoShop. Pour ne pas dévoiler mon prototype, j’utilise dans ce tutoriel un PNG qui représente un tasse de café. Voici le code de mon projet pour réaliser une application transparente:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="initApp()" 
    backgroundAlpha="0"
    layout="absolute">
    <mx:Script>
        <![CDATA[

            private function initApp():void{
                myCup.addEventListener(MouseEvent.MOUSE_DOWN, handleDown);
                myCup.addEventListener(MouseEvent.MOUSE_UP, handleUp);

                nativeWindow.width = Capabilities.screenResolutionX;
                nativeWindow.height = Capabilities.screenResolutionY;
                nativeWindow.x = 0;
                nativeWindow.y = 0;
            }

            private function handleDown(event:MouseEvent):void{
                myCup.startDrag();
            }

            private function handleUp(event:MouseEvent):void{
                myCup.stopDrag();
            }
        ]]>
    </mx:Script>
    <mx:Image x="0" y="0" source="img/Coffee-Time.png" id="myCup" useHandCursor="true" buttonMode="true"/>
</mx:WindowedApplication>

Les éléments intéressants apparaissent en rouge:

  • Je modifie le style de ma WindowedApplication en indiquant que le fond (background) est transparent (alpha=0)
  • A l’initialisation de l’application, sur l’événement creationComplete, je modifie à la volée la taille de mon application. La classe Capabilities me renvoie la résolution de l’utilisateur.
  • J’ai rajouté des listeners sur ma tasse à café pour déclencher son déplacement, ou « drag and drop », à l’aide des fonctions startDrag() et stopDrag().

Ce n’est pas suffisant. Si vous compilez l’application, le fond reste gris. Il faut éditer le manifeste XML de l’application air (il porte le nom de votre application -app.xml et se trouve dans le même répertoire que votre application principale). Trois paramètres (tags XML) dans ce manifeste sont à renseigner. Attention, par défaut ils sont commentés donc inactifs! Recherchez les tags systemChrome, transparent et visible:

<systemChrome>none</systemChrome>
<transparent>true</transparent>
<visible>true</visible>

Si vous compilez, le fond de votre application a bien disparu et vous apercevez le bureau de votre OS derrière la tasse à café. Par contre, le cadre de la fenêtre subsiste ce qui peut diminer l’expérience utilisateur:

C’est parce que nous travaillons avec une mx:WindowedApplication. Pour faire disparaitre ce cadre, il faut remplacer le tag <mx:WindowedApplication> par <mx:Application>. Il faut ensuite remplacer l’objet nativeWindow dans le code par stage.nativeWindow. Mais si vous compilez, vous obtiendrez une erreur! Il sera incapable de modifier la taille de l’application pour que cela prenne toute la taille de l’écran. J’ai réalisé qu’en fait, l’événement qui déclenche ce redimensionnement, ‘creationComplete’, déclenche l’opération trop tôt pour le lecteur Flash qui n’a pas encore placé d’élément sur la scène ‘stage’. Il faut donc utiliser l’événement « addedToStage » et tout rentre dans l’ordre. J’ai aussi rajouté le fait que lorsqu’on effectue un click-droit sur la tasse, l’application se ferme. En effet, vous n’avez plus de cadre pour minimiser, maximiser et fermer l’application. A vous de tout coder🙂. Voici le code mis à jour:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    addedToStage="initApp()"
    backgroundAlpha="0"
    layout="absolute">
    <mx:Script>
        <![CDATA[

            private function initApp():void{
                myCup.addEventListener(MouseEvent.MOUSE_DOWN, handleDown);
                myCup.addEventListener(MouseEvent.MOUSE_UP, handleUp);
                myCup.addEventListener(MouseEvent.RIGHT_CLICK, handleRight);

                stage.nativeWindow.width = Capabilities.screenResolutionX;
                stage.nativeWindow.height = Capabilities.screenResolutionY;
                stage.nativeWindow.x = 0;
                stage.nativeWindow.y = 0;
            }

            private function handleDown(event:MouseEvent):void{
                myCup.startDrag();
            }

            private function handleUp(event:MouseEvent):void{
                myCup.stopDrag();
            }

            private function handleRight(event:MouseEvent):void{
                stage.nativeWindow.close();
            }
        ]]>
    </mx:Script>
    <mx:Image x="0" y="0" source="img/Coffee-Time.png" id="myCup" useHandCursor="true" buttonMode="true"/>

</mx:Application>

Désormais j’ai une application totalement personnalisée, qui n’est plus liée au chrome de l’OS, ni même au chrome standard d’Adobe air.


Actions

Information

19 responses

8 09 2008
DeyLonn

Useful😉.
Thanks.

8 09 2008
Cédric PASCAL

Niquel car c’est un besoin assez régulier.
Personnellement j’ai eu un besoin assez similaire qui m’a posé problème.

Je souhaitais créé un petit compagnon de bureau qui se balade sur l’écran sans pour autant bloquer le clic sur les icônes placés sur le bureau…

Au passage si quelqu’un à une maniere de contourner mon probleme je serais très interessé !🙂

Sinon merci pour ce tuto😉

8 09 2008
michael chaize

Avec cet exemple, tu peux cliquer derrière.
Tu veux cliquer derrière le compagnon ? C’est impossible à mon avis

8 09 2008
Cédric PASCAL

Je vais essayer alors.
Cool🙂

13 09 2008
BrunoM

bonjour,

J’ai testé les deux scripts, le premier pas de problème.
Le second, j’ai deux type d’erreur:
– 1119 accès à la propriété RIGHT_CLICKpeut-être non définie, via la référence de type static Class.
=> j’ai corrigé en remplacant RIGHT_CLICK par CLICK
– 1119 accès à la propriété nativeWindows peut-être non définie, via la référence de type static Flash.display.Stage
=> et la je n’ai pas trouvé de solution de fonctionne

Cordialement.

13 09 2008
michael chaize

Ok, tu peux m’envoyer tes projets zippés si tu le souhaites par email. Mon email c’est « m » plus « chaize » attaché « @ », adobe.com
Vérifie bien que tu travaillez bien dans un projet AIR, avec un tag . C’est erreurs de propriété sont peut-être dues à un copier-coller sauvage. Essaye de retaper entièrement sous Flex Builder les lignes qui posent problème, peut être qu’il n’importe pas les bonnes classes.

19 09 2008
Christopher BOGRAT

Salut,

Merci pour cet article intéressant.

J’ai moi-même été confronté à ce genre de problème et j’arrive au même résultat avec cette méthode:
– passer le showFlexChrome du WindowedApplication à false
– dans mon creationComplete je fais un « this.maximize(); »
– dans mon -app.xml : none, true

Je conserve ainsi mon WindowedApplication.

Est-ce une mauvaise méthode ?

Et comment ferais-tu si l’utilisateur a plusieurs écrans ?

Le Capabilities.screenResolutionX me renvoie la résolution de l’écran principal et du coup je ne peux déplacer l’application que sur cet écran…

19 09 2008
Christopher BOGRAT

Y a du code qui est passé à la trappe!

– dans mon -app.xml : systemChrome:none, transparent:true

désolé😀

19 09 2008
michael chaize

ah intéressant… justement je ne sais pas si on peut savoir si le user a deux écrans, je n’en suis pas sûr. Par défaut tu peux faire x2.🙂

23 09 2008
Christopher BOGRAT

Ah je viens de m’apercevoir que la largeur maximale est de 2880
(cf: http://bugs.adobe.com/jira/browse/SDK-14431 ) sachant que la résolution que j’ai actuellement est de 3600 en largeur, j’ai un gros vide à droite.😀

Sinon j’ai trouvé comment récupérer les écrans de l’utilisateur avec Screen.screens

26 11 2008
Fabien Warniez

Hey Michael !
Interessant mais le probleme est que quand on passe l’appli en transparent = true les performances sont gravement diminuees ! Mon appli passe de 20% a plus de 50% de CPU !
C’est un bug connu ?

26 11 2008
michael chaize

Intéressant. tu es sous quel OS ?

8 12 2008
Flüge

Hey i´ve got searched a long time for this answer´s, very useful! Thx

17 01 2009
Fabien Warniez

En fait j’ai teste que sous XP mais j’imagine que ca fait pareil sous MAC mais je n’ai pas essaye.

13 05 2009
Kiva

Génial, exactement ce que je cherchais, merci beaucoup.

14 05 2009
yacaFX

Hey nice explanation!!! thanks a lot!!

16 05 2009
Deisss

Je viens publier ma petite contribution, étant possesseur d’un dual screen 2×1680/1050 (2×22″ wide) j’étais confronté aux soucis suivant :
-L’application ne peut pas se ballader dans un carré plus grand que 2880px… et on ne peut pas l’agrandir à plus de 2880px (mais ce dernier point est un bug connu et non résolu par ce que je propose ci dessous)
-L’application était lente (saccade visible) lors d’un déplacement à la souris (startDrag)
-Lorsque l’application est créée sur le desktop 1 (celui sur la droite), elle n’apparait jamais sur le desktop 0 sauf si elle démarre avec une partie sur le desktop 0 (ou la totalité) (et inversement)

Voila comment corriger les bugs (très simple), il suffit de remplacer dans ton code la fonction handleDown par :
private function handleDown(event:MouseEvent):void{
stage.nativeWindow.startMove();
}
ou (si l’on est en windowedApplication)
private function handleDown(event:MouseEvent):void{
nativeWindow.startMove();
}

Et le tour est joué ! Par ailleurs à ce moment là, ces 4 lignes peuvent être modifiés sans soucis :
stage.nativeWindow.width = Capabilities.screenResolutionX; stage.nativeWindow.height = Capabilities.screenResolutionY;
stage.nativeWindow.x = 0;
stage.nativeWindow.y = 0;

On peut alors les modifier en mettant la taille de la tasse de café pour les width et height et la position que l’on souhaite sans aucun soucis ! (a ce moment là la démo donné est parfaite !)

PS : encore merci pour ce bout de code très pratique, il est maintenant pleinement fonctionnel sans ancombre grace à cette minuscule modification (a part le bug de redimentionnement)

9 07 2009
marouane

bonjour, je voudrais savoir s’il était possible de redimensionné l’image de départ, après lancement de l’appli (comme si l’on voulé agrandir l’image en la prenant par les bords)
merci.

8 09 2009
ledog

bjr j’ai crée une application air pour une webradio, mais la lecture ne fonctionne pas sur mac. Savez vous pourquoi ?

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s




%d blogueurs aiment cette page :