Trying to draw a Rectangle to a Custom Container in Flex4/AS3 - apache-flex

So below is the code I have so far. For now I simply want to make it draw a square and have it show up. Right now when I click the area defined in MXML as <components:PaintArea width="100%" height="100%" id="paint-a"></PaintArea> it shows nothing; however, the actionlistener is getting triggered and an element is being added to the group. Not sure exactly what is going on... perhaps for some reason it doesn't think the element is drawable? Anyways thanks for the help!
public class PaintArea extends SkinnableContainer
{
private var canvas:Group;
public function PaintArea()
{
super();
canvas = new Group();
canvas.clipAndEnableScrolling = true;
canvas.percentHeight = 100;
canvas.percentWidth = 100;
canvas.addEventListener(MouseEvent.MOUSE_UP,drawRectangle);
this.addElement(canvas);
}
private function drawRectangle(e:MouseEvent):void{
var r:Rect = new Rect();
r.fill = new SolidColor(0x00ff00,.5);
canvas.addElement(r);
}
}

You should probably set the width and height of the rectangle r.

You could also use a BorderContainer (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/components/BorderContainer.html) - its a SkinnableContainer with a styleable border and fill

Related

Scroll inside an item renderer result in an empty item

I'm developing a mobile app. I have a view with an horizontal list, each item has a long description so I would need a vertical scroll for that independent information. I'm trying to add an scroll as a Child of an itemRenderer. And I dont get it. Anyone knows what I'm doing bad?
I have a class with inheritance of ItemRenderer (I tried BaseRenderer from AsFusion too, that it seems to have more performance for mobile apps, with the same result).
And here is the part of the scroll from my code:
override protected function createChildren():void
{
super.createChildren();
scroller = new VScrollBar();
scroller.percentHeight = 100;
scroller.setStyle('right', 0);
scrollGroup = new Group();
scrollGroup.percentHeight = 100;
scrollGroup.percentWidth = 100;
super.addElement(scroller);
super.addElement(scrollGroup);
scroller.viewport = scrollGroup;
}
I also tried
override protected function createChildren():void
{
super.createChildren();
scroller = new Scroller();
scroller.percentHeight = 100;
scroller.percentWidth = 100;
scrollGroup = new Group();
scrollGroup.percentHeight = 100;
scrollGroup.percentWidth = 100;
super.addElement(scroller);
super.addElement(scrollGroup);
scroller.viewport = scrollGroup;
}
And the result is the same. An empty item in the list. I can change page (pagesnapping of the list horizontal scroll) and the next item is also empty. If I delete addElement(scroller) I can see the items perfectly, but without the vertical scroll that I really need. So the problem is in the scroller. Any idea what I'm doing so bad?? Please? I need the solution in actionscript, I have more itemrenderers done and I will make inheritance, and the performance for the mobile is better in actionscript. Thank you in advance.
I've never used scroll bars in an item renderer... But you might check out the Scroller component? Something like this:
<s:ItemRenderer>
<s:Scroller width="100%" height="100%">
<s:Group>
<Your_components_here />
</s:Group>
</s:Scroller>
</s:ItemRenderer>
Not sure if it would behave any different though.
In order to work, scrolls need an actual width and height. It seems that the groups you're passing are actually empty, although they do have a set percentWidth. Add content into them.
If you're scrolling text, it might be more viable to use the built in scroll of the TextArea.
I solved, with the guidance of Grigorash Vasilij I noticed that the content of the scroller was not showing because in the group the content size was 0 and private visible variable was false. So the percent sizes of the scroller was not working, I updated it in the method updateDisplayList.
override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
{
super.updateDisplayList( unscaledWidth, unscaledHeight );
scroller.width = unscaledWidth;
scroller.height = unscaledHeight;
...
}
After that, the scroller was horizontal, then the horizontal scroll wasn't work, I wanted a verticalScroll if needed in the item Renderer, so after the constructor of Scroller I set the horizontalPolicy of the scroll equal to off. The result is the next:
override protected function createChildren():void
{
super.createChildren();
scroller = new Scroller();
scroller.percentHeight = 100;
scroller.percentWidth = 100;
scroller.setStyle("horizontalScrollPolicy", "off");
scrollGroup = new Group();
scrollGroup.percentHeight = 100;
scrollGroup.percentWidth = 100;
addChild(scrollGroup);
scroller.viewport = scrollGroup;
addChild(scroller);
}
My class is inheriting of BaseRenderer from Asfusion If you inherit of itemrenderer use addElement instead of addChild.

