How can I create a Flex application with dynamic height? - apache-flex

Is there a way to allow a flex application to have a dynamic height while embedded in an HTML wrapper?
I want the Flex application to grow in height in a way that it will not cause vertical scroll bars.

The best way should be overriding the Application's measure method like:
private var _lastMeasuredHeight:int;
override protected function measure():void
{
super.measure();
if (measuredHeight != _lastMeasuredHeight)
{
_lastMeasuredHeight = measuredHeight;
if (ExternalInterface.available)
{
ExternalInterface.call("setFlashHeight", measuredHeight);
}
}
}
This function assumes that you have a javascript function named setFlashHeight which can accept a height (or whatever you name it) parameter. An example would be:
function setFlashHeight(newHeight){
//assuming flashDiv is the name of the div contains flex app.
var flashContentHolderDiv = document.getElementById('flashDiv');
flashContentHolderDiv.style.height = newHeight;
}
I use swfobject to embed my flex applications. So the flash object resides inside a div. If yours not; the js function could easily be altered to set the flash object's height. When you implement this solution, you'll notice that scrollBars aren't working as flash consumes the event. But that's another subject...

This is possible. For an example, see the new Kontain by fi. You can see it directly in action by creating a new blog post and adding lines to the entry field. As the entry field grows in size, the page gets taller.
You'll have to coordinate between Flash and Javascript via ExternalInterface. When your Flex app needs to change size, find the new size (probably by digging into Flex's layout engine) and throw that up to a Javascript function via ExternalInterface. The javascript then can set a new height property on the container. You'll probably also want to set verticalScrollPolicy="off" on your tag so that Flex doesn't show the scroll bars when the layout engine runs.

I'm not sure I fully understand the question, are you trying to get the aplication to have a size larger than the browser's view port? If so, then as #hasseg commented and #RickDT mentioned, you can set the Application's horizontalScrollPolicy and/or verticalScrollPolicy properties to "off"?
If you're simply trying to make sure your application scales with changes to the browser's shape and size, then make sure you set the following (or values that suit) in your outer most application tag.
percentWidth="100"
percentHeight="100"

Unfortunately no, I think the only way you could do this is to get rid of the html wrapper in the first place. HTH.

There is no need for all that, just change the application from spark to mx. this will show it automaticly because I think spark does not support that at all ( I think it's stupid bug from adobe )
like this:
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009" >
</mx:Application>
instead of:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" >
</s:Application>
leave application tag without height specification "don't use height="100%"

Related

Resizing container on resize of application window in Adobe Flex/AIR Application

I am working on an Adobe AIR Application. The size on Application window is 800X600 and is contains border container and border container contains many controls.
What I want is to if user re-sizes the application then that container should also be re-sized according to scale. i.e If user maximizes or minimizes the window then that border container should also be maximized or minimized respectively.
If you don't want to (or can't for some reason) use percentage based widths then you can always just do the following in MXML:
<s:BorderContainer
xmlns:mx = "http://www.adobe.com/2006/mxml"
xmlns:s = "library://ns.adobe.com/flex/spark"
width = "{parentApplication.width / 2}"
height = "{parentApplication.height / 2}">
You are just getting a reference to the component's parentApplication and directly binding to its width and height. Throw whatever math you want on the end.
An easier way to do this is to have your components declare their sizes/positions relative to their outer containers. For example, rather than setting x, y, width and height, set left, right, top and bottom in your Application component as well as the containers within your Application. If you want to enforce a minimum size of 800x600, you can set the minWidth and minHeight properties. Hope that helps.
This can be accomplished using an MVC framework. Some options include RobotLegs, Mate, Cairngorm or it is possible to use some quick design patterns and implement a custom version.
Essentially, the Application event Event.RESIZE should be detected and applied to the container. The properties of stageHeight and stageWidth will give the necessary info to resize the container.
Resize events will traverse the display hierarchy in any case, but it's convenient to intercept at the application level, should a custom event or function apply to the controls.

Extending DataGrid component, and adding buttons to it

