确定 Flex/Flash 中的组件是否显示在用户屏幕上的最佳方法是什么?我正在寻找 Java 的Component.isShowing()方法的类似物。
和事件触发可见性show
,hide
这似乎适用于 ViewStack 组件的第一个后代,但不适用于显示树的下方。
确定 Flex/Flash 中的组件是否显示在用户屏幕上的最佳方法是什么?我正在寻找 Java 的Component.isShowing()方法的类似物。
和事件触发可见性show
,hide
这似乎适用于 ViewStack 组件的第一个后代,但不适用于显示树的下方。
...或避免递归:
public static function isVisible(obj:DisplayObject):Boolean
{
while (obj && obj.visible && obj !== Application.application)
{
obj = obj.parent;
}
return obj && obj.visible;
}
您想检查组件属性 visible 是否为真,这适用于 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);
}
UIComponent.visible 不一定对可见 = false 的对象的子对象有效。从文档:
“在任何一种情况下,对象的孩子都不会发出显示或隐藏事件,除非该对象专门编写了一个实现来这样做。”
我编写了一个示例应用程序来确认这是真的。你可以做的是在显示列表中检查 parent 上的 visible 是否为假。基本上“可见”会给出误报,但不应给出误报。这是我整理的一个快速实用程序:
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;
}
}
}
我没有做任何比这更琐碎的测试,但它应该让你开始。
看起来很奇怪,既然你提到了它,我不相信有一个简单的测试来确定组件在 Component.isShowing() 所暗示的意义上是否真的在屏幕上可见。
默认情况下显示和隐藏事件也不会冒泡,因此如果您想在 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>
...一旦它们的可见属性绑定到它们的父面板,你就会看到每个标签的显示和隐藏事件。希望这能说明这一点;您可以扩展它,但最适合您的应用程序。祝你好运!
我试图以可重用的方式获得相同的东西。我几乎找到了一种使用 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;
}
这就是你真正需要的。“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;
}