Flex dynamic form height - apache-flex

I'm not sure if this is possible, is there a way to get the <mx:Form> to set its own height based on the position of an element within it?
For example something like this:
<mx:Form height="{submitBtn.y + submitBtn.height}">
<mx:FormItem>... </mx:FormItem>
<mx:FormItem>... </mx:FormItem>
<mx:FormItem>... </mx:FormItem>
<mx:FormItem>
<s:Button id="submitBtn" label="Submit" />
</mx:FormItem>
</mx:Form>
where the form height is dynamically set based on submitBtn's y position and its height.
I tried using Alert.show to show these values and turned out submitBtn.y = 0 and submitBtn.height = 21. height sounds reasonable, but I know the submitBtn.y can't be 0 since it's below several other
Is it possible to set the form height dynamically?

Yes. Do it in the measure method:
private var n:Number = 0;
override protected function measure() : void {
super.measure();
if (submitBtn) {
var fi:FormItem = FormItem(submitBtn.parent);
n = fi.y + fi.height;
}
}
Then just set the height to n.
Edit: I changed this to specify the containing FormItem, not the button, which is what I tested in my own sample code first. You can either get the button's parent or give that FormItem an ID. But this way does work.

your submitBtn.y will always return 0, since it's the y position inside the mx:FormItem element (like the relative y position)
So as I guess you want to set the y position of a form based of the y position of a button inside the form. why do you want that ?

check out the localToGlobal() method available to all children of DisplayObject. It will convert your x,y coordinates to the global x,y. You should be able to use this in your calculations.

I hope that thread is not closed cause I just have had the same problem like you and found the correct solution, so I will try to explain.
Whenever my application starts it reads a file and parse it, containing some information that will fit some forms, and I create them dynamically without specificating any height or width.
I add them to a viewStack like this:
<mx:ViewStack id="viewStack" resizeToContent="true">
</mx:ViewStack>
that is inside a component to show Information for some items, depending the class of the item one of the form is shown fitting the necessary information in.
As you can notice, the viewstack has inside a property resizeToContent that when I select an item from a datagrid, the viewstack changes the selectedIndex (indicating another form) and automatically changing its size resizing to the new content.
If for some reason you need the height of the form, you can use, instead of measure(), the measuredHeight property.
I will add some of the code used for you to understand:
onCreationComplete(){
...
for each (var form:Form in DataModel.getForms())
{
viewStack.addChild(form);
}
...
}

Related

How to prevent truncating the bottom of text in Flex comboboxes?

I am currently modifying a flex GUI to give it a new look. I am new to flex but I manage to get most of the work done. However I have a problem with comboboxes: I use a rather big font size and the bottom of some characters is truncated ("g" for example, or any character going under the baseline):
I first thought it was a problem with the component height, but even with a very large height the characters got truncated, with big empty spaces above and under the text.
I looked for a solution on the net but did not find one. Worst: I was not able to find references to my problem though it seems to be an important one. Is there a CSS property to prevent this behavior or do I have to look elsewhere?
edit: I use Flex 3 and Halo/MX components
The combobox component contains an inner TextInput. You have to extend the ComboBox class and modify the height of the textinput to what you need.
For example, lets say you put a font size of 20 and this extended class:
public class MyCb extends ComboBox
{
public function MyCb()
{
addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
}
private function onCreationComplete(e:Event):void {
this.textInput.height = 40;
}
}
Main application:
<mx:VBox width="100%" height="100%">
<mx:ComboBox fontSize="20" >
<mx:dataProvider>
<mx:Object label="goubigoulba"/>
<mx:Object label="goubigoulba"/>
</mx:dataProvider>
</mx:ComboBox>
<local:MyCb fontSize="20" >
<local:dataProvider>
<mx:Object label="goubigoulba"/>
<mx:Object label="goubigoulba"/>
</local:dataProvider>
</local:MyCb>
</mx:VBox>
You will get the following result:
I believe that this is not the Comobox itself, but its internal label. You can try setting paddingBottom, to see if the label will inherit that, but you might have better luck creating your own subClass of label and using it as the textFieldClass.

Flex 4 UIMovieClip Modify the Width of a Child DisplayObject

I have a collection of UIMovieClip components which reside in an s:HGroup tag. In ActionScript code I am modifying the width of a child clip in one of the UIMovieClips but these changes are not reflected by the s:HGroup.
<s:HGroup id="_buttonGroup">
<uiassets:NavigationTabButtonSWC id="_lobby" />
<uiassets:NavigationTabButtonSWC id="_achievements" />
</s:HGroup>
<fx:Script>
<![CDATA[
protected function init() : void
{
// The HGroup does not pickup this change and so my buttons
// are no longer evenly spaced out and overlap!
_lobby.getChildByName("background").width += 200;
}
]]>
</fx:Script>
Thanks!
There's a few reasons for this. Just changing one child's width doesn't mean it'll change the whole UIMovieClip's width, so you should check that first.
Second, Flex has a very specific way of doing things (called the component lifecycle), which the UIMovieClip doesn't implement so you can't manage the width yourself in the 'measure' function. I'm guessing that you just have other children in your movieclip that doesn't let you resize it all. Try changing the width of the MovieClip itself and it should work. If it doesn't, then there's another problem.

