Flex:确定组件是否正在显示

时间:2009-01-16 22:56:51

标签: flex flash events components

确定Flex / Flash中的组件是否在用户屏幕上显示的最佳方法是什么?我正在寻找类似于Java的Component.isShowing()方法。

showhide事件触发可见性,这似乎适用于ViewStack组件的第一个后代,但不在显示树的下方。

6 个答案:

答案 0 :(得分:11)

...或避免递归:

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

答案 1 :(得分:7)

您想检查组件属性是否为true,这是否适用于DisplayList中组件的所有父项,我是否正确?

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);
}

答案 2 :(得分:5)

UIComponent.visible对于visible = false的对象的子节点不一定有效。来自文档:

“在任何一种情况下,对象的子节点都不会发出show或hide事件,除非该对象专门编写了一个实现来执行此操作。”

我写了一个示例应用程序,确认这是真的。你可以做的是走上显示列表检查父母可见是否为假。基本上“可见”会产生误报,但不应该给出假阴性。这是我放在一起的快速实用程序:

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;
        }
    }
}

我没有做过比这更简单的测试,但它应该让你开始。

答案 3 :(得分:1)

看起来很奇怪,现在您提到它,我不相信有一个简单的测试来确定组件在屏幕上是否实际上是可见的,在Component.isShowing()意味着。

默认情况下,show和hide事件不会冒泡,因此如果您希望在ViewStack容器的后代中收到可见性更改的通知,则需要明确地监听它们。实现细节会根据您的行为类型而有所不同,但举一个简单的例子:

<?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>

...一旦将其可见属性绑定到其父面板,您将看到每个标签的显示和隐藏事件。希望这说明了这一点;你可以扩展它,但最适合你的应用程序。祝你好运!

答案 4 :(得分:0)

我试图以可重用的方式获得相同的东西。我几乎找到了一种使用getObjectsUnderPoint()的方法 - 这会返回一个特定点下的对象,z-ordered(即使它们不是兄弟,例如ViewStack, Popups,ecc。)。

基本上,我在舞台的特定点下获得最顶层的显示对象,然后在显示对象层次结构上查找测试对象。如果我找到它,该对象是可见的(层次结构中不可见的对象应该已经被getObjectsUnderPoint调用过滤掉了。)

这里的问题是你必须使用对象的非透明点(在我的情况下,由于边缘的边界,我使用了5像素的偏移),否则它将不会被此函数拾取。

有什么改进的想法吗?

卡斯马

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;
}

答案 5 :(得分:0)

这就是您真正需要的。 “ Application.application”检查是徒劳的。

        /**
         * Returns `true` if this component is actually shown on screen currently. This could be false even with
         * "visible" set to `true`, because one or more parents could have "visible" set to `false`.
         */
        public static function isShowing (c : DisplayObject) : Boolean {
            while (c && c.visible && c.parent) {
                c = c.parent;
            }
            return c.visible;
        }