Flex: Custom composite component in ActionScript -- problems with percentWidth/percentHeight

I've done tons of research and read the Adobe Live Docs till my eyes bled trying to figure this out.
I am building a composite custom component in ActionScript, and would like the sub controls to be laid out horizontally. This works fine by adding them to an HGroup and adding HGroup to the component, the problem comes with percentage based sizing.
I need _horizontalGroup:HGroup to size it self based on the size of its container.
stepping through the code shows that the parent properties of each UIComponent are...
_horizontalGroup.parent = ReportGridSelector
ReportGridSelector.parent = grpControls
If grpControls has an explicit size, shouldn't ReportGridSelector have its size as well?
The custom component is implemented like this...
NOTE: ReportControl extends UIComponent and contains no sizing logic
public class ReportGridSelector extends ReportControl{
/*other display objects*/
private var _horizontalGroup:HGroup;
public function ReportGridSelector(){
super();
percentHeight = 100;
percentWidth = 100;
}
override protected function createChildren():void{
super.createChildren();
if(!_horizontalGroup){
_horizontalGroup = new HGroup();
//I WANT SIZE BY PERCENTAGE, BUT THIS DOESN'T WORK
_horizontalGroup.percentWidth = 100;
_horizontalGroup.percentHeight = 100;
//EXPLICITLY SETTING THEM WORKS, BUT IS STATIC :-(
//_horizontalGroup.width = 200;
//_horizontalGroup.height = 200;
addChild(_horizontalGroup);
}
}
}
Consuming MXML code
<?xml version="1.0" encoding="utf-8"?>
<s:VGroup id="grpControls" width="200" height="200">
<ReportControls:ReportGridSelector width="100%" height="100%"/>
</s:VGroup>
If I explicitly define _horizontalGroup's width and height properties, everything displays fine. If I try _horizontalGroup.percentWidth or percentHeight, all the controls get scrunched together.
Any thoughts as to what is going on?
Perform layout when the display list is invalidated from updateDisplayList.
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
_horizontalGroup.width = unscaledWidth;
_horizontalGroup.height = unscaledHeight;
}
Understand the Flex component lifecycle:
http://livedocs.adobe.com/flex/3/html/help.html?content=ascomponents_advanced_2.html
createChildren
Creates any child components of the component. For example, the
ComboBox control contains a TextInput control and a Button control as
child components.
For more information, see Implementing the createChildren() method.
updateDisplayList
Sizes and positions the children of the component on the screen based
on all previous property and style settings, and draws any skins or
graphic elements used by the component. The parent container for the
component determines the size of the component itself.

errorTip on Flex ComboBox

I have a tooltip on a ComboBox but I much prefer the styling of the errorTip
(with the "tail").
I have replaced the tooltip with an errorTip, but now the ComboBox has a red
border.
I'm still pretty much a newb... is there a way to override the red border on the
ComboBox so that its' border is back to good ol' black?
thanks,
Mark
You'd probably want to create your own custom tooltip as errorTip is reserved for the validation system.
There's some info here about how to create your own. It's fairly straightforward if you want something simple.
Here's something I've used in the past:
The Actionscript:
private var infoToolTip:ToolTip;
private function showToolTip(evt:MouseEvent, text:String):void
{
var pt:Point = new Point(evt.currentTarget.x, evt.currentTarget.y);
// Convert the targets 'local' coordinates to 'global' -- this fixes the
// tooltips positioning within containers.
pt = evt.currentTarget.parent.contentToGlobal(pt);
infoToolTip = ToolTipManager.createToolTip(text, pt.x, pt.y, "errorTipAbove") as ToolTip;
infoToolTip.setStyle("borderColor", "#87B846");
infoToolTip.setStyle("color", "white");
var yOffset:int = infoToolTip.height + 5;
infoToolTip.y -= yOffset;
infoToolTip.x -= 5
}
// Remove the tooltip
private function killToolTip():void
{
ToolTipManager.destroyToolTip(infoToolTip);
}
Using the toolTip:
<mx:Image source="{myImageSource}" mouseOver="showToolTip(event, 'Hello there!')" mouseOut="killToolTip()" />

add uicomponent inside a sprite

