2009-01-16 9 views
11

¿Cuál es la mejor manera de determinar si un componente en Flex/Flash se muestra en la pantalla del usuario? Estoy buscando un método analógico para Java Component.isShowing().Flex: determine si un componente muestra

Los eventos show y hide se disparan para obtener visibilidad, y esto parece funcionar para el primer descendiente de un componente ViewStack, pero no más adelante en el árbol de visualización.

Respuesta

5

UIComponent.visible no es necesariamente válido para los elementos secundarios de un objeto donde visible = false. De los documentos:

"En cualquier caso, los elementos secundarios del objeto no emitirán un evento de mostrar u ocultar a menos que el objeto haya escrito específicamente una implementación para hacerlo."

Escribí una aplicación de muestra que confirma que esto es cierto. Lo que puede hacer es recorrer la lista de visualización para verificar que el falso sea visible en un padre. Básicamente, "visible" da falsos positivos pero no debe dar falsos negativos. Aquí es una utilidad rápida que arme:

package 
{ 
    import flash.display.DisplayObject; 

    import mx.core.Application; 

    public class VisibilityUtils 
    { 
     public static function isDisplayObjectVisible(obj : DisplayObject) : Boolean { 
      if (!obj.visible) return false; 
      return checkDisplayObjectVisible(obj); 
     } 

     private static function checkDisplayObjectVisible(obj : DisplayObject) : Boolean { 
      if (!obj.parent.visible) return false; 
      if (obj.parent != null && !(obj.parent is Application)) 
       return checkDisplayObjectVisible(obj.parent); 
      else 
       return true; 
     } 
    } 
} 

no he hecho nada más que pruebas triviales sobre esto, pero debe empezar.

+0

¿Hay alguna razón para parar en la aplicación y no sólo cuando los padres == null? –

+1

Parece recordar que la propiedad "principal" de la Aplicación podría ser un puntero a la misma instancia que causaría un bucle infinito. No estoy 100% seguro y no puedo confirmarlo fácilmente ya que no he estado haciendo ningún trabajo Flex desde hace un par de años. –

1

Por extraño que parezca, ahora que lo mencionas, no creo que haya una prueba simple para determinar si un componente es realmente visible en la pantalla en el sentido que Component.isShowing() implica.

También es cierto que los eventos de mostrar y ocultar no aparecen de forma predeterminada, por lo que si desea que se le notifiquen los cambios de visibilidad en un descendiente de un contenedor ViewStack, deberá escucharlos explícitamente. Los detalles de implementación variarían dependiendo de qué tipo de comportamiento que fueron después, pero para tomar el ejemplo sencillo:

<?xml version="1.0" encoding="utf-8"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> 
    <mx:VBox> 
     <mx:HBox> 
      <mx:Button id="btn1" click="vs.selectedIndex = 0" label="Show 1" /> 
      <mx:Button id="btn2" click="vs.selectedIndex = 1" label="Show 2" /> 
     </mx:HBox> 
     <mx:ViewStack id="vs" selectedIndex="0"> 
      <mx:Panel id="panel1"> 
       <mx:Label id="label1" text="Label 1" show="trace('showing label 1')" hide="trace('hiding label 1')" visible="{panel1.visible}" /> 
      </mx:Panel> 
      <mx:Panel id="panel2"> 
       <mx:Label id="label2" text="Label 2" show="trace('showing label 2')" hide="trace('hiding label 2')" visible="{panel2.visible}" /> 
      </mx:Panel> 
     </mx:ViewStack> 
    </mx:VBox> 
</mx:Application> 

... que van a ver el espectáculo y ocultar eventos para cada etiqueta de fuego una vez que sus propiedades visibles tienen sido obligado a sus paneles de padres '. Espero que eso ilustre el punto; puede ampliarlo, sin embargo, se adapta mejor a su aplicación. ¡Buena suerte!

7

Desea verificar si la propiedad del componente visible es verdadera y esto es para todos los elementos principales de su componente en la Lista de visualización, ¿estoy en lo correcto?

public static function isVisible(c : UIComponent) : Boolean { 
    if (c == null) return false; 
    if (c is Application) return c.visible; 
    return c.visible && isVisible(c.parent); 
} 
+0

Parece una buena mejora para mi código. Mucho más simple Bonito. –

+0

'Coerción implícita de un valor con tipo estático flash.display: DisplayObjectContainer posiblemente tipo no relacionado mx.core: UIComponent'. Deberías declarar 'c' como' DisplayObjectContainer'. –

11

... o evitar la repetición:

public static function isVisible(obj:DisplayObject):Boolean 
{ 
    while (obj && obj.visible && obj !== Application.application) 
    { 
     obj = obj.parent; 
    } 
    return obj && obj.visible; 
} 
+0

Si utiliza ventanas emergentes, Flex las crea en una lista de visualización diferente a la Aplicación, por lo que las pruebas de Application.application en la lista primaria no funcionarán. La etapa debe usarse en su lugar y funcionará en todos los casos. – Chris

0

yo estaba tratando de obtener la misma de una manera reutilizable .. casi me descubrió una manera usando getObjectsUnderPoint() - devuelve el objeto bajo un punto particolar, z-ordenado (incluso si no son hermanos, p. ej. ViewStack, Popups, ecc.).

Básicamente, obtengo el objeto de visualización superior debajo de un punto particular del escenario, luego voy a la jerarquía de objetos de visualización para encontrar el objeto probado. Si lo encuentro, el objeto es visible (los objetos no visibles en la jerarquía ya deben ser filtrados por la llamada getObjectsUnderPoint).

El problema aquí es que debe usar un punto no transparente de su objeto (en mi caso, utilicé un desplazamiento de 5 píxeles debido a los bordes redondeados), de lo contrario no será recogido por esta función.

¿Alguna idea para mejorar?

Cosma

public static function isVisible(object:DisplayObject):Boolean { 
    var point:Point = object.localToGlobal(new Point(5, 5)); 
    var objects:Array = object.stage.getObjectsUnderPoint(point); 
    if (objects.length > 0) { 
     if (isDescendantOf(object, objects[objects.length - 1] as DisplayObject)) { 
      return true; 
     } 
    } 
    return false; 
} 

public static function isDescendantOf(parent:DisplayObject, child:DisplayObject):Boolean { 
    while (child.parent != null) { 
     if (child.parent === parent) { 
      return true; 
     } else { 
      child = child.parent; 
     } 
    } 
    return false; 
} 
+0

¿No detectaría un componente como invisible si la esquina superior izquierda está cubierta por otro componente? –

+1

stage.getObjectsUnderPoint debe devolver una matriz de todos los objetos de visualización que tienen un punto "blitted" en esa posición, incluso si están cubiertos por otros objetos de visualización (esta es la razón por la que se devuelve una matriz en lugar de un único objeto). –

Cuestiones relacionadas