Can not move my custom component based on HGroup - apache-flex

I have created a custom component based on spark.components.HGroup and it works mostly as needed, but I have this minor problem: I can not move it.
Maybe someone will look at my simplified test case below and spot my error?
Here is the screenshot of my 3 custom components, representing chat bubbles:
Here my custom component Bubble.mxml drawing black text on green background:
<?xml version="1.0" encoding="utf-8"?>
<s:HGroup
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
gap="0"
creationComplete="init(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
private static const PAD:uint = 10;
private static const BGCOLOR:uint = 0xCCFFCC;
private static const BGALPHA:Number = 0.8;
private var _timer:Timer = new Timer(600, 20);
public function init(event:FlexEvent):void {
_timer.addEventListener(TimerEvent.TIMER, fadeBubble);
_timer.addEventListener(TimerEvent.TIMER_COMPLETE, hideBubble);
addEventListener(MouseEvent.CLICK, hideBubble);
}
public function set text(str:String):void {
_text.text = str;
if (x > 100 && x < 200) {
_left.visible = true;
_right.visible = false;
} else {
_left.visible = false;
_right.visible = true;
}
visible = true;
alpha = 1.0;
_timer.reset();
_timer.start();
}
public function get text():String {
return _text.text;
}
private function fadeBubble(event:TimerEvent):void {
if (_timer.currentCount * 2 > _timer.repeatCount)
alpha /= 2;
}
// the argument could be TimerEvent or MouseEvent
public function hideBubble(event:Event):void {
visible = false;
_timer.stop();
}
]]>
</fx:Script>
<s:Graphic id="_left" visible="false">
<s:Path data="M 20 10 L 0 20 L 20 30">
<s:fill>
<s:SolidColor color="{BGCOLOR}" alpha="{BGALPHA}" />
</s:fill>
</s:Path>
</s:Graphic>
<s:Label id="_text" width="100%"
paddingTop="{PAD}" paddingBottom="{PAD}"
paddingLeft="{PAD}" paddingRight="{PAD}"
fontSize="24" textAlign="center"
backgroundColor="{BGCOLOR}" backgroundAlpha="{BGALPHA}" />
<s:Graphic id="_right" visible="false">
<s:Path data="M 0 10 L 20 20 L 0 30">
<s:fill>
<s:SolidColor color="{BGCOLOR}" alpha="{BGALPHA}" />
</s:fill>
</s:Path>
</s:Graphic>
</s:HGroup>
Here is my text application Test.mxml which uses absolute positioning:
<?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:comps="*"
width="700" height="525">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
private static const AVATAR:String =
'http://preferans.de/images/70x90/male_happy_70x90.png';
public static function randRange(from:int, to:int):int {
return from + Math.round((to - from) * Math.random());
}
public function chat(event:FlexEvent):void {
_bubble0.y = 340 + randRange(-20, 20);
_bubble1.y = 4 + randRange(0, 40);
_bubble2.y = 4 + randRange(0, 40);
trace('_bubble0.y = ' + _bubble0.y);
trace('_bubble1.y = ' + _bubble1.y);
trace('_bubble2.y = ' + _bubble2.y);
_bubble0.text = _chat.text;
_bubble1.text = _chat.text;
_bubble2.text = _chat.text;
_chat.text = '';
}
]]>
</fx:Script>
<s:Image id="_user0" source="{AVATAR}" horizontalCenter="20" y="340" width="160" height="140" />
<s:Image id="_user1" source="{AVATAR}" left="4" top="4" width="160" height="140" />
<s:Image id="_user2" source="{AVATAR}" right="4" top="4" width="160" height="140" />
<comps:Bubble id="_bubble0" maxWidth="200" x="20" y="340" />
<comps:Bubble id="_bubble1" maxWidth="200" left="170" top="4" />
<comps:Bubble id="_bubble2" maxWidth="200" right="170" top="4" />
<s:TextInput id="_chat" bottom="4" right="4" enter="chat(event)" text="Hello!" />
</s:Application>
In the debug console I do see the varying y coordinates:
_bubble0.y = 350
_bubble1.y = 31
_bubble2.y = 36
_bubble0.y = 340
_bubble1.y = 43
_bubble2.y = 15
but at the screen they never change!

The problem is that _bubble1 and _bubble2 are positioned with constraints (left="170" top="4"). Flex ignores the x and y properties because the constraints have a higher priority than absolute positioning with x and y.
Try removing the left="170" top="4" from both components and you'll see they change positions as expected.
Hope this helps,
Blaze

Related

