I have 1 class (that is extending a UIcomponent) that is representing a component. In that component I create different instances of another class that is also a UIComponent but this class doesn't show up in de first class. I see that it is running and that it has the correct hights but I got the feeling that it doesn't show up with this hights. If I trace I see the width and height is 200 X 200 but there is still nothing visible in my component
I bet there is a simple solution for this problem?
If extending UIComponent directly, you have to make sure to override all the right methods, including createChildren, updateDisplayList, and measure. If you miss any of those it won't work.
Remember to addChild in createChildren, to set x, y, width, and height in updateDisplayList, and to set your own measured properties in measure.
"Fixing" it by "setting everything in one UIComponent" is probably not the right idea.
That said, it's usually A LOT easier to just put stuff into a canvas instead of extending UIComponent. Everything will show up by default, and you don't have to override anything. I only extend UIComponent when I'm doing something really fancy or I want custom control
Related
If I skin a button and use the AS3 graphice.clear() and graphics.lineTo and beginFill to create a shape, the button overlaps other items in the container.
When I use the and mxml to create the same shape, the button is neatly positioned inside the container.
Why is that?
This is probably happening because Flex is unable to calculate the size of your dynamically drawn button, while the MXML version allows the size to be calculated prior to being displayed. You may need to override the measure method to calculate the width/height. If that's not the issue, then post some code so we can take a closer look. Hope that helps.
Because the Line Object is doing a bunch of checks and extra work you aren't doing when you use the Graphics object. Look at the code for spark.primitives.Line to see what its doing that you aren't.
I have custom components which must adjust their text content based on space constraints. For example a component adds labels until there is no space, and then the content of the last label becomes "(x more)"
I do not have access to size of child controls before adding them. When in updateDisplayList, I make changes to the layout of the component, but for labels, lblInstance.text property fires events, which lead to updateDisplayList being called again. I know that updateDisplayList may be called more than once, but if there is a way to modify text without triggering events, that'd be really useful. For example, setActualSize method in UIComponent allows this kind of modification.
Anything similar for text controls? Or do you have best practices for laying out and managing text content, in the context of custom Flex components?
Best Regards
Seref
Use the measure() method to set your text component sizes.
You will probably have to call validateNow() on them so that they will be forced to figure out the actual textWidth and textHeight and return the actual number of lines of text in the textField if they are long enough to wrap. Investigate the TextMetrics class for more ways to measure.
I want to create an MXML container component that has some of its own chrome -- a standard query display, et al -- and that supports the addition of child components to it. Something a lot like the existing mx:Panel class, which includes a title label, but acts like a plain mx:Box with regards to adding children.
What's the easiest way to do this?
Edit:
To be clear, I want to be able to extend the container using MXML, so the "Multiple visual children" problem is relevant.
Extend a container and add a title label. Probably the <mx:Canvas/> will work here. Make the title a public var and include a var for the styleName of the label.
Then override the addChild() method so that any child that is added is added instead to the that is your container.
Leave enough space for your title when you position your Box element (i.e., give its y property enough space. If there is no title you may want to reclaim that space.
That's the basics. Customize to your heart's content.
EDITED TO ADD: I do this creating an ActionScript class first, extending the container I am targeting, and I add the "furniture" — items the class will always use, like title in your case — by overriding createChildren and calling super.addChild(item) for those items. Calling addChild from then on, even in MXML markup, adds items to the inner container.
We do this with states.
We put the chrome for the base container in a state (in mx:AddChild elements) and then use the initialize event to switch to that state when the control is created. All the chrome is then added to the container.
That gets round the multiple sets of visual children problem.
The downsides to this approach are:
You don't see the chrome when editing descendents of the base.
You can't directly access the parent chrome controls from descendent components as they are not there at compile time (instead, you need to define properties, methods or events on the base that the descendents can access)
However, it works well for us.
I've created a AS3 class which extends UIComponent so that I can easily add it to my MXML layout. It works fine, but I'm trying to figure out how to update the UIComponent width and height dynamically. I want my super UIComponent to draw a border around the content, so I need get the specific 'content' dimensions in order to do this.
I understand the idea of UIComponent is that you are supposed to specifically set the width and height... but I am literally only extending it so that I am able to use my custom component with MXML easily.
Is there a method in which I can get the width and height of a UIComponents 'content'?
Thanks
Like Robusto described in his comment, the Canvas is probably a better choice if you're trying to add children to it. The Canvas instantiates a CanvasLayout, which handles all the complex logic for sizing itself and children.
The width and height of a UIComponent's content is determined in the measure() method, unless the UIComponent has explicit or percent sizes defined. Measure is one of those methods that aren't well documented. I suggest Diving Deep into the Flex Component Lifecycle with EffectiveUI. They go into the lifecycle methods and really explain how to use them.
The measure() method is called if the parent (your component) doesn't have any sizing defined. Then it goes through all of its children, calculates their sizes, and sums them up into measuredWidth and measuredHeight. The parent's sizes are then set to those values.
If you extend UIComponent, you have to do a lot in the measure method to handle all the edge cases: explicit, percent, constraints (top, left...), padding, whether or not includeInLayout = true, etc. Canvas does all that. Same with the other container components: Box, HBox, VBox, List, etc.
Hope that helps,
Lance
Not sure what you mean by the "content" of your UIComponent. Do you mean the UIComponent's dimensions, or a child container's?
One place you can look for the size of any component is in its updateDisplayList method, which is a protected method you would have to override, as so:
override protected function updateDisplayList(width:Number, height:Number) {
super.updateDisplaylist(width, height);
// your statements here
}
You say you are extending UIComponent only so that you are able to use your custom component "with MXML easily." But you still need to extend it as much as you need to in order to do what you need to do. For that you should learn about the lifecycle of a component, when to overrwrite the createChildren(), commitProperties(), measure() and other methods, and so on. It's really not hard, and you've already taken the first step. Good luck!
What is the best way to change/set a registration point on a Flex 3 display object? I know this isn't really built in to easily change, but does anyone have any suggestions on how I could extend UIComponent to achieve this?
For some reason, the Flash Player API doesn't expose the registration point of DisplayObjects (and the Flash IDE makes them a pain to modify once an object is created). The best solution, as David pointed out, is to add your component as a child of another component (UIComponent would be fine). So, for example, if I had a Button and I wanted its registration point at its center, I'd add it as a child of a UIComponent (not Canvas) and offset the child by setting its position to (-button.width/2, -button.height/2).
Put your DisplayObject inside a sprite and set the DisplayObject's x & y positions to the negitive of your target registration point. Apply all transforms to the Sprite container.
Put it inside a Canvas container, with its clipContent attribute set to false. Within the canvas, you can put your object wherever you like.