Flex 3 UITextField Layout Problem

I'm using Flex 3, SDK 3.2.
I'm having problems determining the height of a UITextField. (Unfortunately, I have to use the UITextField because I'm using FlashEff 2.0. Otherwise, I'd use a different component).
I've got a UITextfield that is multiline and has wordWrap. The text is pulled from a database, so the length varies. I've got a radioButtonGroup underneath the UITextField.
My goals are:
To keep the UITextField from
crashing into the radioButtonGroup's
VBox.
To change the y
position of the radioButtonGroup
based on the height of the
UITextField.
To make the TitleWindow's
height variable. The
UITextField and the radioButtonGroup
are in a TitleWindow. I'd like to
change the height of the TitleWindow
based on the contents inside.
At the moment, I've set y of the  radioButtonGroup way down on the TitleWindow, so that the UITextField's content doesn't overlap. But, when there isn't too much text in the UITextField, I get a huge gap between the radioButtonGroup's VBox and it.
If I don't give the TitleWindow a height, then the UITextField will stretch itself to something like 2000 px.
I've Googled and from what I can tell, the UITextField's height behaves weirdly.
Does anyone know how to solve this problem?
I create the UITextField like this:
 
public var tf:UITextField = new UITextField;
     
tf.autoSize = TextFieldAutoSize.LEFT;
     tf.embedFonts = true;
     tf.multiline = true;
     tf.text = myText;
     tf.width = 440;
     tf.wordWrap = true;
     var myFormat:TextFormat = new TextFormat;
     myFormat.size = 25;
     myFormat.blockIndent=53;
     this.addChild(tf);
     tf.validateNow();
     tf.setTextFormat(myFormat);
 
 
My VBox looks like this:
<mx:VBox  id="radioVBox" x="180" y="220">
     <mx:RadioButtonGroup id="myRadioButtonGroup" itemClick="goClickHandler(event);"/>
     <mx:RadioButton  groupName="myRadioButtonGroup" label="A"  fontSize="17" />
     <mx:RadioButton  groupName="myRadioButtonGroup" label="B"  fontSize="17" />
     <mx:RadioButton  groupName="myRadioButtonGroup" label="C"  fontSize="17" />
     <mx:RadioButton  groupName="myRadioButtonGroup" label="D"  fontSize="17" />
     <mx:RadioButton  groupName="myRadioButtonGroup" label="E"  fontSize="17" />
 
And it's all wrapped in a TitleWindow that looks like this:
 
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
     layout="absolute"
     width="520" 
     height="450"
     verticalScrollPolicy="off"
     horizontalScrollPolicy="off"
>
Any suggestions?
Thank you.
-Laxmidi
rtalton helped me out.
I figured out that the radioVBox was shifting up and overlapping the MainBox, because the UITextField is dynamic and has a FlashEff2 effect on it. Basically, the height of the MainBox is 0 when radioVBox's layout is calculated.
So, I add the UITextField to one VBox. Below that I've got the radioVBox. I set the radioVBox's visibility to false. Then I added an eventListener for when the FlashEff2 effect ended, which called a function that turned on the radioVBox's visibility. Also, in the function I set: radioVBox.y = (tf.y + tf.height + 40);. Lastly, I set the TitleWindow's height as follows: height="{radioVBox.y + 270}"
Thank you.
-Laxmidi

Flex: How do I space out items in a HorizontalList control (using a custom ItemRenderer)

I have a HorizontalList control that uses a custom ItemRenderer to represent each item as a toggle-button. The list allows drag and drop, and I used this method to rotate the drop feedback (line) into a vertical position instead of horizontal, but with the buttons mashed together, the drop feedback is pretty subtle. I'd like to space out the buttons somehow, so that the drop feedback is more obvious.
I've looked through the properties and nothing stands out. There are padding and margin properties, but their descriptions say they affect the list control itself, not the items.
Below is the code of my ItemRenderer. I've added padding to it, but that doesn't seem to change anything. If I add padding, that affects the inside of the button, not the space between them, and the button control doesn't have margin properties.
I suppose I could base my ItemRenderer on a canvas in order to get a margin, but then I wouldn't inherit all of the functionality of a button.
<?xml version="1.0" encoding="utf-8"?>
<mx:Button
xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="go();"
toggle="true"
>
<mx:Script>
<![CDATA[
private var _val:int = -1;
private function go():void {
this.label = data.title;
_val = data.index;
}
override protected function clickHandler(event:MouseEvent):void{
//todo: bubble an event that causes all other
//buttons in the list to un-toggle
//now do the default clickHandler
super.clickHandler(event);
}
]]>
</mx:Script>
</mx:Button>
How about writing your item renderer as a container (either Canvas or HBox) and placing the Button element inside?
Make a custom skin for your buttons that includes the spacing you need. You may need to combine it with padding styles to ensure that text or icons don't go outside the skin.
It's a bit on the hacky side, but you can also lie about your columnWidth for the actual HorizontalList object. Set it to something larger than your actual itemRenderer width.