SkinnablePopUpContainer Is Visually Blocked by StageWebView in Flex

For some unknown reason, my popup AlertMsg is visually blocked by the StageWebView:
<?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" applicationDPI="160" xmlns:local="*"
creationComplete="application1_creationCompleteHandler(event)"
backgroundColor="#112233">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import mx.events.FlexEvent;
public var webView:StageWebView = new StageWebView();
public function StageWebViewExample():void
{
webView.stage = webContainer.stage;
// webView.viewPort = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight );
webView.viewPort = new Rectangle( 100, 100, 500, 500 );
}
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
webContainer.addEventListener(Event.ADDED_TO_STAGE, function(ee:Event):void {
StageWebViewExample();
});
}
protected function btnTest_clickHandler(event:MouseEvent):void
{
webView.loadURL("http://www.example.com");
new AlertMsg().open(FlexGlobals.topLevelApplication as DisplayObjectContainer, true);
}
]]>
</fx:Script>
<fx:Declarations>
<fx:Component className="AlertMsg">
<s:SkinnablePopUpContainer x="70" y="300">
<s:TitleWindow title="My Message" close="close()">
<s:VGroup horizontalAlign="center" paddingTop="8" paddingBottom="8" paddingLeft="8" paddingRight="8" gap="5" width="100%">
<s:Label text="My alert message text here..."/>
<s:Button label="OK" click="close()"/>
</s:VGroup>
</s:TitleWindow>
</s:SkinnablePopUpContainer>
</fx:Component>
</fx:Declarations>
<s:Panel id="thePanel" title="Panel" backgroundColor="blue">
<s:Button id="btnTest" label="Test"
click="btnTest_clickHandler(event)" />
<s:BorderContainer id="webContainer" y="50" width="400" height="300" />
</s:Panel>
</s:Application>
Any idea?
I absolutly agree with #www.Flextras.com, there is no another workaround than substitute WebView by its snapshot. There is a ready solution http://www.judahfrangipane.com/blog/2011/01/16/stagewebview-uicomponent/

Adobe Flex : Popup dialog not sizing correctly

I have a popup dialog that is an mx:TitleWindow. The rendered height of the dialog is too large however, see the whitespace at the bottom. Decreasing the height by x pixels seems to have no effect. How do I get it to size correctly?
<mx:TitleWindow 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="356" height="322"
layout="vertical" showCloseButton="true" close="cancel(event)"
title="Add User" creationComplete="usernameTF.setFocus();"
hasFocusableChildren="true">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.adobe.crypto.SHA1;
import com.hurlant.crypto.hash.SHA1;
import mx.controls.Alert;
import mx.events.CloseEvent;
import mx.events.FlexEvent;
import mx.managers.PopUpManager;
[Bindable]
public var mainApp:Object = null;
protected function apply_clickHandler(event:MouseEvent):void {
if (usernameTF.text == null || usernameTF.text.length < 1) {
usernameTF.errorString = "The username is mandatory";
width = 520;
return;
}
else if (mainApp.userExists(usernameTF.text)) {
usernameTF.errorString = "Username already exists";
width = 520;
return;
}
else {
usernameTF.errorString = "";
}
if (passwordTF.text == null || passwordTF.text.length < 1) {
passwordTF.errorString = "The password is mandatory";
width = 520;
return;
}
else {
passwordTF.errorString = "";
}
if (confirmTF.text == null || confirmTF.text.length < 1) {
confirmTF.errorString = "The confirmation password is mandatory";
width = 520;
return;
}
else {
confirmTF.errorString = "";
}
if (passwordTF.text != confirmTF.text) {
passwordTF.errorString = "The passwords must match";
width = 520;
return;
}
else {
passwordTF.errorString = "";
}
var u:Object = new Object();
u.username = usernameTF.text;
u.password = com.adobe.crypto.SHA1.hash(passwordTF.text);
u.accesslevel = accessLevelCB.selectedItem;
mainApp.addUserToModel(u);
mainApp.applyHandler(null);
}
protected function cancel(event:Event):void {
PopUpManager.removePopUp(this);
}
]]>
</fx:Script>
<s:Form height="280" defaultButton="{apply}">
<s:layout>
<s:FormLayout gap="{Globals.FORM_GAP}"/>
</s:layout>
<s:FormHeading label="Add User"/>
<s:FormItem label="Username:">
<s:TextInput id="usernameTF" restrict="0-9A-Za-z_." maxChars="127"/>
</s:FormItem>
<s:FormItem label="Password:">
<s:TextInput maxChars="127" id="passwordTF" displayAsPassword="true"/>
</s:FormItem>
<s:FormItem label="Confirm Password:">
<s:TextInput maxChars="127" id="confirmTF" displayAsPassword="true"/>
</s:FormItem>
<s:FormItem label="Access Level:">
<s:ComboBox id="accessLevelCB" selectedIndex="0">
<s:dataProvider>
<mx:ArrayList>
<fx:String>user</fx:String>
<fx:String>admin</fx:String>
</mx:ArrayList>
</s:dataProvider>
</s:ComboBox>
</s:FormItem>
<s:FormItem>
<s:HGroup>
<s:Button id="apply" label="Apply" click="apply_clickHandler(event)" />
<s:Spacer width="3"/>
<s:Button label="Cancel" click="cancel(event)"/>
</s:HGroup>
</s:FormItem>
</s:Form>
Decreasing the height by x pixels
Which height are you decreasing?
<mx:TitleWindow 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="356" height="322"
layout="vertical" showCloseButton="true" close="cancel(event)"
title="Add User" creationComplete="usernameTF.setFocus();"
hasFocusableChildren="true">
<s:Form height="280" defaultButton="{apply}">
In the code you show I would expect the height of the box to be 322. The form would be 280; which leaves ~42 pixels of whitespace at the bottom.

