views:

586

answers:

5

how can i add an event listener to detect when the height of a DisplayObject changes.

i have a holding Sprite with a border that needs to resize when any object inside changes height or is added.

thanks.

Josh

+2  A: 
displayObject.addEventListener(ResizeEvent.RESIZE, onResize);

function onResize(event:ResizeEvent):void
{
    // handle it here
}
Vinay Sajip
A: 

Create the custom event class:

package com
{
    class ChildResizeEvent extends Event
    {
        public static var RESIZE:String = "resize";
        public static var ADDED:String = "added";
    }
}

In main Sprite MXML you can use this:

<mx:Metadata>
    [Event(name="onChildResize", type="com.ChildResizeEvent")]
</mx:Metadata>

Then when the event happens (When an object changes height or is added), you dispatch:

function onInteriorObjectHeightChange(event:Event):void
{
    dispatchEvent(new ChildResizeEvent(ChildResizeEvent.RESIZE));
}
CookieOfFortune
+2  A: 

i presume this is a flash and not a Flex question ... which is why mx.events.ResizeEvent (which is dispatched by UIComponent and subclasses) and all this kind of funky Flex stuff won't work ... if you do use Flex and UIComponents, it's the best way to go though ...

the problem is, that this event is not generated ...

  • you could subclass any builtin classes, override the accessors for width, height, x, y, scaleX, scaleY, transform and visible, to get most information ...
  • you would have to make sure, that any object is an instance of your custom classes ... you would not be able to use startDrag, since it bypasses the accessors ...
  • you really got practically NO chance to find out, if someone draws on a subobject ... Graphics is final ... except, overriding the getter and setting a timeout, when the getter is used, to check changes 1 msec later (and be sure you have 1 timeout at max) ...

this is more than dodgy, takes a lot of developement and debugging time, will be a pain in the ass, since you will have to make absolutely sure, everything (also any library symbol, if you use CS3/CS4 as i presume) ... and will eat up quite a chunk of performance due to all the events dispatched by your custom accessors ...

the most simple thing really, is to watch the width/height on enterframe and if they change from one frame to another, then redraw your border ... this makes much more sense, since you don't need to redraw the border more then once a frame, which is an effect that could very well occur, if you tried to capture any actions that could possibly mean resizing ... and really, comparing two floats is very cheap ... :)

hope that helped ...

back2dos
Monitoring is not a good idea. Suppose you have a visual list with hundreds of items. Storing and monitoring for change the sizes of hundreds of items is not efficient, compared with simply handling a single dispatched change event when/if it occurs. I would suggest that if you have objects that change size and need to report that size change, then write the classes to do just that... designate a way to change their size (width/height props for example), and commit to changing their sizes that way, and dispatch a resize event when their size is changed in the designated fashion.
Triynko
@Triynko: 1. OP has **one** Sprite. 2. Even **1000** Sprites will perform well. 3. It is far more robust and far easier to implement and maintain. 4. It will outperform event based alternatives if there are many simultaneous changes, since don't have tons of event instantiations and dynamic handler invocations (also you have O(1) function calls). 5. It can really track ALL changes ... in this and many other scenarios it is a very good idea. In a perfect world the player would dispatch a non-bubbling event for each DisplayObject that rerenders and this question would be moot. But life is tough.
back2dos
@back2dos: 1. # of sprites in container that may be added or change size is unspecified. 2. Depends on the machine. 3. No, it's not. A monitoring solution is inflexible, and individual objects couldn't be switched off. 4. It may outperform EventDispatcher, but it won't outperform a custom event based system. SO(whatever). It's push vs pull, no reason to pull info from 1000 objects per frame, remembering sizes and computing deltas if items are added occasionally. 5. Event-based can track ALL changes as well, and can be selective, allowing individual object's event dispatching switched off.
Triynko
@Triyonko: 1. he is tracking exactly one sprite, that needs to be resized if the content changes. 2. true, it does matter on some machines. These machines however will choke if they have to render 1000 sprites only once. 3. How so? You could switch off monitoring individual objects. And it IS far more robust, since you can't possibly forget to dispatch an event. 5. No, it simply can't. except if all changes are managed by you. But if someone just grabs your sprite and draws something onto it, or translates a child, you just can't.
back2dos
A: 

I don't know about Flex, but AS3 doesn't have a ResizeEvent.

Zeke
A: 

Thoughts

At first I was surprised the implementation of the DisplayObject class does not dispatch Event.RESIZE events when its width and height properties are changed or the size of the contents is recalculated, but it makes a lot of sense for performance reasons.

I thought about using the Event.RENDER event, but I was listening for it on a TextField that I was resizing like crazy through a script... and despite the text re-wrapping, and the box expanding and the cursor flashing... it NEVER fired a single RENDER event. Surprising, it only fires the RENDER event when the text is changed, which just shows how useless the RENDER event is.

Answer... focus on the circumstances or frequency with which you expect the DisplayObject to change size.

I suggest that you either:

  1. Dispatch Event.RESIZE events from any custom subclass of DisplayObject that you create. OR
  2. Use the Event.ENTER_FRAME event to monitor the width and height of any DisplayObject you expect to change dimensions.

Logically, the method you choose should depend on what you know about the DisplayObject's likelihood to change size:

  • If you expect it to change size unexpectedly (e.g. like a dynamic particle system)... then it makes sense to monitor its unpredictable dimensions with ENTER_FRAME, especially if you're certain it's dimensions are likely to change every frame.
  • Alternatively, if you know the object will resize only under particular conditions (e.g. during a TextField's Event.CHANGE event) or it's a class you created yourself... then YOU should know whether what you're doing might cause the size to change, and simply dispatch an Event.RESIZE event from your class.
Triynko