Flex: Custom Item Renderer For Combobox controls truncates text

I've implemented a custom item renderer that I'm using with a combobox on a flex project I'm working on. It displays and icon and some text for each item. The only problem is that when the text is long the width of the menu is not being adjusted properly and the text is being truncated when displayed. I've tried tweaking all of the obvious properties to alleviate this problem but have not had any success. Does anyone know how to make the combobox menu width scale appropriately to whatever data it's rendering?
My custom item renderer implementation is:
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
styleName="plain" horizontalScrollPolicy="off">
<mx:Image source="{data.icon}" />
<mx:Label text="{data.label}" fontSize="11" fontWeight="bold" truncateToFit="false"/>
</mx:HBox>
And my combobox uses it like so:
<mx:ComboBox id="quicklinksMenu" change="quicklinkHandler(quicklinksMenu.selectedItem.data);" click="event.stopImmediatePropagation();" itemRenderer="renderers.QuickLinkItemRenderer" width="100%"/>
EDIT:
I should clarify on thing: I can set the dropdownWidth property on the combobox to some arbitrarily large value - this will make everything fit, but it will be too wide. Since the data being displayed in this combobox is generic, I want it to automatically size itself to the largest element in the dataprovider (the flex documentation says it will do this, but I have the feeling my custom item renderer is somehow breaking that behavior)
Just a random thought (no clue if this will help):
Try setting the parent HBox and the Label's widths to 100%. That's generally fixed any problems I've run into that were similar.
Have you tried using the calculatePreferredSizeFromData() method?
protected override function calculatePreferredSizeFromData(count:int):Object
This answer is probably too late, but I had a very similar problem with the DataGrid's column widths.
After much noodling, I decided to pre-render my text in a private TextField, get the width of the rendered text from that, and explicitly set the width of the column on all of the appropriate resize type events. A little hack-y but works well enough if you haven't got a lot of changing data.
You would need to do two things:
for the text, use mx.controls.Text (that supports text wrapping) instead of mx.controls.Label
set comboBox's dropdownFactory.variableRowHeight=true -- this dropdownFactory is normally a subclass of List, and the itemRenderer you are setting on ComboBox is what will be used to render each item in the list
And, do not explicitly set comboBox.dropdownWidth -- let the default value of comboBox.width be used as dropdown width.
If you look at the measure method of mx.controls.ComboBase, you'll see that the the comboBox calculates it's measuredMinWidth as a sum of the width of the text and the width of the comboBox button.
// Text fields have 4 pixels of white space added to each side
// by the player, so fudge this amount.
// If we don't have any data, measure a single space char for defaults
if (collection && collection.length > 0)
{
var prefSize:Object = calculatePreferredSizeFromData(collection.length);
var bm:EdgeMetrics = borderMetrics;
var textWidth:Number = prefSize.width + bm.left + bm.right + 8;
var textHeight:Number = prefSize.height + bm.top + bm.bottom
+ UITextField.TEXT_HEIGHT_PADDING;
measuredMinWidth = measuredWidth = textWidth + buttonWidth;
measuredMinHeight = measuredHeight = Math.max(textHeight, buttonHeight);
}
The calculatePreferredSizeFromData method mentioned by #defmeta (implemented in mx.controls.ComboBox) assumes that the data renderer is just a text field, and uses flash.text.lineMetrics to calculate the text width from label field in the data object. If you want to add an additional visual element to the item renderer and have the ComboBox take it's size into account when calculating it's own size, you will have to extend the mx.controls.ComboBox class and override the calculatePreferredSizeFromData method like so:
override protected function calculatePreferredSizeFromData(count:int):Object
{
var prefSize:Object = super.calculatePrefferedSizeFromData(count);
var maxW:Number = 0;
var maxH:Number = 0;
var bookmark:CursorBookmark = iterator ? iterator.bookmark : null;
var more:Boolean = iterator != null;
for ( var i:int = 0 ; i < count ; i++)
{
var data:Object;
if (more) data = iterator ? iterator.current : null;
else data = null;
if(data)
{
var imgH:Number;
var imgW:Number;
//calculate the image height and width using the data object here
maxH = Math.max(maxH, prefSize.height + imgH);
maxW = Math.max(maxW, prefSize.width + imgW);
}
if(iterator) iterator.moveNext();
}
if(iterator) iterator.seek(bookmark, 0);
return {width: maxW, height: maxH};
}
If possible store the image dimensions in the data object and use those values as imgH and imgW, that will make sizing much easier.
EDIT:
If you are adding elements to the render besides an image, like a label, you will also have to calculate their size as well when you iterate through the data elements and take those dimensions into account when calculating maxH and maxW.

Resources