Unknown error with <mx:Repeater> in Flex Builder 4.5.1 Mobile

I recently learned how to work with API's in Flash Builder. So I made this (note: it has no errors and it works in a normal Flex application:
<?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"
width="957" minWidth="800" minHeight="600"
creationComplete="initApp(event)">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<s:HTTPService id="myRequest"
resultFormat="e4x"
url="{api_request}"
result="getMyPhotos(event)">
</s:HTTPService>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.XMLListCollection;
import mx.events.FlexEvent;
import mx.rpc.events.ResultEvent;
[Bindable]
public var api_request:String;
protected function initApp(event:FlexEvent):void
{
btnClear.addEventListener(MouseEvent.CLICK, leegAlleVelden);
btnSearch.addEventListener(MouseEvent.CLICK, zoekOpFlickr);
flickrFotoCollection.addEventListener(MouseEvent.CLICK, haalFoto);
}
protected function zoekOpFlickr(event:MouseEvent):void
{
var api_URL:String = 'http://api.flickr.com/services/rest/';
var api_method:String = 'flickr.photos.search';
var api_key:String = '290845e3c32e4e10a9e4b09fd993ddb9';
var api_tags:String = txtSearchString.text;
api_request = api_URL + '?method=' + api_method +
'&api_key=' + api_key + '&tags=' + api_tags;
myRequest.send(); // hier maak je connectie met flickr
}
//http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=290845e3c32e4e10a9e4b09fd993ddb9&tags=cat&format=rest&api_sig=93e43cc21b7209d2e59af67736d27eb3
protected function leegAlleVelden(event:MouseEvent):void
{
txtSearchString.text="";
}
protected function getMyPhotos(event:ResultEvent):void
{
//photos allemaal ingelezen
flickrFotoCollection.dataProvider = new XMLListCollection(myRequest.lastResult.photos.photo);
}
public function haalFoto(selectedFoto:Object):String {
// http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[mstb].jpg
var farm_id:String = selectedFoto.#farm;
var server_id:String = selectedFoto.#server;
var id:String = selectedFoto.#id;
var secret:String = selectedFoto.#secret;
var size:String = 't';
var api_selectedPhotoURL:String = "http://farm"+farm_id+".static.flickr.com/"+server_id+
"/"+id+"_"+secret+"_"+size+".jpg";
return api_selectedPhotoURL;
}
public function toonFoto(event:MouseEvent):void
{
}
]]>
</fx:Script>
<s:BorderContainer x="0" y="21" width="800" height="100%" backgroundColor="#000000">
<s:HGroup x="30" y="14">
<s:TextInput x="0" y="23" width="267" id="txtSearchString"/>
<s:Button x="289" y="24" label="Search" id="btnSearch" click="zoekOpFlickr(event);"/>
<s:Button x="394" y="24" label="Clear" id="btnClear" click="leegAlleVelden(event);"/>
</s:HGroup>
<s:HGroup x="30" y="54" width="742" height="500">
<mx:Tile width="399" height="500">
<mx:Repeater id="flickrFotoCollection" dataProvider="{myRequest.lastResult.photos.photo}">
<s:Image id="fotoKlein"
source="{haalFoto(flickrFotoCollection.currentItem)}"
click="toonFoto(event);"
width="80" height="80"
scaleMode="stretch"/>
</mx:Repeater>
</mx:Tile>
<s:Image id="fotoGroot" width="336" height="500"/>
</s:HGroup>
</s:BorderContainer>
</s:Application>
Next, I wanted to see if I could get it to work in a 4.5.1 mobile application. I didn't get any errors except for a "could not resolve <mx:Repeater>..." At line 87. So for some reason it doesn't recognize the <mx:Repeater> tag?
I tried to find the cause of this problem, but didn't find it.
Is there a reason why it works in a normal application, but not in a mobile application?
The MX Components are not supported in a Mobile Project. For that code to compile in a Flash Builder mobile project you will have to manually add the SWC with MX components to the library path. Be prepared for poor performance, though.

