Fluid layout of text in Flex3 - apache-flex

In my Flex3 app I have some floating windows which contain variable amounts of text. The windows are meant to be user-resizable. Currently, while I can resize the windows OK, I can't get the text in a TextArea in the window to re-flow when the window is resized. I've come across blog postings that there's a size bug in TextArea that means that setting the text content does not re-size the TextArea properly, together with suggested workarounds. In my case, the content stays the same but the geometry of the container changes. What seems to be happening is that the TextArea adopts a fixed size when it is first rendered, and no amount of resizing the container changes that. Can anyone suggest a means of creating a fluid text area in Flex?
Ian

By binding the textArea's width to its container's with, you can manage to keep the margins and borders and don't have to deal with percentages.
Also, your textArea will be resized each time its parent changes in size.
i'm thinking of something like this:
<fx:Script>
<![CDATA[
import spark.layouts.supportClasses.LayoutBase;
protected function onButtonClicked(event:MouseEvent):void
{
currentState = (event.target.selected ? 'largeState' : 'smallState');
}
]]>
</fx:Script>
<s:TitleWindow id="window" width="300" height="200">
<s:TextArea width="{window.width - 10}" height="{window.height - 60}"
text="{IMyConsts.LOREMIPSUM}" borderVisible="false" />
<s:ToggleButton id="btnEffect" bottom="5" click="onButtonClicked(event)"
label="{btnEffect.selected ? 'Go smaller' : 'Go larger'}" />
</s:TitleWindow>
<s:states>
<s:State name="smallState" />
<s:State name="largeState" />
</s:states>
<s:transitions>
<s:Transition fromState="smallState" toState="*">
<s:Resize target="{window}" widthTo="400" heightTo="300" />
</s:Transition>
<s:Transition fromState="largeState" toState="*">
<s:Resize target="{window}" widthTo="300" heightTo="250" />
</s:Transition>
</s:transitions>

I found a great example of fluid windows please do visit it. They provide source code also so may be you would get better idea.
http://examples.adobe.com/flex3/devnet/dashboard/main.html

You could try Text Layout Framework from Adobe:
http://labs.adobe.com/technologies/textlayout/

I can take a whack at this... but don't laugh..
I am not sure if you need to use a particular container but in any event, set the width and height to 100% and use Grid > GridRow and GridItem to size and resize Text Control you can specify the width of the table or just use it just like an HTML table in Flex to manipulate the size of controls and containers....
hope that helps...

Related

How to add margin for a button in Flex

In my Flex application I have a button with the following declaration placed above a custom data-grid component.
<mx:Button id="resetButton" label="Reset" visible="true" />
The button is now placed just above the grid and I would need to move it a few pixels higher so that there is a little space between them.
I noticed that there is a paddingBottom attribute for the Button component but no marginBottom equivalent.
I could not find any advice on Google. What is the correct way to achieve this?
EDIT:
The bottom property did not have any effect in my case (perhaps due to the layout we used) so I ended up surrounding the Button with a new VBox component like this:
<mx:VBox paddingBottom="5">
<mx:Button id="resetButton" label="Reset" visible="true" />
</mx:VBox>
you can use top, bottom, left, right attribute instead of marginTop, marginBottom, marginLeft, marginRight. The function of top is same as marginTop
<mx:Button id="btnSave"
top="50"
bottom="50"
left="50"
right="50"
click="btnSave_clickHandler(event)"
label="SAVE to File" />
May this will help you.
It sounds like your button and grid are already in a VBox. If that is the case, you can simply add a spacer after the button. It is much more lightweight than surrounding a single button with a VBox.
<mx:Spacer height="5"/>

Placing Flex-component in the middle of the screen

