Flex fixed and variable height - can it be set in markup? - apache-flex

I've got the following Flex application markup:
<app:MyApplicationClass
xmlns:app="*"
width="100%"
height="100%"
layout="vertical"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:VBox id="idPageContainer" width="100%" height="100%" verticalGap="0"
horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:HBox id="idTopContainer" width="100%" height="28" horizontalGap="2">
(top menu stuff goes here)
</mx:HBox>
<mx:HBox id="idBottomContainer" width="100%" height="100%" verticalScrollPolicy="off" clipContent="false">
(page stuff goes here)
</mx:HBox>
</mx:VBox>
</app:MyApplicationClass>
When I run it, it displays top panel with a fixed height, and a bottom panel with variable height. I expect the bottom panel's height to contain the remaining height, but it somehow overflows off-page.
The only way I found to fix this height issue (so far) is to programmatically set the height to be fixed instead of variable:
<mx:HBox id="idBottomContainer" width="100%" height="700" verticalScrollPolicy="off" clipContent="false">
(page stuff goes here)
</mx:HBox>
And code-behind:
package {
import mx.containers.HBox;
import mx.core.Application;
import mx.events.ResizeEvent;
// (...)
public class MyApplicationClass extends Application {
public var idBottomContainer:HBox;
// (...)
private function ON_CreationComplete (event:FlexEvent) : void {
// (...)
addEventListener(ResizeEvent.RESIZE, ON_Resize);
}
private function ON_Resize (event:Event) : void {
idBottomContainer.height = this.height - idTopContainer.height;
}
}
}
But this solution is too "dirty" and I'm looking for a more elegant way. Does anyone know an alternative?

Seems to me what you have ought to work. I have something similar working in countless screens. But if you're really stuck you could try to replace the VBox with a Canvas and do something like this:
<mx:Canvasid="idPageContainer" width="100%" height="100%" verticalGap="0"
horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:HBox id="idTopContainer" width="100%" height="28" horizontalGap="2">
(top menu stuff goes here)
</mx:HBox>
<mx:HBox id="idBottomContainer" width="100%" top="{idTopContainer.height}"
height="{idPageContainer.height - idTopContainer.height}"
verticalScrollPolicy="off" clipContent="false">
(page stuff goes here)
</mx:HBox>
</mx:Canvas>

Related

Flex: Getting rid of "Warning: Filter will not render. The DisplayObject's filtered dimensions ..." error

When printing (I think at the point I call FlexPrintJob.addObject()) I get the following:
Warning: Filter will not render. The DisplayObject's filtered dimensions (3324, 1740) are too large to be drawn.
I don't know what it thinks is 3324, 1740. The mx:Box object I pass to it is about 600x100.
I'm wondering if this problem is related to another problem I'm having. What gets printed has an extra border on the bottom and the right of what I want printed. I'm hoping that understanding this message will correct my problem.
I'm using the Flex 3.5 SDK
Here's a stripped down version of the code that still allows for this problem:
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
title="FPL Flight Strip"
showCloseButton="true"
borderAlpha="1"
borderColor="{BrandGlobals.COLOUR_DARK}"
borderThicknessBottom="1"
borderThicknessLeft="1"
borderThicknessRight="1"
borderThicknessTop="0"
dropShadowEnabled="true"
fontSize="{AppGlobals.fntSize}"
backgroundAlpha="1.0"
alpha="1.0"
creationComplete="init()"
close="PopUpManager.removePopUp(this);">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.printing.FlexPrintJobScaleType;
import mx.printing.FlexPrintJob;
private function init():void
{
this.setStyle('fontFamily', 'Arial');
}
private function printData():void
{
var dbPrintJob: FlexPrintJob = new FlexPrintJob();
if (dbPrintJob.start())
{
try
{
dbPrintJob.addObject(boxPrint, FlexPrintJobScaleType.NONE);
}
catch (e:Error)
{
//trace(e);
}
dbPrintJob.send();
}
}
]]></mx:Script>
<mx:VBox width="600" height="100" horizontalAlign="center" verticalAlign="middle" backgroundColor="#FFFFFF" verticalGap="1" paddingLeft="2" paddingRight="2" paddingTop="2" paddingBottom="2">
<mx:Box id="boxPrint" width="100%" height="100%" backgroundColor="#FFFFFF">
<mx:Box id="box" width="100%" height="100%"/>
</mx:Box>
</mx:VBox>
<mx:ControlBar width="100%" barColor="#E8E8E8" paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0">
<mx:VBox width="100%" height="100%" horizontalAlign="left" backgroundColor="#E8E8E8" paddingTop="5" paddingBottom="5" paddingRight="20" paddingLeft="20">
<mx:HBox width="100%" height="100%">
<mx:Button label="Print Strip" fontFamily="Arial" click="printData()" width="100" height="25" />
</mx:HBox>
</mx:VBox>
</mx:ControlBar>
</mx:TitleWindow>
I was not able to reproduce the filter error in Flex 3.6. Are you not able to upgrade? To my knowledge, there shouldn be very few issues with backwards compatibility, unless you are heavily overriding mx_internal.
I did however get the problem with the borders. This has to do with the way you are adding your objects. It's best to wrap the thing you want to print in a container, then add the container to the print job. This let's you control things like margins and spacing.
private function printData():void
{
var dbPrintJob:FlexPrintJob = new FlexPrintJob();
if(dbPrintJob.start())
{
try
{
dbPrintJob.addObject(this.canvas, FlexPrintJobScaleType.NONE);
}
catch(e:Error)
{
//trace(e);
}
dbPrintJob.send();
}
}
<mx:Canvas id="canvas" width="100%" height="100%">
<mx:Box id="boxPrint" top="10" left="10" bottom="10" right="10" backgroundColor="#FFFFFF">
<mx:Box id="box" width="100%" height="100%" />
</mx:Box>
</mx:Canvas>
Use the canvas to paint your background and space the children into the desired print layout.
I would also suggest giving this a quick read:
Setting size, scale, and orientation
You can try using a simple font such as "Arial", and try if the error still appears, to rule out problems than font.
And avoid using any component if you're having this problem to see if that eliminates the problem.

