Adobe Air - Load PNG image from file in IconItemRenderer - actionscript-3

I have a LIST object that has an IconItemRenderer. I have images stored in the documentsDirectory and would like to dynamically attach them to items in the list based on a proptery in the "item" in the iconFunction.
I've looked everywhere for an iconFunction that will return an image from file.

<s:List width="150">
<s:itemrenderer>
<fx:component>
<s:Image source="{data.img}"/>
</fx:component>
<s:itemrenderer>
</s:List>
here in 'data.img' img is the property which holds the path to the image. This data object is also available in your itemrenderer file. so you can use as below in your iconItemrenderer
<s:Image source="{data.img}"/>
Even if you dont have path and have byteArray instead of path of image, you can pass the same to source property
Ex : <s:Image source="{data.byteArray}"/>

Related

Referring .mxml tag from (not included) actionscript file

I have a Home.mxml file with home_src.as included in a fx:Script tag. Now suppose that I want to retrieve the value of a <mx:TextInput.../> tag located in Home.mxml, from another .as file (for example login_src.as).
I tried mx.core.Application.application.[file.mxml].[property] but doesn't work (I obtain an error like this: property not found on ).
I don't know if it is possible without including the .as file who wants access to the .mxml property, but I want to find out because I have a canvas.mxml page (with some text and combo tag) that contains a tabNavigator with two other .mxml pages; in the actionscript of these two tabs I need the value of canvas.mxml input and combo tag.
Is there a way to do this without including tab1 or tab2.as into my canvas.mxml?
A button click opens a popup for data insertion:
home.as
..
var insertPop:InsertPopUp = InsertPopUp(PopUpManager.createPopUp((this.parentApplication as DisplayObject), InsertPopUp, true));
PopUpManager.centerPopUp(insertPop);
..
InsertPopUp.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init()" close="close()">
<mx:Script source="InsertPopUp_src.as"/>
<mx:Label id="lblage" text="Age:"/>
<mx:TextInput id="txtAge" editable="true"/> // I want this data
<mx:TabNavigator id="insertTab" width="100%" height="85%">
<mx:VBox id="vbx1" width="100%" height="100%" label="Car Data">
<mx:ModuleLoader id="mdlCatData" url="modules/Cat.swf" height="100%" width="100%" />
</mx:VBox>
<mx:VBox id="vbx2" width="100%" height="100%" label="Van Data">
<mx:ModuleLoader id="mdlDogData" url="modules/Dog.swf" height="100%" width="100%"/>
</mx:VBox>
</mx:TabNavigator>
</mx:TitleWindow>
Then I have:
Cat.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init();">
<mx:Script source="CatData_src.as" />
// other forms..
</mx:Module>
and:
Dog.mxml
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init();">
<mx:Script source="DogData_src.as" />
// other forms..
</mx:Module>
I want to retrieve data of the txtAge textInput and use it in both CatData_src.as and DogData_src.as; how can I get that data without resorting to a script include?
I made this "graphic configuration" because some data are common to Cat and Dog.. (obviously is just an example).
mxml is not anything special in the world of AS3, it seems different but it's really not as it is compiled later into AS3 code. Any object declared in mxml tag with an id is just a property of the as3 class that will be generated (using the same name as the mxml file).
If that mxml class is supposed to be unique (not 2 instances of it) you can access your property using static methods.
Example:
mxml main class named: MyMain.mxml
declare static variable (in fx:script) of type MyMain: static public var instance:MyMain;
in addedToStage listener (or similar) set your variable: instance = this
from anywhere access your instance and property: MyMain.instance.mytextimput
If working with multiple instances of mxml class then get reference of the instance and use it just like any other AS3 object.

Flex mx:SWFLoader Loads Incorrect SWF File