I have a very general question and have prepared a simple test case.
When using BasicLayout (i.e. absolute positioning) - what is the best approach to place a Flex component in the center of the application?
In the test case below I'm using x="{width/2}" but this gives me at least 2 problems:
How do I account for the component dimensions (the ProgressBar in the test case)?
Is the binding {width/2} a good idea to use? Wouldn't it send unnecessary DATA_CHANGE events in some cases?
And finally I wonder, how this all applies to full screen applications using StageScaleMode.SHOW_ALL - because currently my application is aligned to the top-left in the full screen mode and there is a white dead zone on the right of it. (Which is at least a change from pure Flash/AS3 behaviour, where the full screen content is displayed in the center of the screen and 2 dead zones on the left and right).
<?xml version="1.0" encoding="utf-8"?>
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="700" height="525"
backgroundColor="#CCFFCC"
initialize="systemManager.stage.scaleMode=StageScaleMode.SHOW_ALL">
<fx:Script>
<![CDATA[
private function fullScreen(event:MouseEvent):void {
stage.displayState =
stage.displayState == StageDisplayState.NORMAL ?
StageDisplayState.FULL_SCREEN :
StageDisplayState.NORMAL;
}
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="connected" />
</s:states>
<s:CheckBox right="10" bottom="10"
label="Full screen"
click="fullScreen(event)" />
<mx:ProgressBar indeterminate="true"
x="{width/2}" y="{height/2}"
label="Connecting..." labelPlacement="center"
includeIn="normal" />
</s:Application>
Way easier than that: just use horizontalCenter and verticalCenter properties of UIComponent. When used inside a BasicLayout the component will always be centered. Like this:
<mx:ProgressBar indeterminate="true"
horizontalCenter="0" verticalCenter="0"
label="Connecting..." labelPlacement="center" />
If you give these properties a value other than '0' the component will be offset from the middle by the amount of pixels you specify as a value. (e.g. horizontalCenter="50" will offset the component 50 pixels to the right of the center of the parent component)
That white space is probably due to your usage of systemManager.stage.scaleMode=StageScaleMode.SHOW_ALL. Just remove that line. Why are you doing that anyway?
edit
Just noticed you're using a fixed 'width' and 'height' on your Application: you'll have to make those '100%' if you want your app to really fill the screen. This is another possible cause for that white space.
To get your application centered (rather than left/right aligned) when using systemManager.stage.scaleMode=StageScaleMode.SHOW_ALL, set systemManager.stage.align to the empty string - i.e.:
// in your Application creationComplete handler
systemManager.stage.scaleMode = StageScaleMode.SHOW_ALL;
systemManager.stage.align = "";
I typically do 2 things,
I place objects inside VGroups/HGroups with alignment, I also use relative widths eg percentages.
Think like in the old days of using HTML tables. It works very well especially if your canvas is resized allot.
All of my canvases have to be resizeable as I like to only write my apps once, for pc, mobile etc, so I just make everything scalable by default.

Flex state transition that resizes a TitleWindow by animating

I have a title window based component in Flex 4 that has two states: A & B.
The title window is wider in state B.
I want the title window to animate when I switch states by using the Resize effect to widen the component.
What's the correct way to do this? Should define state specific width for the component or should I just run a transition effect that does this? The first option seems cleaner to me, but I can't figure out how to tell flex to use an effect and figure out by itself how much to resize the component..
Assaf, You can use tween, Parallel, Move and Resize properties for the same.
I implemented something similar to your request: I needed to add a transition effect, (Resize effect), between two states included in a TitleWindow component. This is how I did it:
My two states:
<s:states>
<s:State name="State1"/>
<s:State name="myInfoState"/>
</s:states>
My transition effect:
<s:transitions>
<s:Transition id="myTransition" fromState="*" toState="myInfoState">
<s:Parallel target="{this}">
<s:Resize duration="400"/>
</s:Parallel>
</s:Transition>
</s:transitions>
Note the {this} property. This is because my TitleWindow doesn't have an id.
Finally, you just need to call your currentState declaration as always:
<s:Button click="currentState = 'myInfoState'"/>
I guess that the keyword is {this} instead of the element's id.
Greetings from Pachuca, México!

actionscript flex, how to send browser width to the swf itself

I'm working with flex, but actionscript ideas are just as good.
The flex <s:Application> tag has height="100%" width="100%" so the swf fits the browser as the browser gets resized.
My problem is that I have a <s:Label> that I need to position based on the real/current size of the browser.
<s:Application height="100%" width="100%">
.....
<s:Label text="hello" x="?" y=">" />
</s:Application>
I heard it's possible to use Application.application.width; but I get a compile error, that it doesn't know what that is.
Any ideas how to do this. I'm trying to get the current size of the swf in the browser, as the browser resizes.
As far as I can tell the following should work. Application.application simply is the same as this provided you are in the base application. The binding should allow the size to change after initialization.
<s:Application height="100%" width="100%">
.....
<s:Label text="hello" x="{width}" y="" />
</s:Application>
Edit : I just checked and it does work. To put your Label in the middle of the stage you simply have to put it like that
<s:Application height="100%" width="100%">
.....
<s:Label text="hello" x="{width/2}" y="{height/2}" />
</s:Application>
you could only know stage size when element is added inside stage, you could try a eventdelegate like this
app.addEventListener(Event.ADDED_TO_STAGE,init);
private function init(evt:Event):void{
trace(stage.stageWidth);
trace(stage.stageHeight);
}
Call a javascript function on browser resize. From there get the reference to the swf, and call the AS function to resize the label. Pass the browser width/height.
See example here
UPDATE: Correction: ExternalInterface goes AS to JS.
It's not completely clear what you are trying to do. x and y are positional elements, width and height are size elements. If you are positioning the label you should probably use top, left, right and bottom rather than x and y if you want it to size as the parent control sizes.
If you want the label centered you can use horizontalCenter and verticalCenter.
If you put it inside a layout control like a panel or a canvas you can just set its left and right to 0 and have the parent canvas size.
If your label is always in a different place depending on the size, you can override updateDisplayList to set the position. That holds whether you put it inside a layout control or not.

Flex - Laying out text within a Canvas

Here's a problem I keep running into:
I have a lot of situations where I need to display some text with a styled container like so:
<mx:Canvas>
<mx:Text text="{text}" left="5" verticalCenter="0" right="5" />
</mx:Canvas>
As you can see - the text in constrained by the left and right margins of the canvas and I have not specified a height for the text control because I want it to grow vertically when I add text to it. Reason being - if there is one line of text I want it to display in the center of the canvas but if there are two or three lines of text I want the text control to show those two or three lines of text.
What keeps happening however, is that it will only display one line of text - no matter how many times I call invalidateSize() on it or the container. What do I do?
CAVEAT: The canvas height and width is set by the component that instantiates it (this is all wrapped up in a custom component) so I can't explicitly set the width or height of the text control...
NOTE: Ok, maybe it's an easy fix because as I was typing this question I figured it out - but, here's a chance to answer an easy question!?
The Text component needs a width if you want it to automatically wrap for you. If you used a string with newlines in it it will work grow as you expected without a width. For you, use:
Edit: Ok, you want it centered in a canvas of varying size. Then you can:
<mx:HBox
width="500"
paddingLeft="5"
paddingRight="5">
<mx:Spacer width="100%" />
<mx:Text
width="100%"
text="{text}" />
<mx:Spacer width="100%" />
</mx:HBox>
Take a look at the TextArea component.

Resources