Flex: определить, отображается ли компонент - PullRequest
11 голосов
/ 17 января 2009

Как лучше всего определить, отображается ли компонент в Flex / Flash на экране пользователя? Я ищу аналог метода Java * Component.isShowing () .

События show и hide запускаются для наглядности, и, похоже, это работает для первого потомка компонента ViewStack, но не дальше по дереву отображения.

Ответы [ 5 ]

11 голосов
/ 11 марта 2009

... или избегая рекурсии:

public static function isVisible(obj:DisplayObject):Boolean
{
    while (obj && obj.visible && obj !== Application.application)
    {
        obj = obj.parent;
    }
    return obj && obj.visible;
}
7 голосов
/ 19 января 2009

Вы хотите проверить, является ли свойство компонента видимым истинным, и это для всех родителей вашего компонента в 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);
}
5 голосов
/ 17 января 2009

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

Я не сделал ничего, кроме тривиальных тестов по этому вопросу, но это должно помочь вам начать.

1 голос
/ 17 января 2009

Как ни странно, теперь, когда вы упомянули об этом, я не верю, что существует простой тест, чтобы определить, действительно ли компонент видим на экране в том смысле, который подразумевает 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>

... вы увидите события show и hide для каждого ярлыка, когда их видимые свойства будут привязаны к их родительским панелям ». Надеюсь, это иллюстрирует суть; Вы можете расширить его, однако лучше всего подходит для вашего приложения. Удачи!

0 голосов
/ 15 декабря 2010

Я пытался получить то же самое многоразовым способом. Я почти нашел способ с помощью getObjectsUnderPoint () - это возвращает объект в определенной точке, в z-порядке (даже если они не являются братьями и сестрами, например ViewStack, Всплывающие окна, 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;
}
...