Flex 4 Move Effect only animating last target in array of multiple items

I am animating a number of items using the Move effect. I am adding each item to an array after it has been added to the display list and once all items are added calling the play method, passing an array of the items to it.
Only the last item plays in my animation.
Here is my code:
MXML: s:Move id="coinFall" yFrom="-400" duration="2000" />
public function showCoins(n:Number):void{
holder.removeAllElements();
var targets:Array = [];
if (n>=2.5){
var coins:uint = Math.round(n/2.5);
for (var i:uint = 0; i<coins; i++){
var c:Coin = new Coin();
c.y = 0 - (i*15);
holder.addElement(c);
targets.push(c);
}
coinFall.play(targets);
}
}
Any help much appreciated.
Thanks
It's hard to tell without more complete code, but this sample works for me:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Declarations>
<s:Move id="coinFall" yBy="100" duration="2000" />
<fx:Component className="Coin">
<s:Ellipse width="50" height="50">
<s:fill>
<s:SolidColor color="red" />
</s:fill>
</s:Ellipse>
</fx:Component>
</fx:Declarations>
<fx:Script>
<![CDATA[
public function showCoins(n:Number):void{
holder.removeAllElements();
var targets:Array = [];
for (var i:uint = 0; i<n; i++){
var c:Coin = new Coin();
c.x = i*50;
c.y = 0 - i*10;
holder.addElement(c);
targets.push(c);
}
coinFall.play(targets);
}
]]>
</fx:Script>
<s:controlBarContent>
<s:Button label="play" click="showCoins(5)" />
</s:controlBarContent>
<s:Group id="holder" />
</s:Application>
I would suggest looking into using yBy/yTo on the Move effect.

Fitting Flex Image in Canvas

How do I scale an Image in Flex to fit a Canvas? My code follows:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
horizontalAlign="center"
width="100" height="100"
verticalGap="0" borderStyle="solid"
initialize="onLoad()"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:Canvas width="100%" height="100%" id="PictureBox" horizontalScrollPolicy="off"
verticalScrollPolicy="off" />
<mx:Label id="NameLabel" height="20%" width="100%"/>
<mx:Script>
<![CDATA[
private function onLoad():void
{
var image:SmoothImage = data.thumbnail;
image.percentHeight = 100;
image.percentWidth = 100;
this.PictureBox.addChild(image);
var sizeString:String = new String();
if ((data.fr.size / 1024) >= 512)
sizeString = "" + int((data.fr.size / 1024 / 1024) * 100)/100 + " MB";
else
sizeString = "" + int((data.fr.size / 1024) * 100)/100 + " KB";
this.NameLabel.text = data.name + " \n" + sizeString;
}
]]>
</mx:Script>
</mx:VBox>
I am trying to get the image:SmoothImage into PictureBox and scaling it down.
Note SmoothImage derives from Image.
you need to make sure you have set
image.scaleContent = true;
image.maintainAspectRatio = false;
That should scale the content to the size of the swf loader and distortin it so it fills the entire area of the Image component.
Here's a quick version of it working
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
horizontalAlign="center"
width="100" height="100"
verticalGap="0" borderStyle="solid"
initialize="onLoad()"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:Canvas width="100%" height="100%" id="PictureBox" horizontalScrollPolicy="off"
verticalScrollPolicy="off" />
<mx:Label id="NameLabel" height="20%" width="100%"/>
<mx:Script>
<![CDATA[
import mx.controls.Image;
private function onLoad():void
{
var image : Image = new Image()
image.source = "http://i.stackoverflow.com/Content/Img/stackoverflow-logo-250.png";
image.scaleContent = true;
image.maintainAspectRatio =false;
image.percentWidth = 100;
image.percentHeight = 100;
PictureBox.addChild(image);
}
]]>
</mx:Script>
</mx:VBox>

Resources