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

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.

Related

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.

Flex4 Button is covered by runtime graphic and is unusable

Newbie here,
I have a skinned button at x=47 y=126 which is later "covered" by a .png that loads dynamically. Once the .png loads, the button disappears. How can I tell Flash Builder 4 to place the .png behind the button so that it is always clickable. FYI: if I move the button away from the graphic, it works just fine, but, for design purposes, I really would like it to stay where it is.
Thanks,
Jason M.
You could also try giving the button a depth value of 1 or higher.
"Spark containers order their items based on their depth property, with the lowest depth in the back, and the higher in the front.Items with the same depth value appear in the order they are added to the container."
<s:Button x="47" y="126" depth="1" skin="customSkin"/>
Conversely you could add a smaller depth to the .png, or if you are drawing them in the same container change the order they are in there. (From the quote above on depth)
If you need to have an image as a background for your button you should place it behind button the following way:
<s:Group>
<s:BitmapImage />
<s:Button />
</s:Group>
I suppose your case is the following:
<s:Group>
<s:Button />
<s:BitmapImage />
</s:Group>

Components inside a repeater not resizing as expected

I have an mxml panel in which I'm using a repeater. The panel can be resized horizontally and I would like for the repeated components to resize together with panel. Here is a simplified example of how things look like:
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" ...>
<!-- scripts and some controls -->
<mx:VBox width="100%">
<core:Repeater width="100%" dataProvider="model">
<ns1:MyItemRenderer width="100%" />
</core:Repeater>
</mx:VBox>
</mx:TitleWindow>
When I resize the component, the width of the repeated items does not change.
There also buttons and event handlers, which add and remove items from the model. When this is done, the repeater updates to display the correct number of items and all the items are resized correctly.
I have not been able to get the items to resize when the root panel is resized. I can see, that the VBOx around the repeater is getting a resize event. However, the repeated items are not getting the event. I tried to dispatch a resize event to the repeated items manually from a resize handler I hooked up to the VBox but that didn't help.
I also tried adding and removing a dummy-item from the ArrayCollection which is the dataProvider (because that triggers a correct resize otherwise as mentioned above) However, doing this in the resize handler of the VBox just leads to the repeater not showing any items at all.
Is there any way to get items in a repeater to resize with their enclosing container?
The ItemRenderer I'm using resizes correctly when used in a mx:List. It is built so it can work both with the data property set by the List container an getRepeaterItem() when used in a Repeater. In this particular case, I cannot use the List as a container because of the way it behaves with regards to controlling its height via the rowCount, height and maxHeight properties which doesn't work out for me in this particular case (I spare you the details).
override updateDisplayList in the titleWindow and when the height or width changes, invalidate the displayList on every item created inside the repeater.
That said, using repeaters are generally considered bad practice because every component inside it is rendered. A list based class--which makes use of renderer recyling is considered to be much more performant.
Based on your code segment, I can't tell whether your code could be re-worked without repeaters, or not.
For the record, I figured out the following "solution":
Use the maxHeight attribute on the box enclosing the repeater, binding it to an expression that derives the correct value from the other components... I still need to hardcode any space I want to reserve for components that come after the box containing the repeater if I don't want to have them pushed out of the enclosing panel but it is good enough for now.
essentially:
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" ...>
<!-- scripts and some controls -->
<mx:VBox id="outerBox" height="100%">
<mx:VBox id="innerBox" width="100%"
maxHeight="{outerBox.height - innerBox.y - 40}">
<!-- reserve 40 px for the button -->
<core:Repeater width="100%" dataProvider="model">
<ns1:MyItemRenderer width="100%" />
</core:Repeater>
</mx:VBox>
<mx:Button label="Stay Visible"/>
</mx:VBox>
</mx:TitleWindow>

Flex : Cross resolution applications