I'm fairly new to Flex and am having an issue where I have a main Flex program (let's called it "Parent.swf") attempting to load another Flex application (Child.swf) via the SWFLoader class/component.
Environment is Flex 4.6 on FlashDevelop.
The call appears to work correctly (i.e. no IO or sandbox errors are returned), only that it seems to reload the "Parent.swf" into the SWFLoader instead of the "Child.swf".
For example, I have the Parent.swf containing:
<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"
initialize="doStartup()"
width="1024" height="768">
...
<fx:Script>
<![CDATA[
private function doStartup():void
{
trace("STARTING UP!");
}
....
]]>
</fx:Script>
<mx:VBox top="10" left="10" width="100%" horizontalAlign="center">
<mx:Label text="I'M A LOADER!" />
</mx:VBox>
<mx:VBox top="10" left="10" width="100%" horizontalAlign="center">
<mx:SWFLoader
id="pluginLoader"
source="plugins/Child.swf"
autoLoad="true"
height="400" width="400"
complete="onPluginLoaded(event);"
ioError="onPluginLoadError(event);"
securityError="onPluginSecurityError(event);"
httpStatus="onHttpStatus(event);"
init="onInit(event);"
open="onOpen(event);"
progress="onProgress(event);"
unload="onUnload(event);"
/>
</mx:VBox>
....
The child swf contains:
....
<mx:Label text="I'M A PLUGIN!" />
....
The trace above (i.e. "STARTING UP!") is repeated on the load of Child.swf, followed by another attempt to load Child.swf which fails because the working directory for the call is now in the "plugins" directory.
So it seems to know the file exists and load it, but somehow swaps in Parent.swf over the top of it.
Note that if I execute Child.swf directly, I'm able to verify that it is what I expect it to be (i.e. a flex app with a single label saying "I'M A PLUGIN!").
I've also tried various other approaches such as instantiating a SWFLoader via code but the same issue occurs. I even tried to switch to Modules but had the same behaviour there too.
It fails whether run locally or run via a web server.
Does anyone have any idea how this could occur? Is there some way that the main.mxml of Parent.swf is overriding Child.swf?
(Sorry for the essay)
I need the full code to discovery. But I can suggest two ideas:
Check your onPluginLoaded function, it can be called by Parent instead of the Child
Check if you don't have any class or object name repeated that can generated a cross-reference. For example, both Parent and Child use MyScrollbarClass. As this class was firstly loaded by Parent, it will create a new name when load in Child, like MyScrollbarClass_1
mxml file must be named differently in loaded applications

flashbuilder list component - how to add an image URL

