Cristalab

Evitar que los popups salgan de la pantalla en Flex 3

   Foros de discusión -> Tips, ¡Envía tus trucos aquí!
Mensaje Autor
Mensaje Publicado: Mie Mar 05, 2008 3:54 pm     Citar   firefox 
El problema es simple, Flex no tiene un modo simple de evitar que los popups se salgan de la pantalla y la solución es algo complicada.

Aparentemente no hay ninguna manera simple de hacer esto, pero sin duda sería muy interesante. El motivo por el que no se puede hacer es que internamente, Panel no usa StarDrag, sino un método parecido.

Una forma fácil de workaroundear esto es overridear el método move de nuestro Panel:

Código :

public override function move (x:Number, y:Number):void
{
   x = Math.max (0, Math.min (x, Application.application.width - width));
   y = Math.max (0, Math.min (y, Application.application.height - height));
   super.move (x, y);
}



Pero internamente, el StartDrag funciona de la siguiente manera (voy a describir el comportamiento de la propiedad x, la y es absolutamente análoga):

  1. Toma la coordenada X del cursor al momento de hacer click y le resto la posición de la pantalla.
  2. Cuando mueva el Mouse drageando la ventana, la posición final será la posición actual del cursor menos la diferencia del punto 1.


Esto genera un problema y es que el Drag de la ventana no es tan intuitivo como debería. Si no pueden imaginar lo que digo, vean el ejemplo del final del post. El drag se comporta algo raro.

Es por esto que hace falta un workaround más complejo. Siempre tratando de evitar caer en un kludge vamos a limitar la posición de la ventana para mantenerla dentro de los límites, pero además vamos a modificar la variable que usa internamente el reposicionamiento de la ventana.

A mano, hacemos esto soltando el botón izquierdo y volviéndolo a presionar, por lo tanto, vamos a hacer eso mismo, pero internamente.


Solución


El primer paso sería, anular el drag actual. Eso es simple, llamamos al método stopDragging.

Ahora, hay que empezar un nuevo drag, para eso llamamos al método startDragging. Pero éste recibe como parámetro un evento del Mouse.... ¿qué hacemos entonces?

La solución parecería ser crear un nuevo evento. Pero las propiedades stageX y stageY del MouseEvent son read-only. Lo que nos impide modificarlas fácilmente.

Entonces el código;

Código :

var myEvent:MouseEvent = new MouseEvent (MouseEvent.MOUSE_DOWN);
myEvent.stageX = 9999;
myEvent.stageY = 9999;


Simplemente no sirve. Tampoco sirve crear un objeto con esas propiedades y pasarlo a la función usando as y tampoco funciona crear un evento personalizado y castearlo.

¿Cuál es el truco entonces? Vamos a crear nuestra propia función de Drag. Es feo, pero aparentemente, no hay otra opción.

Lo que hacemos es overridear la función startDragging y stopDragging de la siguiente manera:

Código :

private var relx:Number;
private var rely:Number;

protected override function startDragging (e:MouseEvent):void
{
   relx = e.stageX - x;
   rely = e.stageY - y;
   
   systemManager.addEventListener (MouseEvent.MOUSE_MOVE, handleMouseMove, true);

    systemManager.addEventListener (MouseEvent.MOUSE_UP, handleMouseUp, true);

    systemManager.stage.addEventListener (Event.MOUSE_LEAVE, handleMouseLeave);
}
protected override function stopDragging ():void
{
   systemManager.removeEventListener (MouseEvent.MOUSE_MOVE, handleMouseMove, true);

    systemManager.removeEventListener (MouseEvent.MOUSE_UP, handleMouseUp, true);

    systemManager.stage.removeEventListener (Event.MOUSE_LEAVE, handleMouseLeave);
   
    relx = rely = NaN;
}

private function handleMouseMove (e:MouseEvent):void
{
   e.stopImmediatePropagation ();
   
   var myStage:Sprite = Sprite (Application.application);
   
   var xp:Number = e.stageX - relx;
   var yp:Number = e.stageY - rely;
   
   var xd:Number = Math.max (0, Math.min (xp, myStage.width - width));
   var yd:Number = Math.max (0, Math.min (yp, myStage.height - height));
   
   if (xp != xd || yp != yd)
   {
      relx = e.stageX - x;
      rely = e.stageY - y;
   }
   
   move (xd, yd);
}
private function handleMouseUp (e:MouseEvent):void
{
   if (!isNaN (relx)) stopDragging ();
}
private function handleMouseLeave (e:Event):void
{
   if (!isNaN (relx)) stopDragging ();
}

En caso de que se pregunten cómo supe que había que hacer todo esto, la respuesta es simple, busqué el código del componente Panel para encontrar la solución.

En caso de que se pregunten porqué empecé con la respuesta equivocada, es para que no aparezcan comentarios sugiriendo hacerlo de manera más simple.

Un ejemplo de cómo quedaría sería éste:




Quizás también te interesen estos otros tips :

HernanRivas


clabLevel: 2580 Genero:Masculino

1 Tutoriales
23 Tips

MP Email         
Volver arriba
Mensaje Publicado: Mie Mar 05, 2008 4:07 pm     Citar   firefox 
Link a mi post: http://www.cristalab.com/foros/t53343.html
Link al comentario: http://www.cristalab.com/foros/p359863.html#359863
 _________________
Hernán Rivas Acosta -hernanrivasacosta@gmail.com-

Gracias a PenHolder por el avatar los avatares.

HernanRivas


clabLevel: 2580 Genero:Masculino

1 Tutoriales
23 Tips

MP Email         
Volver arriba
Mensaje Publicado: Mie Mar 05, 2008 6:00 pm     Citar   firefox 
ES PEC TA CU LAR! Muy Feliz
Muchas gracias Hernán por tu tiempo, la amabilidad y la muy buena explicación!.

PD: Tan dificil era que Adobe ( ó MacroMedia ) lo incorpore como ( como se dice? ) comportamiento nativo ?. O simplemente no tuvieron ganas de agregarle esta funcionalidad Malvado ?
Saludos!

raxiro


clabLevel: 6



MP         
Volver arriba
Mensaje Publicado: Mie Mar 05, 2008 7:48 pm     Citar   firefox 
Alabanza

...AS3 no era tan complicado despues de todo
 _________________

I'm perfect in wickness

penHolder


clabLevel: 1778
| mdz |

19 Tips

MP Web     Google Talk    
Volver arriba
Mensaje Publicado: Jue Mar 13, 2008 2:41 pm     Citar   opera 
Tambien puedes hacerlo, haciendo que cuando se llama a la funcion drag, se calcule cuales son las 4 puntas de la pantalla.
Yo estuve horas haciendo ese codigo, para que cuando se "resize" la pantalla, tome los nuevos valores. y si cuando se "resiza" el objeto queda fuera de la pantalla, se centra.

Anonimato_blog
Invitado






        
Volver arriba
Responder al tema    Foros de discusión -> Tips, ¡Envía tus trucos aquí! Todas las horas son GMT
Página 1 de 1

Respuesta Rapida
Nick: 

  Citar el ultimo mensaje
Adjuntar tu firma

Mostrar mensajes de anteriores:
  

 


Cristalab BloodBerry Style © 2006 Cristalab
Powered by phpBB © 2001, 2002 phpBB Group