« More Thinking About Item Renderers | Main | DataGrid Footers »

Multiline Buttons

Someone recently asked about having the label of a radiobutton wrap onto more than one line. Maybe it just got lost in FlexCoders traffic because I'm sure others have already solved this, but I put together this version out of my own curiosity. The pattern can be re-used for Button and CheckBox as well. The usual caveats apply.

Download file

You'll notice that I used "undocumented" methods to accomplish this, so it might break in some future release of Flex. However, this is really intended to be another example of subclassing and illustrate that by knowing the underlying base class you can usually tweak things the way you want them.

Now you may ask, why doesn't this functionality come built-in with Flex? The answer is that text-flow is slow and doesn't really work well with the Flex layout system. That's because there really is no way to determine the size of a block of text unless it is only one line or has line-breaks in it or you know its width. In fact, to use this example, you need to specify the width of the radiobuttons, so it defines a width so we can calculate the height.

Here is a Flex 3 version:
Download Source
Run Example


Comments

Hi, Alex:
How can I use the button you offer? I have tried to do in the Application :

It does not work.

Thanks

-------------------

You have to give it an numeric width like width="100" otherwise it won't know how to wordwrap correctly. I explained why this is required in the blog post

Works like a charm! I've been looking for something like this for a while now. Thanks!

Hi Alex... thanks for responding to my flexcoders post on this. I've tried your code and it works great. I have just one tweak request... How can I get the radio button vertically aligned to the top of the wrapped text? Right now it appears in the middle. Thanks again for all you do for the Flex community!
----------------

I would override updateDisplayList, call super.updateDisplayList, then get the current icon via getCurrentIcon() and set its y value to where you want it.

Worked like a charm, thanks.

Here's the fix for the radio button alignment.

override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
this.getCurrentIcon().y = 2;
}

I'm new to this Flex stuff and was wondering how do I use the two files you have in my project?

Thanks
jason

----------------

Ask that question on flexcoders, you'll get better help on how to do that. I generally don't use FlexBuilder for my work.

You say you don't use Flex Builder. What do you use?

-------------

ANT or UNIX shell scripts.

Thanks so much for Alex good example! :-)

I'm getting the following error in the MultilineRadioButton.as file at addChild(textField):

1067:Implicit coercion of a value of type mx.core:IUITextField to an unrelated type flash.display:DisplayObject

How can I fix this?

Great! I was building one of these myself but it didn't quite work.

I used this for the Button class and one thing I noticed is that the multi-line text wasn't vertically centred properly until you rolled over the button.

You need to force the button to re-render itself after it's created. I added the following function to my MultilineButton class:

public function forceUpdate():void{
this.updateDisplayList(this.width,this.height);
}

I call this from the tag like so:

And here's the handler that should be in the Script tags:

private function forceUpdateHandler(event:Event):void{
event.target.forceUpdate();
}

I'm getting the same error in the MultilineRadioButton.as file at addChild(textField), like Jack :

1067:Implicit coercion of a value of type mx.core:IUITextField to an unrelated type flash.display:DisplayObject

Can anybody help? i'm using Flex 3 Beta 3 Builder.

Thx,
Toni

-----------------------

You'll have to cast it via DisplayObject(textField). These examples were for Flex 2.0.1 and some will need updating for Flex 3

Thanks! I was having this same exact problem, but with regular Button components. I subclassed Button and used the same code as in your MultilineRadioButton class.

Now the "#13;" escape sequence works and my buttons allow multiline labels.

Thank you very much! I just used your code for CheckBox components and it works perfectly.

Nice blog -- I really need this for a multiline Button! I extended the Button class and adapted the createChildren function slightly for Flex3. Works just fine. I just use \n in the label like label="{'This\nis\nGreat'}"

override protected function createChildren():void{
if (!textField){
textField = IUITextField(createInFontContext(UITextField_NoTruncation));
textField.styleName = this;
addChild(DisplayObject(textField));
}
super.createChildren();
textField.wordWrap = true;
textField.multiline = true;
}

"this.getCurrentIcon().y = 2;" worked in flex 2, but in Flex 3, the icon is pretty well hidden by the internal keyword. Is there any way around this?

-------------
Alex responds:

getCurrentIcon is still mx_internal so

import mx.core.mx_internal;
use namespace mx_internal

should still do the trick.

I used you code to extend a Button, and published these class (if you dont mind).
I made a link for this post on the blog and also on the code.
Really usefull, thanks.

Does anyone have a working example I could look at? I am trying to create a multi-line label for a button in Flex2.

--------------------
Alex responds:

Several people have used the source and were successful. If you are having problems, pose the question on FlexCoders

this is not a problem now

http://flexlib.googlecode.com/svn/trunk/docs/flexlib/controls/CanvasButton.html

Very simple

Hi
I used this component and the text was cut by the verticalScroll for long texts and having fixed width...
This may help in MultineRadioButton.as

textField.width = w - 5;

Thanks

I'd like to use this code as part of an open-source Flex library I've written. Is it something you're willing to release?

---------------
Alex responds:

Yes, as long as I'm free of all liability.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)