Im working with flashbuilder 4.6 and have a simple app underway that uses a listcomponent pulling data from an XML service (external URL) that is setup with data/services functionality within flashbuilder.
right now I have a relatively simple list that just displays the 'name' of the xml items:
<s:List id="list1" x="0" y="108" width="320" height="355" change="list1_changeHandler(event)"
creationComplete="list1_creationCompleteHandler(event)" labelField="Itemname">
<s:AsyncListView list="{getDataResult.lastResult}"/>
</s:List>
... I have another xml node / data element that is a full URL (http:// ... .jpg) to a thumbnail image, I'd like to have that image aligned to the left of the 'name' element.
I tried using someting like the following, but no luck. the information I've found online hasnt really helped much with understanding itemrenderers (which is what I think I need to use).
<s:List id="list1" x="0" y="108" width="320" height="355" change="list1_changeHandler(event)"
creationComplete="list1_creationCompleteHandler(event)" labelField="Itemname">
<s:AsyncListView list="{getDataResult.lastResult}"/>
<mx:itemRenderer>
<mx:Component>
<mx:Label text="Itemname"/>
<mx:Image source="ItemImageURL"/>
</mx:Component>
</mx:itemRenderer>
</s:List>
is there some way to do this WITHOUT itemrenderers? or is that the only way to go? was my attempt close at all to the proper way to implement a thumbnail image in the list component? Thanks for any help someone can provide here.
The code you provided mixes Spark and MX Components in such a way that I would expect compiler errors. For starters, you have these issues:
The mx:itemRenderer is the syntax used to define a property on a component. So, it is used to define the value for the itemRender property on the s:List component. This will cause a compiler error because the namespaces are different. You should specify s:itemRenderer instead.
The mx:Component is used to define a new in-line component. However, your namespace is wrong. With Flex 4.6 you should specify the fx namespace, not the mx namespace.
There are two components listed as children to the mx:Component tag, where their should only be 1. The solution in the MX world to this would be to wrap it the label and image in a container. In the Spark world, the itemRenderer must extend the ItemRenderer class.
For the text and source you are specifying string literals; not variables in your data element.
You have the right idea; but the wrong execution. Read this information on creating itemRenderers.
I would rework your code like this:
<s:List id="list1" x="0" y="108" width="320" height="355" change="list1_changeHandler(event)"
creationComplete="list1_creationCompleteHandler(event)" >
<s:AsyncListView list="{getDataResult.lastResult}"/>
<s:itemRenderer>
<fx:Component>
<s:ItemRenderer dataChange="onDataChange()">
<fx:Script>
<![CDATA[
protected function onDataChange():void{
labelDisplay.text =data.Itemname
imageDisplay.source = data.ItemImageURL
}
]]>
</fx:Script>
<s:HGroup>
<s:Label id="labelDisplay" />
<s:Image id="imageDisplay" />
</s:HGroup>
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>
This is untested code I wrote the browser; but it should demonstrate the correct approach. The namespaces are correct. There is a single component defined as the itemRenderer and it extends the ItemRenderer class. The displayed items should update when the itemRenderer data changes, such as when you scroll in the list. And the two items are positioned so that they do not display on top of each other.

How to set DefaultComplexItemRenderer background alpha to 0

I have a simple list with a tileLayout of images. From the examples I've looked at it looks like i'm supposed to use the DefaultComplexItemRenderer. It works, and my array of images loads fine, but each item has a solid background. I need the background behind each image to have an alpha of 0. How Can I set that?
In the past i've just made a custom itemRenderer, and overrided the drawBackground function on itemRenderers, but DefaultComplexRenderer doesn't have a drawBackground function to override.
Is there another simple solution in the flex code? OR it would be awesome if someone could show me how to make a custom DefaultComplexRenderer.
NOTE:
This is a Flex MOBILE project. I know some itemRenderer's aren't friendly with mobile. Adobe says to "always do item renderers in AS3 rather than mxml" so, keep that in mind.
Thanks!
Here's my code:
<fx:Declarations>
<s:ArrayList id="arrList">
<s:BitmapImage source="assets/images/one.png" scaleMode="letterbox" smooth="true" width="100%" height="100%"/>
<s:BitmapImage source="assets/images/two.png" scaleMode="letterbox" smooth="true" width="100%" height="100%"/>
<s:BitmapImage source="assets/images/three.png" scaleMode="letterbox" smooth="true" width="100%" height="100%"/>
<s:BitmapImage source="assets/images/four.png" scaleMode="letterbox" smooth="true" width="100%" height="100%"/>
</s:ArrayList>
</fx:Declarations>
<s:List id="extrasList_list" width="100%" height="100%"
dataProvider="{arrList}"
itemRenderer="spark.skins.spark.DefaultComplexItemRenderer"
horizontalCenter="0"
verticalCenter="0">
<s:layout>
<s:TileLayout requestedColumnCount="-1"
requestedRowCount="-1"
horizontalGap="10"
verticalGap="10"
orientation="rows"
columnAlign="justifyUsingWidth"
/>
</s:layout>
</s:List>
Things I've tried:
this in my main css file...
s|DefaultComplexItemRenderer {
contentBackgroundAlpha:0;
}
but i get this warning, and it doesn't work...
-Cannot resolve namespace qualified type 'DefaultComplexItemRenderer' in CSS selector 'DefaultComplexItemRenderer'
[Edit]
The contentBackgroundAlpha and contentBackgroundColor styles for a Flex List are somewhat misleading! You generally want to style the item renderers. In the context of a list, these styles only affect a tiny bit of "chrome" that can appear around the list. See below for details on styling the renderers.
If you just want to show an image, the IconItemRenderer is the way to go. It extends LabelItemRenderer so it's optimized for mobile and also has two text fields as well.
Flex List components recycle item renderers to be efficient, and only create as many renderers as needed to display what is currently visible. To do this, the list populates the renderer's data property. So you want to configure your item renderer using this data property.
An efficient way to do that is to override the setter function for data. Create a new Actionscript class that extends IconItemRenderer add this to it:
override public function set data(value:Object):void
{
super.data = value;
// IconItemRenderer already has a BitmapImage component, it's property name is iconDisplay
// your ArrayList should therefore only contain Strings representing the image sources
// note how I've changed your ArrayList in the declarations tag below
iconDisplay.source = data.imageSource;
}
You'll likely want to configure that iconDisplay BitmapImage to look how you want it. The method above may get called frequently, so you can put code that only needs to happen once somewhere else... by overriding a Flex component lifecycle method like createChildren():
override protected function createChildren():void
{
super.createChildren();
iconDisplay.scaleMode="letterbox";
iconDisplay.smooth=true;
}
Now tell the List to use your renderer w/syntax like this:
<s:List itemRenderer="com.yourdomain.or.whatever.MyIconItemRendererClass" />
Styling the renderer:
<s:List alternatingItemColors="[0xFFFFFF, 0xFFFFFF]" selectionColor="#FF0000" />
Another way is to override the mobile item renderer's drawBackground() and/or drawBorder() protected methods and draw your own stuff w/the graphics api (or nothing at all).
Supplying the data:
Instead of giving the list an array of BitmapImage components, you give it an array of objects that contain your data. It's better to use strongly typed objects, but this works too:
<fx:Declarations>
<s:ArrayList id="arrList">
<fx:Object imageSource="assets/images/one.png" />
<fx:Object imageSource="assets/images/two.png" />
<fx:Object imageSource="assets/images/three.png" />
</s:ArrayList>
</fx:Declarations>
I like writing renderers in Actionscript... But there is also an MXML example in the link to IconItemRenderer docs at the top. It also shows how you to set the values of the two text areas in this renderer (with labelField and messageField). You can also specify a function that returns the label/message/icon values (with labelFunction, messageFunction, and iconFunction).
Looks like you should be able to use setStyle('contentBackgroundAlpha', 0); on your DefaultComplexItemRenderer.
Not 100% this is what you're looking for, not really familiar with this class. Any reason you're using this over extending LabelItemRenderer?
edit
I believe you may want to extend IconItemRenderer
Check out this tutorial
http://www.youtube.com/watch?v=EOpsDZaQrOI
Thanks for trying to help guys, but I found the quickest/simple solution to be be just as simple as copying the DefaultComplexItemRender from the SDK into a custom one, and then changing this one line of code
autoDrawBackground="false"
It's simple and it worked.

resizing list components upon dataProvider change

I have a component that contains a list that implements a custom renderer. I use this component as a tooltip, keeping one in memory and just altering the databindings as necessary.
Something like this where TTComponent is a class that extends Canvas:
<s:TTComponent>
<s:BorderContainer>
<s:List id='lstItems' dataProvider="{data.Items}" width="50%" borderVisible="false" contentBackgroundColor="#222222">
<s:layout>
<s:VerticalLayout useVirtualLayout="false" requestedMinRowCount="1"/>
</s:layout>
<s:itemRenderer>
<fx:Component>
<s:ItemRenderer>
<s:HGroup>
<s:Label text="{data.Value}" paddingLeft="6" />
<s:Label text="{data.Name}" />
</s:HGroup>
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>
</s:BorderContainer>
</s:TTComponent>
Now, the driver code looks like this for the mouse over:
if (tt == null) {
tt = new TTComponent();
}
tt.data = data;
PopUpManager.addPopUp(tt, this);
And, of course, the mouse out:
PopUpManager.removePopUp(tt);
Now, what happens is when data containing many items is set to tt.data, the list resizes itself larger and displays fine. However, after this, if data containing few items is set to tt.data, the component momentarily displays larger than it needs to be, then resizes itself smaller.
What I'd like to do is have the component resize itself before it displays, so I don't see the resize on screen. Any idea on how to accomplish this?
First, I would compel you to consider creating the component once and just showing / hiding it / moving it when needed rather than using pop up manager. That's how I would typically do something similar to what you're attempting. It will perform better and probably fix this issue on its own. Just a thought.
Secondly, after you rebind new data to it, try these :
Tell it needs to resize :
tt.invalidateDisplayList();
Also, you might need to tell it you changed the data by refreshing the data if an ArrayCollection:
data.refresh();
Let me know if that doesn't do the trick.