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):
Toma la coordenada X del cursor al momento de hacer click y le resto la posición de la pantalla.
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:
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.
ES PEC TA CU LAR! 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 ? Saludos! Por:raxiro
...AS3 no era tan complicado despues de todo Por:penHolder
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. Por:Anonimato_blog