how to replace the images in flex 3?

In my flex application, i am maintaining 5 images. When user clicks on 'next' button, it should display one image say 'image1'. If that button clicked again, then image1 should replace with image2 and so on. I am basically following 'image.visible' method. But images are displaying side by side. I think it is not the correct procedure. Any alternative? Thanks in advance
here is my code. I kept all my images and buttons in mx:panel. Even i used x and y positions which are not working.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Panel
title = 'Learn and Test your Knowledge'
height = '80%'
paddingBottom = '10' paddingTop = '10'
paddingLeft = '10' paddingRight = '10'
borderAlpha='0.20' fontFamily="Verdana" fontSize="15" color="#F30C32" backgroundImage="#Embed(source='../images/lad.jpg')" width="413" x="139">
<mx:Script>
<![CDATA[
public function nextEvent():void
{
// here i should write next button code
}
]]>
</mx:Script>
<mx:Image source="../images/image1.jpg" visible="true" id="image1" />
<mx:Image source="../images/image3.jpg" visible="true" id="image2"/>
<mx:Image source="../images/image3.jpg" visible="true" id="image3"/>
<mx:Button id="next" visible="false" click="nextEvent()">
</mx:Button>
The best way is to use only one image component if you are only ever showing one image. You can create an array or vector with the embedded images and reference that to change the source property on the image component. Here is an example: (the code below will work with any layout/container)
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Image id="image" click="imageClick()" source="{new images[0]()}" />
<mx:Script>
<![CDATA[
[Embed(source="assets/1.png")]
private var image1:Class;
[Embed(source="assets/2.png")]
private var image2:Class;
[Embed(source="assets/3.png")]
private var image3:Class;
private var images:Array = [image1, image2, image3];
private var imageIndex:uint = 0;
protected function imageClick():void
{
imageIndex++;
if(imageIndex == images.length) imageIndex = 0;
image.source = new images[imageIndex]();
}
]]>
</mx:Script>
</mx:Canvas>
Specify the x and y position of images as same and play around with their visibility.It ll definitely work.
ViewStack is my option it fits very well in this occasion.
At a time it shows only one component, for next action it will automatically override previous content by its new component.
<mx:ViewStack id="myViewStack" borderStyle="solid" width="100%" height="80%">
<mx:Canvas id="one" click="myViewStack.selectedChild=two;">
<mx:Image source="assets/1.png" />
</mx:Canvas>
<mx:Canvas id="two" click="myViewStack.selectedChild=three;">
<mx:Image source="assets/2.png" />
</mx:Canvas>
<mx:Canvas id="three" click="myViewStack.selectedChild=four;">
<mx:Image source="assets/3.png" />
</mx:Canvas>
<mx:Canvas id="four" click="myViewStack.selectedChild=five;">
<mx:Image source="assets/4.png" />
</mx:Canvas>
<mx:Canvas id="five" click="myViewStack.selectedChild=one;">
<mx:Image source="assets/5.png" />
</mx:Canvas>
</mx:ViewStack>

Tab Navigator in a Title window : issue