i want to add UIComponent inside a spite. here is the code:
private function make() : void {
var circle : Sprite = new Sprite();
circle.graphics.beginFill(0xFF0000, 0.2);
circle.graphics.drawCircle(0, 0, 20);
var button : Button = new Button();
button.label = "testing...";
var wrapper : UIComponent = new UIComponent();
circle.addChild( button );
wrapper.addChild( circle );
addChild( wrapper );
}
the problem is that button is added, but is not displayed. if i do reversed - add sprite to uicomponent - everything works fine, but this way it doesn't work. i tried to use invalidate functions for button etc... even tried making "circle" as UIMovieClip, but no luck - button is still invisible. also if i simply do "addChild( button );" - it is shown, what the... please help, what i am doing wrong? how can i add a button inside a sprite?
Short answer, you can't. What you CAN do is instead of using Sprite, you use UIComponent for your circle.
The reason for this is that UIComponent has A LOT of code that changes how it behaves, including how to add and layout children. You could essentially take the same code to a Sprite since UIComponent does extend it, however that would be VERY redundant. This works great for me:
private function make() : void {
var circle : UIComponent= new UIComponent();
circle.graphics.beginFill(0xFF0000, 0.2);
circle.graphics.drawCircle(0, 0, 20);
var button : Button = new Button();
button.label = "testing...";
var wrapper : UIComponent = new UIComponent();
circle.addChild( button );
wrapper.addChild( circle );
addChild( wrapper );
}
Unfortunately, in order to use Sprite the way you are trying to do it, you would have to extend Sprite and implement IUIComponent.
Taken from the Flex 3 Language Reference:
Note: While the child argument to the
method is specified as of type
DisplayObject, the argument must
implement the IUIComponent interface
to be added as a child of a container.
All Flex components implement this
interface.
Sprite does not implement IUIComponent, so you are experiencing a pretty typical issue. UIComponent's don't typically have speed issues when compared to Sprites, so I would recommend just drawing on your UIComponent.
As stated before, you /could/ extend Sprite to implement IUIComponent, but it's a pain.
Hope this helps!

Is there a multiline text workaround for Flex

Is there a workaround for displaying multiline text in Flex 3? The two controls I have tried so far are mx:Text, and mx:TextArea. Each control has its own bug associated with it. For reference: mx:Text bug - http://bugs.adobe.com/jira/browse/SDK-9819 mx:TextArea bug - http://bugs.adobe.com/jira/browse/SDK-12616. Basically, neither control handles scrolling correctly if you do not specify a height and the text wraps onto the next line (height is determined dynamically by Flex, based on the wrapping). Does anybody have a workaround that might be helpful?
Thanks.
Update: One of the methods I have tried in the past has been to manually calculate the height of a mx:Text element. I can do this by using the following:
var textItem:Text = new Text();
var len:int = value.length;
var lines:int = int(len/115) + 1;
var height:int = lines * 20;
textItem.height = height;
While this seems to get around the problem in mx:Text, there is one big fault. The calculation relies heavily on font-size, letter-spacing, and the width of textItem. I can use this method, and move on with my project. However, maintenance on this is inevitable, and with code like this, it will a gigantic PITA.
I've had to deal with this a few times myself. The best way I've found to get dynamic height sizing of <mx:Text> is to leave the height out of the text and then specify a percent height of 100% on the enclosing VBox, HBox, etc. Something like the following should work for you:
<mx:VBox width="100%" height="100%">
<mx:Text text="Your really long text goes here." width="100%"/>
</mx:VBox>
As this is a bit of a hack itself, your milage may vary.
Edit
If you want to extend your above example so that maintenance on the code is easier, you should look into the TextLineMetrics class. This will allow you to measure the width and height of your text, taking into account font, size, etc. The docs for TextLineMetrics can be found here. To use your above example, you'd want to do something like the following:
var textItem:Text = new Text();
var metrics:TextLineMetrics = textItem.measureText( value );
var len:int = metrics.width;
var lines:int = int(len/textItem.width) + 1;
var height:int = lines * metrics.height;
textItem.height = height;
I use a variable height text area class that works very well for me:
package
{
import mx.controls.TextArea;
/**
* TextArea that xpands to the height of the content contained
* within.
* #author joel
*
*/
public class VariableHeightTextArea extends TextArea
{
public function VariableHeightTextArea()
{
super();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(this.height != int(this.textField.measuredHeight) + 5 )
{
this.height = this.textField.measuredHeight + 5;
}
}
}
}

Resources