In Flash Builder (flex 4) I try to use next code to set selected by user (from file system) Image as a repeated background. It worked with mx:Image but I want to use cool repited capabiletis of s:BitmapFill.
BTW: Technic I use also does not work with S:BitmapImage. Also FP does not return any errors. What Shall I do with my code to make it work?
<?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"
xmlns:net="flash.net.*"
minWidth="955" minHeight="600" >
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.utils.ObjectUtil;
private function btn_click(evt:MouseEvent):void {
var arr:Array = [];
arr.push(new FileFilter("Images", ".gif;*.jpeg;*.jpg;*.png"));
fileReference.browse(arr);
}
private function fileReference_select(evt:Event):void {
fileReference.load();
}
private function fileReference_complete(evt:Event):void {
img.source = fileReference.data;
Alert.show(ObjectUtil.toString(fileReference));
}
]]>
</fx:Script>
<fx:Declarations>
<net:FileReference id="fileReference"
select="fileReference_select(event);"
complete="fileReference_complete(event);" />
</fx:Declarations>
<s:Rect id="backgroundRect" left="0" right="0" top="0" bottom="0">
<s:fill>
<s:BitmapFill id="img" source="#Embed('1.jpg')" fillMode="repeat" />
</s:fill>
</s:Rect>
<mx:Button id="btn"
label="Browse and preview..."
click="btn_click(event);" />
</s:Application>
Check this code:
private function fileReference_complete(evt:Event):void {
var loader:Loader = new Loader();
loader.loadBytes(fileReference.data);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderCompleteHandler);
}
private function loaderCompleteHandler(evt:Event):void{
img.source = evt.target.content;
}
So you need to use a loader in order to create the bitmap object.
Related
I couldn't find a simple way to get remove or hide the caretIndicator in the Spark DataGrid so I'm posting the solution here if there's not a better way.
This seems to work. To hide the caretIndiator we have to create a new data grid skin based on spark.skins.spark.DataGridSkin. Then in that skin set the alpha of the stroke or alpha of the rect to 0.
Method 1:
MXML:
<s:DataGrid skinClass="view.skins.AbstractDataGridSkin"/>
AbstractDataGridSkin:
<?xml version="1.0" encoding="utf-8"?>
<spark:DataGridSkin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
xmlns:spark="spark.skins.spark.*"
xmlns:skins="view.skins.*"
>
<fx:Component id="caretIndicator">
<s:Rect implements="spark.components.gridClasses.IGridVisualElement" alpha="0">
<fx:Script>
<![CDATA[
import spark.components.DataGrid;
import spark.components.Grid;
/**
* #private
*/
public function prepareGridVisualElement(grid:Grid, rowIndex:int, columnIndex:int):void
{
const dataGrid:DataGrid = grid.dataGrid;
if (!dataGrid)
return;
const color:uint = dataGrid.getStyle("caretColor");
caretIndicatorFill.color = color;
}
]]>
</fx:Script>
<s:stroke>
<!--- #private -->
<s:SolidColorStroke id="caretIndicatorFill" color="0x0167FF" weight="0" alpha="0"/>
</s:stroke>
</s:Rect>
</fx:Component>
</spark:DataGridSkin>
Method 2:
There's another method that involves duplicating the default datagrid skin and removing the caretIndicator property. That ways probably better : P.
Method 3:
This also works:
<spark:DataGridSkin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
xmlns:spark="spark.skins.spark.*"
xmlns:skins="view.skins.*"
initialize="caretIndicator = null" />
I have this ViewNavigator inside a callout and the callout displays a view inside it using firstView="views.ListMenusHomeView" . Now how can I close the callout from ListMenusHomeView? Hope someone can help.
Here is my code for the callout:
<?xml version="1.0" encoding="utf-8"?>
<s:Callout xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
contentBackgroundAppearance="none"
height="300" width="300">
<fx:Declarations>
<fx:XML id="menu" source="xmldata/menu2.xml" />
</fx:Declarations>
<fx:Script>
<![CDATA[
import spark.events.PopUpEvent;
protected function back(event:MouseEvent):void {
if(viewNav.length>1)
viewNav.popView();
}
]]>
</fx:Script>
<s:ViewNavigator id="viewNav" width="100%" height="100%" firstView="views.ListMenusHomeView">
<s:navigationContent>
<s:Button label="Back" click="back(event)"/>
</s:navigationContent>
<s:actionContent>
<s:Button label="Cancel" click="close(false)" emphasized="true"/>
</s:actionContent>
</s:ViewNavigator>
</s:Callout>
You see that there is a ViewNavigator which holds the ListMenusHomeView. This is the code for the ListMenusHomeView.
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="Main Menu" creationComplete="onCreationComplete()">
<fx:Declarations>
<fx:XML id="menu" source="xmldata/menu2.xml" />
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.adobe.serializers.xml.XMLDecoder;
import mx.collections.ArrayCollection;
import spark.events.IndexChangeEvent;
[Bindable]
private var dataArray:ArrayCollection = new ArrayCollection();
private var object:DataArray = new DataArray();
private function onCreationComplete() : void{
var decoder:XMLDecoder = new XMLDecoder();
var resultObj:Object = decoder.decode(menu);
dataArray = object.onCreationComplete(menu, menu.menuitem, resultObj, resultObj.menuitem);
}
protected function list1_changeHandler(event:IndexChangeEvent):void
{
}
]]>
</fx:Script>
<s:List id="tileLayout"
width="100%" height="100%"
verticalScrollPolicy="off" horizontalScrollPolicy="on"
pageScrollingEnabled="true" dataProvider="{dataArray}"
itemRenderer="renderers.iconList2" change="list1_changeHandler(event)">
<s:layout>
<s:TileLayout orientation="columns" requestedRowCount="3"
verticalGap="20" horizontalGap="20"/>
</s:layout>
</s:List>
Now I want to close MyCallout whenever I click an icon inside ListMenusHomeView. The function list1_changeHandler(event:IndexChangeEvent) is responsible for that one.
What should I do?
The Callout class has a close() method, so you basically just need to access the ListMenusHomeViews parentDocument (which would be your "viewNav" ViewNavigator) and its parentDocument, which should be your ListMenusHomeView.
I haven't tested it but you might fiddle around with the parentDocument, parent and owner properties to access the correct object. Try them with a simple trace and you'll be up and running in no time.
I have following itemrenderer
<?xml version="1.0" encoding="utf-8"?>
<s:MXAdvancedDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" focusEnabled="true">
<s:Label id="lblData" top="0" left="0" right="0" bottom="0" text="{listData.label}" />
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
override public function set data(value:Object):void
{
if(value != null)
{
super.data = value;
if(value.age >30 )
lblData.setStyle("backgroundColor","red");
else
lblData.setStyle("backgroundColor","green");
}
//super.invalidateDisplayList();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
if(super.data)
{
}
}
]]>
</fx:Script>
</s:MXAdvancedDataGridItemRenderer>
My question is Should above logic go in updtaeDisplayList or remain in set data() itself.
The output is smae from both. Whats the performance impact difference if we consider it from lifecycle perspective.(The heavy computations should be pushed towards the end of the frame rendering)
In your way I'd rather use invalidateProperties() and commintProperties(). But what about using data binding?
<?xml version="1.0" encoding="utf-8"?>
<s:MXAdvancedDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" focusEnabled="true">
<s:Label top="0" left="0" right="0" bottom="0" text="{listData.label}" backgroundColor="{data.age > 30 ? `red` : `green`}" />
</s:MXAdvancedDataGridItemRenderer>
I just don't get it with [Bindable] and updating a label
So here are my three pages, please tell me what I am doing wrong because when the listner sends the updated var to button2.mxml the var updates but the label does not redraw it.
application.mxml
<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"
xmlns:comps="components.*"
creationComplete="init();">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
public function init(){
btn1.addEventListener(MouseEvent.MOUSE_OVER, myFunction);
}
public function myFunction(e:MouseEvent){
var myPage:button2 = new button2();
var ranNum = Math.floor(Math.random() * 40) + 10;
myPage.myValue("ABC "+ranNum);
}
]]>
</fx:Script>
<comps:button1 y="0" id="btn1" width="100"/>
<comps:button2 y="100" id="btn2" width="100"/>
button1.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group 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="128" height="72">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button x="27" y="19" label="Button1" id="btn1" enabled="true"/>
</s:Group>
button2.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group 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="400" height="300">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
[Bindable]
public var myVal:String = "Button2";
public function myValue(mV:String)
{
myVal = mV;
}
]]>
</fx:Script>
<s:Button x="10" y="32" label="{myVal}" id="btn2" enabled="true"/>
</s:Group>
Your function should be:
public function myFunction(e:MouseEvent){
var ranNum = Math.floor(Math.random() * 40) + 10;
btn2.myValue("ABC " + String(ranNum));
}
In the function that you have, you are creating a new button (without adding it as a child to anything) and setting the label on that button rather than the one you have already defined in your application.
You also do not necessarily need a [Bindable] variable for the label in button2.mxml but this depends on what you are accomplishing. You could just do btn2.label = mV; in the myValue() function definition alternatively.
The simplest way to do this is to remove your setter for myVal in button2.mxml and just set the value in myFunction like you would any other public variable:
myPage.myVal = "ABC " + ranNum;
The reason your code is not currently working is that you have implicitly overridden the myVal setter and are not dispatching a data change event, which is what makes binding work. When you add the [Bindable] metadata tag to a variable, the compiler automatically generates a setter for that variable with the proper event dispatching for you.
Hope that helps.
In my example below, when I click "Add Content", new stack content is loaded into the ViewStack as expected. But when I then click "Close Content", I'm expecting it to close the newly created content inside the ViewStack and switch to the "defaultContent" content.
Can anyone tell me where I'm going wrong please? Thanks in advance.
// TestProject.mxml (application)
<?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">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import com.NewContent;
private function addContent():void
{
var content:NewContent = new NewContent();
var navContent:NavigatorContent = new NavigatorContent();
navContent.id = 'newContent';
navContent.label = 'newContent';
navContent.width = Number('100%');
navContent.height = Number('100%');
navContent.addElement(content);
viewStack.addElement(navContent);
viewStack.selectedChild = navContent;
}
]]>
</fx:Script>
<mx:ViewStack id="viewStack" width="100%" height="100%">
<s:NavigatorContent id="defaultContent"
label="defaultContent">
<s:Button click="addContent()" label="Add Content"/>
</s:NavigatorContent>
</mx:ViewStack>
</s:WindowedApplication>
// NewContent.mxml (component)
<?xml version="1.0" encoding="utf-8"?>
<s:Group 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="100%" height="100%">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
private function closeContent():void
{
FlexGlobals.topLevelApplication.viewStack.removeChild('newContent');
FlexGlobals.topLevelApplication.viewStack.selectedChild = 'defaultContent';
}
]]>
</fx:Script>
<s:Button click="closeContent()" label="Close Content"/>
</s:Group>
selectedChild expects the child itself, not the label.
Instead - try this:
public function removeContent():void
{
Viewstack(this.parent).selectedIndex = 0;
this.parent.removeChild(this);
}
Note - it's generally reccomended to avoid using FlexGlobals.topLevelApplication, as it leads to a very tightly coupled & fragile application.
Sorted it...
// TestProject.mxml (application)
private function addContent():void
{
var content:NewContent = new NewContent();
content.addEventListener("removeMe",onRemove,false,0,true);
var navContent:NavigatorContent = new NavigatorContent();
navContent.id = 'newContent';
navContent.label = 'newContent';
navContent.width = Number('100%');
navContent.height = Number('100%');
navContent.addElement(content);
viewStack.addElement(navContent);
viewStack.selectedChild = navContent;
private function onRemove(event:Event):void
{
var content:NewContent = event.currentTarget as NewContent;
content.removeEventListener("removeMe",onRemove,false);
viewStack.removeChild(content.parent.parent.parent);
}
// NewContent.mxml (component)
public function removeContent():void
{
dispatchEvent(new Event("removeMe"));
}