Reputation: 22988
I'm porting a Flash game to Flex.
In the original Flash game, when a player would chat something, I assign that text to a TextField (which had a harcoded width W=240 and wordWrap=true, multiline=true). After that I use the TextField's textHeight to draw a rectangle around (and underneath) it:
public function set text(str:String):void {
_tf.text = str;
_tf.height = _tf.textHeight + 2 * PAD;
// draw the rectangle around the TextField
_rect.x = _tf.x - PAD;
_rect.y = _tf.y - PAD;
_rect.graphics.clear();
_rect.graphics.beginFill(BGCOLOR, 0.8);
_rect.graphics.drawRoundRect(0, 0, _tf.textWidth + 2 * PAD, _tf.textHeight + 2 * PAD, R);
_rect.graphics.endFill();
_fadeTimer.reset();
_fadeTimer.start();
}
In my new Flex app however I don't know, how to find Label dimensions and how to make it grow with the text.
Here is my test case, which doesn't work as wished (but it runs in Flash Builder ok).
Does anybody please have any suggestions, I've searched a lot.
BubbleTest.mxml:
<?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" backgroundColor="#CCCCCC"
creationComplete="init()">
<fx:Script>
<![CDATA[
public function init():void {
_bubble0.text = 'Hello world';
}
]]>
</fx:Script>
<s:Rect id="_user0" horizontalCenter="0" y="340" width="160" height="140">
<s:stroke>
<s:SolidColorStroke color="red" />
</s:stroke>
</s:Rect>
<s:Rect id="_user1" left="4" top="4" width="160" height="140">
<s:stroke>
<s:SolidColorStroke color="red" />
</s:stroke>
</s:Rect>
<s:Rect id="_user2" right="4" top="4" width="160" height="140">
<s:stroke>
<s:SolidColorStroke color="red" />
</s:stroke>
</s:Rect>
<comps:Bubble id="_bubble0" x="20" y="340" />
<comps:Bubble id="_bubble1" left="170" top="4" />
<comps:Bubble id="_bubble2" right="170" top="4" />
</s:Application>
Bubble.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"
creationComplete="init(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
public static const W:uint = 240;
private static const R:uint = 6;
private static const PAD:uint = 4;
private static const BGCOLOR:uint = 0xCCFFCC;
private var _timer:Timer = new Timer(500, 20);
public function init(event:FlexEvent):void {
_timer.addEventListener(TimerEvent.TIMER, fadeBubble);
_timer.addEventListener(TimerEvent.TIMER_COMPLETE, hideBubble);
addEventListener(MouseEvent.CLICK, hideBubble);
if (x > 100 && x < 200) {
_left.visible = true;
_right.visible = false;
} else {
_left.visible = false;
_right.visible = true;
}
}
public function set text(str:String):void {
_text.setStyle('color', Util.isRed(str) ? 0xFF0000 : 0x000000);
_text.text = str;
// XXX resize _rect here, but how?
_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;
}
public function hideBubble(event:MouseEvent):void {
visible = false;
_timer.stop();
}
]]>
</fx:Script>
<s:Graphic id="_right" x="{W}" y="0">
<s:Path data="L 0 10
L 20 20
L 0 30">
<s:fill>
<s:SolidColor color="{BGCOLOR}" />
</s:fill>
</s:Path>
</s:Graphic>
<s:Graphic id="_left" x="0" y="0">
<s:Path data="L 0 10
L -20 20
L 0 30">
<s:fill>
<s:SolidColor color="{BGCOLOR}" />
</s:fill>
</s:Path>
</s:Graphic>
<s:Rect id="_rect" x="0" y="0" width="{W}" height="120" radiusX="{R}" radiusY="{R}">
<s:fill>
<s:SolidColor color="{BGCOLOR}" />
</s:fill>
</s:Rect>
<s:Label id="_text" x="0" y="75" width="{W}" fontSize="16" textAlign="center" />
</s:Group>
Sofar I've only got 2 ideas:
1) Somehow get ahold of Label's mx_internal TextField
import mx.core.mx_internal;
use namespace mx_internal;
// XXX and then?
2) Use a <mx:UIComponent id="uic"/> and addChild() my own TextField to it
but maybe there are more painless ways?
Upvotes: 1
Views: 1050
Reputation: 600
You will have to change the way you think about layouts a bit if you use flex. What you want to do is set the rectangles to be percentage based width and set the absolute width on nothing. What this allows the layout to do is what is called "Size to Content" meaning, its width will be determined by its children. Then the items that use percentage based width will look at that value and lay themselves out. A bit hard to explain through words so I pasted the new Bubble.mxml here for you to take a look. It probably isn't the exact look you want but this should get you started and will only take a little tweaking to get it exactly how you want.
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
//public static const W:uint = 240;
private static const R:uint = 6;
private static const PAD:uint = 4;
private static const BGCOLOR:uint = 0xCCFFCC;
private var _timer:Timer = new Timer(500, 20);
public function init(event:FlexEvent):void {
_timer.addEventListener(TimerEvent.TIMER, fadeBubble);
_timer.addEventListener(TimerEvent.TIMER_COMPLETE, hideBubble);
addEventListener(MouseEvent.CLICK, hideBubble);
if (x > 100 && x < 200) {
_left.visible = true;
_right.visible = false;
} else {
_left.visible = false;
_right.visible = true;
}
}
public function set text(str:String):void {
//_text.setStyle('color', Util.isRed(str) ? 0xFF0000 : 0x000000);
_text.text = str;
// XXX resize _rect here, but how?
_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;
}
public function hideBubble(event:MouseEvent):void {
visible = false;
_timer.stop();
}
]]>
</fx:Script>
<s:Graphic id="_right">
<s:Path data="L 0 10
L 20 20
L 0 30">
<s:fill>
<s:SolidColor color="{BGCOLOR}" />
</s:fill>
</s:Path>
</s:Graphic>
<s:Graphic id="_left" x="0" y="0">
<s:Path data="L 0 10
L -20 20
L 0 30">
<s:fill>
<s:SolidColor color="{BGCOLOR}" />
</s:fill>
</s:Path>
</s:Graphic>
<s:Rect id="_rect" x="0" y="0" width="100%" height="100%" radiusX="{R}" radiusY="{R}">
<s:fill>
<s:SolidColor color="{BGCOLOR}" />
</s:fill>
</s:Rect>
<s:Label id="_text" x="0" paddingTop="5" paddingBottom="5" fontSize="16" textAlign="center" />
Upvotes: 2