I am adding a tab navigator to a title window here. Once the title window is closed, it can be reopened using the button.But on opening the title window second time in this manner ,the content of the children of the Tab navigator(here, a label) is not visible.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()"
<mx:TabNavigator x="68" y="68" width="200" height="200" id="tabNavig" historyManagementEnabled="false">
</mx:TabNavigator>
<mx:Script>
<![CDATA[
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
public function init():void{
tabNavig.removeAllChildren();
tabNavig.addChild(canvas1);
tabNavig.addChild(canvas2);
tabNavig.addChild(canvas3);
expenseTitle.showCloseButton = true;
expenseTitle.addChild(tabNavig);
PopUpManager.addPopUp(expenseTitle,this,false);
expenseTitle.addEventListener(CloseEvent.CLOSE,titleWindow_close);
}
private function titleWindow_close(evt:CloseEvent):void
{
expenseTitle.removeAllChildren();
PopUpManager.removePopUp(expenseTitle);
}
]]>
</mx:Script>
<mx:TitleWindow id="expenseTitle" >
</mx:TitleWindow>
<mx:Canvas id="canvas1" x="476" y="117" width="200" height="200" >
<mx:Label x="64" y="93" text="Label1"/>
</mx:Canvas>
<mx:Canvas id="canvas2" x="244" y="310" width="200" height="200" >
<mx:Label x="111.5" y="29" text="Label2"/>
</mx:Canvas>
<mx:Canvas id="canvas3" x="697" y="117" width="200" height="200" >
<mx:Label x="59" y="79" text="Label3"/>
</mx:Canvas>
<mx:Button x="78" y="310" label="Button" click="init()"/>
</mx:Application>
The structure of your MXML is completely wrong.
You need to keep MXML components (e.g. a TitleWindow that you plan on using as a popup) separate from your main application markup.
For example, create a separate MXML component, called MyForm.mxml. This component should be a TitleWindow with a Tab Navigator. The Tab Navigator should have the 3 Canvas components as children.
Then, in your main application logic, the Button should launch the pop up, MyForm.mxml like so:
var form:MyForm = MyForm(PopUpManager.createPopUp(this, MyForm, true));
PopUpManager.centerPopUp(MyForm);
Finally, in your MyForm.mxml component, add the event listener for closing. The method should only need to call: PopUpManager.removePopUp(this);

Flex show/hide on mouse over/out

i have 2 containers one above the other,
i need to show the second one when
there is a mouse over the first one
and
hide it when it goes out of the first one
also i want the second container content to be usable (mouse clicks/moves)
how can i do that?
Biroka has the right idea but there is another way. Put the containers in a viewstack and change the selectedChild on rollOver and rollOut. This should eliminate your flicker. Here's a fully functional sample
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[
private function vsRollOver():void{
viewstack1.selectedChild = container2;
}
private function vsRollOut():void{
viewstack1.selectedChild = container1;
}
]]>
</mx:Script>
<mx:ViewStack x="10" y="10" id="viewstack1" width="200" height="200" rollOver="vsRollOver();" rollOut="vsRollOut();">
<mx:Canvas id="container1" label="View 1" width="100%" height="100%" backgroundColor="0x0000ff">
</mx:Canvas>
<mx:Canvas id="container2" label="View 2" width="100%" height="100%" backgroundColor="0xff0000">
</mx:Canvas>
</mx:ViewStack>
</mx:Application>
The second container has to be above the first one and:
private function init():void // call this on creationComplete event
{
container2.visible = false;
container1.addEventListener(MouseEvent.ROLL_OVER,overFunction);
container1.addEventListener(MouseEvent.ROLL_OUT,outFunction);
}
private function overFunction(e:MouseEvent):void
{
container2.visible = true;
}
private function outFunction(e:MouseEvent):void
{
container2.visible = false;
}
I would suggest that container1 should be 1-2 pixel larger than container2

Controlling which VBox gets the scrollbar

I have the following application and I am trying to put a scrollbar somewhere inside the TabNavigator, preferably on the innermost Vbox, but the scrollbar always ends up on the Panel. Is there some kind of property which controls this? I thought height=100% would have controlled it but it doesn't seem to work.
Sample is here. You can view source on it:
VBox Sample
Here is the source anyway:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" viewSourceURL="srcview/index.html">
<mx:Panel width="400" height="400">
<mx:TabNavigator width="100%" height="100%" creationPolicy="all">
<mx:VBox label="Tab 1" width="100%" height="100%">
<mx:ViewStack width="100%" height="100%">
<mx:VBox width="100%" height="100%">
<mx:Text width="100%" height="500" text="This box is taller than the Panel, but the scrollbar is on the window." />
</mx:VBox>
</mx:ViewStack>
</mx:VBox>
</mx:TabNavigator>
</mx:Panel>
</mx:Application>
I found the proper solution is to set the minheight on the box to 0. When the minheight is not defined, the box will try to remain at it's measured height. By setting the minheight you are telling the box it is ok to shrink.
I've had this issue in the past, and the solution is a bit wonky, but hopefully this helps:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Panel width="400" height="400" verticalScrollPolicy="off">
<mx:TabNavigator width="100%" height="100%">
<mx:VBox id="container" label="Tab 1" width="100%" height="100%">
<mx:ViewStack width="100%" height="{container.height - 20}">
<mx:VBox width="100%" height="100%">
<mx:Text width="100%" height="500" text="This box is taller than the Panel, but the scrollbar is on the window." />
</mx:VBox>
</mx:ViewStack>
</mx:VBox>
</mx:TabNavigator>
</mx:Panel>
</mx:Application>
Flex seems to calculate dynamic component dimensions properly about 98% of the time, but sometimes we need to "massage" the logic.
When you look at your layout hierarchy (as I've shown above), you just need to name the parent container (in this case Tab1) for the purposes of data binding, then use that container's height property for your sizing. (you also don't need to explicitly state verticalScrollPolicy="off" on the panel, but I use if for good measure :P)
Note that you may need to subtract a bit from the given height or your scrollbar will be below the component bounds ;)

Resources