What is the best way to create applications in Flex/AIR,
which look and feel the same irrespective of the screen
resolution?
When creating the layout in your flex application, you can achieve a consistent screen resolution independent look and feel from using relative scaling.
This is much akin to creating a liquid layout with HTML.
For example, to create a simple two column application— left navigation and content— you only need two containers, one predefined and one left to scale indefinitely.
As follows:
<mx:HBox width="225">
<mx:Button label="Menu 1"/>
<mx:Button label="Menu 2"/>
<mx:Button label="Menu 3"/>
</mx:HBox>
<mx:HBox width="100%">
Any content here will flow fluidly across the entire screen regardless of window size/screen resolution.
</mx:HBox>
Using the above basics you can create a application layout that forms to any screen.
However, sometimes you need to create a more elaborate layout scheme with many interchanging components resizing dynamically to fit the window.
For this you can do Absolute Positioning.
override the components updateDisplayList() function and create your own sizing/positioning rules.
This of course requires you to be within a Canvas container or have the main Application container set to absolute layout.
A simple example:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
{
//find out how big we are
var stageWidth:int = this.width;
//center the box in the middle of the page.
centeredBox.x = stageWidth - (centeredBox/2);
}
</mx:Script>
<mx:HBox id="centeredBox" width="500"/>
</mx:Application>
By overriding updateDisplayList() you can create endless ways to better dynamically position and size your components to better use the screen realestate.
You can create a application with height and width respective to the container so that way all components will aling themself properly at all screen resolutions.
We typically create a MainFrame.mxml which acts as our primary component and has layout relative scaling as mentioned by the others. Then we create the AIR app which just embeds that one MainFrame.mxml and another Flex app that embeds it as well. This way we can keep the entire app within MainFrame and not worry about if it is in Flex or Air. This being said you will need to make sure you do not use any AIR specific or Flex specific calls that do not translate to the other.

Limit width of custom list itemrenderer in Flex

I'm using a custom itemrenderer to display a list of photos and need to know how to control the width. At the moment it does this:
(source: tdwright.co.uk)
Which, as I'm sure you'll agree, is eye-bleedingly ugly.
The list is created like this:
<mx:Panel width="100%" height="100%" layout="absolute" title="Photos">
<mx:List x="0" y="0" width="100%" height="100%" id="photoList" dataProvider="{photos}" itemRenderer="thumbnails" rowHeight="100"/>
</mx:Panel>
And the itemrenderer component looks like this:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Image source="{data.src}" id="image" scaleContent="true" toolTip="{data.caption}" height="100%" horizontalAlign="center"/>
</mx:VBox>
I've tried placing width="100%" in a whole bunch of places, but without success. If anyone knows how I can control this I'd be very grateful.
If you set these properties inside the itemrenderer verticalScrollPolicy="off" horizontalScrollPolicy="off" the bars are disappeared
I don't know why they choose for the terrible "off" instead of False
A couple of observations here, based on a miasma of similar painful experiences. (Caveat: I have not built a test app to confirm everything here for this specific case)
Assuming that what you want is for the list to size its width based on the size of the itemRenderer elements it contains, those itemRenderer elements need to provide width information. Using a VBox in this fashion with scroll bars permitted means the VBox will attempt to "arbitrate" between the size of the content (Image) and the size of the parent. So yes, first thing to do is turn off the scrollbars on the VBox, assuming you can't just get rid of the VBox altogether. (I'm guessing you want the VBox so that you can put a title or something under the image as a next step)
The List as you have it specified is sized to 100% of its parent, the Panel, which is itself sized to 100% of its parent. Rather than size these elements "top down", consider letting their width be unspecified so that Flex will compute their required width bottom-up. Use maxWidth on the List or the Panel constrain their size if you need to for laying them out relative to their peers.
Another important thing to know about is the "minHeight=0" trick. Turns out, the sizing algorithm used by Flex behaves quite differently when minHeight or minWidth is set to something other than the default NaN. Setting it to 0 is extremely useful in many of these cases. Try minWidth=0 on the VBox and/or the List.
In addition to turning off the scrolling policy, set left and right to 0. That should anchor the width to the width of the parent.

Resources