Comunidad de diseño web y desarrollo en internet online

Evitar que los popups salgan de la pantalla en Flex 3

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 :

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate