Beginner Question:
I am using the IFrame Component for Flex in Flex 4. The code below works when it is put at the top of the scrolling area. However, if I put it where it below the viewable area it will not render. I am a complete beginner to Flex. The interesting thing is when I resize the window while the HBox is in view, the Iframe will load. But scrolling to it will not. Below is my code. I have made sure everything is visible=true but it seems like I need to add a listener or somehow trick it to think that the window has been resized to get it to render. Anyone with an idea how to fix this? Thanks!
<mx:HBox visible="true" backgroundColor="#cccccc" id="facebookhbox" width="100%" height="100" horizontalAlign="center" verticalAlign="middle" verticalGap="0" verticalScrollPolicy="off">
<mx:Canvas id="facebookcanvas" visible="true" x="0" y="0" width="650" height="80">
<flexiframe:IFrame visible="true" y="0" x="0" id="facebookIFrame" source="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.examplelink.com&layout=standard&show_faces=true&width=450&action=like&colorscheme=light&height=80" width="450" height="80"/>
</mx:Canvas>
</mx:HBox>
No experience with the Flex IFrame here just FYI but in generic terms you can invalidate the size of the component or invalidate the display list then call validate now in order to force the LayoutManager to recalculate the sizes of the element and it's children (or simply draw in the case of invalidating the display list):
The difficult part I see here is figuring out when exactly you want that to happen (that is capturing some sort of event from the scrollbar). For test purposes you can just create a button and in it's click handler do the following:
facebookIFrame.invalidateSize();
facebookIFrame.invalidateDisplayList();
facebookIFrame.validateNow();
If this works out then you just need to find the appropriate event from the Scroller or Canvas that tells you when scrolling is occuring (at worst you could capture mouse down mark a flag then capture mouseMove and if the flag is set then run the code to invalidate/re-validate). Basically how the layout/drawing works is that the UIComponents have flags that let it know when it needs to recalculate the size of something or redraw it, this way everything isn't always redrawn only those components that require it. In this case it seems the FacebookIFrame isn't getting invalidated at some point when it should. Let me know if I can help anymore or if this doesn't work out.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
height="100%"
width="100%"
xmlns:code="http://code.google.com/p/flex-iframe/"
mouseDown="application1_mouseDownHandler(event)"
mouseUp="application1_mouseUpHandler(event)"
mouseMove="application1_mouseMoveHandler(event)">
<mx:Script>
<![CDATA[
var isMouseDown:Boolean;
protected function button1_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
facebookIFrame.invalidateSize();
facebookIFrame.invalidateDisplayList();
facebookIFrame.validateNow();
}
protected function application1_mouseDownHandler(event:MouseEvent):void
{
isMouseDown = true;
}
protected function application1_mouseUpHandler(event:MouseEvent):void
{
isMouseDown = false;
}
protected function application1_mouseMoveHandler(event:MouseEvent):void
{
if(isMouseDown)
{
facebookIFrame.invalidateSize();
facebookIFrame.invalidateDisplayList();
facebookIFrame.validateNow();
}
}
]]>
</mx:Script>
<mx:Spacer height="1000"/>
<mx:Button label="Test Invalidation"
click="button1_clickHandler(event)"/>
<mx:HBox visible="true" backgroundColor="#cccccc" id="facebookhbox" width="100%" height="80" horizontalAlign="center" verticalAlign="middle" verticalGap="0" verticalScrollPolicy="off">
<mx:Canvas id="facebookcanvas" visible="true" x="0" y="0" width="650" height="80">
<code:IFrame visible="true" y="0" x="0" id="facebookIFrame" source="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.examplelink.com&layout=standard&show_faces=true&width=450&action=like&colorscheme=light&height=80" width="450" height="80"/>
</mx:Canvas>
</mx:HBox>
</mx:Application>
Updated to include a full application showing the example working, this is by no means a good way of doing things, this is due to a bug in the IFrame code that should be fixed (though I'm not sure how or where the bug exists something should be causing it to invalidate appropriately where it is not).
Shaun
Related
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.
I have an AIR application. It should be moved around the screen with the mouse. In order to achieve this I use the event:
this.stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown, true,-2);
It should be activated with the lowest priority compared to inserted elements for example those that should be scrolled, clicked, etc.
I tried the solution shown below with the event priority set to -1 because there might happen 2 different events and my moving application event should be the last one to be serviced or shouldn't be serviced at all.
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication 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="200"
height="200"
applicationComplete="init()">
<fx:Script>
<![CDATA[
import mx.core.Window;
import mx.events.ScrollEvent;
private function init():void {
this.stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown, true,-2);
}
private function onMouseDown(event:MouseEvent):void {
trace("clicked on stage "+event.currentTarget.toString());
if(event.currentTarget == stage){
trace("catched stage target");
this.nativeWindow.startMove();
event.stopImmediatePropagation();
}
}
function scrolledCanvasHandler(event:ScrollEvent){
trace("clicked on canvas "+event.currentTarget.toString());
event.stopPropagation();
}
]]>
</fx:Script>
<mx:Canvas x="29" y="34" width="80%" height="80%" backgroundColor="#343434" scroll="scrolledCanvasHandler(event)">
<mx:Label x="25" y="77" text="moving window, moving window"
fontSize="18" color="#FFFFFF" fontWeight="bold"/>
</mx:Canvas>
</s:WindowedApplication>
As you will notice the
event.stopPropagation();
doesn't work.
Perhaps my solution isn't the best suited to achieve this. Are there better solutions?
Chris
that's what i did in an app of mine:
<s:HGroup id="appTitleBar"
width="100%" height="35"
styleName="titleBar"
mouseDown="nativeWindow.startMove();"
doubleClickEnabled="true"
doubleClick="nativeWindow.minimize();"
contentBackgroundColor="#313131"/>
click (+drag) on this HGroup will drag the window. duobleclick will minimize it.
edit
don't make your whole app draggable this will only confuse the user.
and btw priority should be positive not negative - but also don't mess with this. not expected behavior for anyone.
I am having an issue with my ItemRenderer, which I am using for a spark List. My code is the following:
I have this list:
<s:List
id="productSetList"
dataProvider="{ model.productSets }"
change="model.selectSet( productSetList )"
height="100%" width="100%"
borderVisible="false"
itemRenderer="SideBarItemRenderer" top="20" left="15">
</s:List>
and my itemRenderer is:
<s:ItemRenderer
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
width="160" height="175" autoDrawBackground="false" buttonMode="true" useHandCursor="true"
click="click(event)" cacheAsBitmap="true"
>
<fx:Script>
<![CDATA[
import com.png.vm.model.vos.ProductSet;
protected function click(event:MouseEvent):void
{
trace('arthur');
}
]]>
</fx:Script>
<s:BitmapImage source="{ProductSet(data).image}" width="160" height="175"/>
</s:ItemRenderer>
The thing is, if I scroll the list, and click on an item, it does not trace 'arthur' ! Why is this so ? I must trace that all the time that someone clicks in the list!
EDIT:
If I remove change="model.selectSet( productSetList )" in the list, it works!! but I cannot remove that, some suggestions ? How can I switch that to another function?
Trace only works when you are debugging/using the debugging version of Flash Player. Make sure you are using that. If you want a pop-up message use Alert.show("message")
For more information about trace() check out:
http://livedocs.adobe.com/flex/3/html/help.html?content=logging_08.html
And Alert.show(): http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001965.html
If you are running debug player. Try originating the click event from an embedded <s:Group> this way whatever you add in here beyond the bitmap will still trigger the click event.
Something like:
<s:Group width="100%" height="100%" click="click(event)" >
<s:BitmapImage source="{ProductSet(data).image}" width="160" height="175"/>
</s:Group>
I've definitely had click events work for me inside of ItemRenderers before
My apologies, I have finally solved it. The problem was that inside the function,model.selectSet, I was calling List.change; I was messing the list up! My function was as follows:
public function selectSet(list:List):void {
list.layout.verticalScrollPosition=100;
// another stuffs
}
So, I just removed the line : list.layout.verticalScrollPosition=100; and now it`s working fine.
Thanks for all the help!
I'm trying to call a function and pass a couple of properties to it however it's complain the object i'm attempting to target is null. Can anyone see where I am going wrong?
<mx:ViewStack id="vs" width="100%" height="100%" y="53">
<mx:Canvas id="view1" label="Community" width="100%" height="100%" backgroundColor="#ff9900" showEffect="WipeDown" hideEffect="WipeUp">
<mx:Label text="Community"/>
</mx:Canvas>
<mx:Canvas id="view2" label="Apps" width="100%" height="100%" backgroundColor="green">
<mx:HTML id="myHTML" width="100%" height="100%"
visible="true"
paintsDefaultBackground="true"
htmlRender="browser_completeHandler(event)"
locationChange="browser_locationChangeHandler(event)"
complete="browser_completeHandler(event)" />
</mx:Canvas>
</mx:ViewStack>
<local:DockBar id="dockbar" horizontalCenter="0" bottom="0" width="100%" height="100" minSize="32" maxSize="80">
<mx:Label visible="false" id="menuLabel" text="Menu" bottom="0" horizontalCenter="0" fontSize="24" color="#ffffff" alpha=".75" />
<mx:Image click="gotoApp('Google','http://www.google.com/')" source="{icon1}" buttonMode="true" useHandCursor="true" toolTip="Nice red" rollOver="turnOn(event)" rollOut="turnOff(event)" />
<mx:Image click="gotoApp('Yahoo','http://www.yahoo.com/')" source="{icon2}" buttonMode="true" useHandCursor="true" toolTip="Cool orange" rollOver="turnOn(event)" rollOut="turnOff(event)" />
</mx:HBox>
</local:DockBar>
and the function looks like this:
private function gotoApp(id:String,url:String):void {
vs.selectedChild=view4;
trace(myHTML);
}
It's returning null the first time I click an image however subsequent attempts traces a value (I assume because it is set then, just not when the app loads). Any ideas how to recognize it when the app loads?
Cheers
Well "view4" isn't a child of your viewstack, so its going to throw a null pointer when it tries to shift its children.
The reason it doesn't throw it the second time is probably due to something like
public function set selectedChild( child : Object ) : void {
if ( child == _selectedChild ) return;
...
}
That's a pretty common pattern in setters.
Assuming "view4" is a typo and you meant "view2", you can set the creationPolicy on your ViewStack to "all". By default, ViewStacks only instantiate the first view when created, setting the creationPolicy to "all" will force all of the views in the stack to get instantiated.
The ViewStack will, by default, create its children lazily in document-order, so only the first child which will be visible on load (i.e view1) will not have a null id in your function. Subsequent clicks on the ViewStack will create the other views (view2, view3 and view4) which is why the error will no longer occur.
So you need to modify your code to include a creationPolicy="all" to fix this:
<mx:ViewStack id="vs" creationPolicy="all" width="100%" height="100%" y="53">
<mx:Canvas id="view1" label="Community" width="100%" height="100%">
...
</mx:Canvas>
...
<mx:Canvas id="view4" label="Apps" width="100%" height="100%">
...
</mx:Canvas>
</mx:ViewStack>
Try setting by using the selectedIndex property instead:
vs.selectedIndex = 1;
This way you're not losing out on the benefits of the deferred instantiation.
I am writing an custom component in Flex 3.2 that extends the panel component. After a user performs a certain action I would like to hide the main content area in the Panel component, as well as the Control Bar if one is specified. Any ideas on how to do this? controlBar.visible does not seem to hide the control bar, and I don't know of another easy way of accessing the main content area besides iterating through all the children of the main panel, and I would like to avoid that if possible. Thanks
Couldn't you set one main container, whether a HBox or VBox etc... inside your Panel that would contain all the children, then you could toggle this container visibility depending on the user's action.
As for the ControlBar , you should be able to change its visibility value...
The reason you can't seem to hide the controlbar, is because you are only setting it's visible property - it's still taking up it's space. So, to truly "hide" it, do this:
myControlBar.includeInLayout = false;
Also, to hide all you children, only requires a simple loop:
for each (var oChild:DisplayObject in idPanel.getChildren()) {
oChild.visible = false;
}
So, the entire application would look like this:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
private function doit(): void {
idControl.visible = false;
idControl.includeInLayout = false;
for each (var oChild:DisplayObject in idPanel.getChildren()) {
oChild.visible = false;
}
}
]]>
</mx:Script>
<mx:Button x="10" y="10" label="Button" click="doit()"/>
<mx:Panel x="83" y="10" width="250" height="200" layout="absolute" id="idPanel">
<mx:CheckBox x="10" y="10" label="Checkbox"/>
<mx:DateField x="10" y="40"/>
<mx:ControlBar id="idControl">
</mx:ControlBar>
</mx:Panel>
</mx:Application>
Hope that helps!