Flex. Определите, отображается ли компонент.
Каков наилучший способ определить, отображается ли компонент в Flex/Flash на экране пользователя? Я ищу аналог Java метод Component.isShowing().
События show
и hide
срабатывают для видимости, и это, похоже, работает для первого потомка компонента ViewStack, но не дальше по дереву отображения.
Ответы
Ответ 1
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;
}
}
}
Я не делал ничего более, чем тривиальные тесты, но вам нужно начать.
Ответ 2
... или избежать рекурсии:
public static function isVisible(obj:DisplayObject):Boolean
{
while (obj && obj.visible && obj !== Application.application)
{
obj = obj.parent;
}
return obj && obj.visible;
}
Ответ 3
Вы хотите проверить, является ли свойство компонента видимым, и это относится ко всем родителям вашего компонента в 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);
}
Ответ 4
Как ни странно, теперь, когда вы упомянули об этом, я не верю, что есть простой тест, чтобы определить, действительно ли компонент отображается на экране в смысле 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>
... вы увидите шоу и скройте события для каждого ярлыка, как только их видимые свойства будут привязаны к их родительским панелям. Надеюсь, это иллюстрирует суть; вы можете расширить его, но лучше всего подходит для вашего приложения. Удачи!
Ответ 5
Я пытался получить то же самое в многоразовой манере. Я почти узнал способ использования getObjectsUnderPoint() - это возвращает объект под особой точкой z-упорядочен (даже если они не являются братьями и сестрами, например 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;
}