Flex:确定一个组件是否显示了

问题描述 投票:11回答:6

怎样才能确定FlexFlash中的某个组件是否显示在用户的屏幕上? 我正在寻找一个类似于Java的 Component.isShowing() 方法。

showhide 事件发射的可见性,这似乎对ViewStack组件的第一个后裔有效,但对更进一步的显示树无效。

apache-flex flash events components
6个回答
5
投票

UIComponent.visible不一定对一个对象的子对象有效,其中visible=false。从文档中可以看出,"在任何一种情况下,UIComponent.visible的子代都是有效的。

"在任何一种情况下,对象的子代都不会发出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;
        }
    }
}

我还没有做任何更多的测试 但它应该能让你开始使用.


12
投票

... 或避免递归。

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

7
投票

你要检查组件的可见属性是否为真 这是对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);
}

1
投票

看起来很奇怪,既然你提到了,我不相信有一个简单的测试来确定一个组件是否真的在屏幕上可见,在Component.isShowing()暗示的意义上。

另外,默认情况下,显示和隐藏事件确实不会冒泡,所以如果你想在ViewStack容器的子代中得到可见性变化的通知,你需要明确地监听它们。 具体的实现细节会根据你想要的行为而有所不同,但以简单的例子来说,你会发现......你会看到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>

...你会看到每个标签的显示和隐藏事件会在它们的可见属性被绑定到它们的父面板上后被触发。 希望这能说明问题,你可以根据你的应用情况进行扩展。 祝您好运


0
投票

我试图以一种可重用的方式获得同样的东西。我几乎找到了一个使用getObjectsUnderPoint()的方法--这将返回一个particolar点下的对象,按z顺序排列(即使它们不是兄弟姐妹,例如ViewStack、Popups等)。

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

这里的问题是,你必须使用对象的非透明点(在我的例子中,由于边框比较圆,我使用了5个像素的偏移),否则它将不会被这个函数接收。

有什么办法可以改善这个问题吗?

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
投票

这是你真正需要的。"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;
        }
© www.soinside.com 2019 - 2024. All rights reserved.