I'd like to extend the standard DataGrid component in flex with mxml. But I want to add buttons to the bottom of the component. I've tried attempting the following but its not working...
Am I adding the Button to the wrong element?
<mx:DataGrid xmlns:fx = "http://ns.adobe.com/mxml/2009"
xmlns:mx = "library://ns.adobe.com/flex/mx"
xmlns:s = "library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
override protected function createChildren():void
{
super.createChildren();
listContent.addChild(button);
}
]]>
</fx:Script>
<s:Button id="button" label = "asdasdas"/>
</mx:DataGrid>
You need to define "Not working"! Are you getting compiler errors? Or runtime errors? Or is the button just not showing up? I'll assume the latter.
The DataGrid does not have any mechanism for positioning or laying out it's children. Your button most likely has a height and width of zero and resides at position 0,0; making it effectively invisible. Many Flex container classes have the ability to size and position their children; but the DataGrid is not a container and does not provide built in functionality for that. It focuses, primarily, on working with the columns array.
You will need to override the updateDisplayList() to position the function. Quite possibly you will need to make changes to commitProperties() and measure() along the way. You may also need to re-work how the columns are positioned and sized as to not interfere with your new button. If stuff is locked away in private methods (which is probable) then you're in a for a not-so-fun-time.
Read up on the Flex Component LifeCycle methods for more information and also review the DataGrid code to figure out what it does.
You may have an easier time just putting the button and DataGrid in a container, and treating that container as a single entity instead of trying to get a Button renderered inside of the DataGrid.
Got it. All I needed to do was replace listContent.addChild(button); with...
parent.addChild(button);
Thanks!

What's the easiest way to create an extensible custom container in Flex?

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.

Why are width & height of loaded SWFLoader zero?

I have a class which extends SWFLoader, I use it like a normal SWFLoader:
var loader:MySWFLoader = new MySWFLoader();
loader.load("myFile.SWF");
myScene.addChild(loader);
The loading works OK, except that it remains 0 because the width & height never change from 0. I had to override the width/height get properties to make it work:
class MySWFLoader extends SWFLoader
{
public override function get width():Number{ return contentWidth; }
public override function get height():Number{ return contentHeight; }
}
As well as being a big hack this isn't quite correct; especially since the SWF has multiple frames and the frames are of different width/height.
Why aren't width/height working in the first place? Shouldn't they be automatically set during loading? Is it possible the issue lies with the SWF itself somehow?
Update: Changing scaleContent to true or false makes no difference.
I'm not sure if this applies for SWF loading, but whenever I'm loading content, i cannot access width and height before the whole thing is loaded.
So make an event listener that listens when the loading is completed, and then read the height/width.
Also take a look at the loaderInfo class in AS3
I'm not sure what part of the cycle you're trying to grab the height and width (and is it of the loader object or the loaded content) but you can can access the height and width of the loaded object using SWFLoader.loaderInfo.height and SWFLoader.loaderInfo.width.
By default the SWFLoader scales the content to the size of the loader, so you have to set the size of the loader. If you want the loader to scale to the size of the content then you have to set the scaleContent property to false.
SWFLoader is a UIComponent.
It needs to be run through the UIComponent framework to set its dimensions correctly
In other words, it is waiting for calls to commitProperties(), updateDisplayList(), etc.
If you drop it in your application (so that it is part of the layout framework) it should be fine.

brokenImageSkin dimensions in Flex

I am trying to implement a custom "broken image" icon to appear if I cannot load an image. To accomplish this, I used the brokenImageSkin parameter, but it renders the image at its true resolution, which ends up cutting off the image if the size of the control is constrained.
<mx:Image brokenImageSkin="#Embed('/assets/placeholder.png')" source="http://www.example.com/bad_url.png"/>
How can I scale the brokenImageSkin to a custom width and height?
I see that in this example,
http://blog.flexexamples.com/2008/03/02/setting-a-custom-broken-image-skin-for-the-image-control-in-flex/#more-538, there is an IO error event where you could set the width and height of the image.
Make a new class that extends ProgrammaticSkin. Embed your image using the [Embed] meta keyword and associate it with a variable of type Class (see the documentation for this)
Override updateDisplaylist.
Call graphics.clear() in this function.
Call graphics.beginBitmapFill and then apply the appropriate dimensions and scaling based on the unscaledWidth and unscaledHeight passed in.
This is way more complicated but it's the only way I know of to get more control out of a custom skinning operation like that.

Resources