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

50 Responses to Multiline Buttons

  1. jeff says:

    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

  2. Brandon says:

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

  3. Merritt says:

    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.

  4. Rich says:

    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;
    }

  5. Jason says:

    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.

  6. Randy Martin says:

    You say you don’t use Flex Builder. What do you use?
    ————-
    ANT or UNIX shell scripts.

  7. Jack says:

    Thanks so much for Alex good example! 🙂

  8. JRosamond says:

    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?

  9. nicemandan says:

    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();
    }

  10. Toni says:

    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

  11. Ken says:

    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.

  12. David says:

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

  13. Warren Koch says:

    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;
    }

  14. Peter Gardner says:

    “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.

  15. 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.

  16. Ken Greenwood says:

    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

  17. Krishnendra says:

    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

  18. Mark says:

    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.

  19. George says:

    Thanks for the help Alex!
    Based on this I created a Flex 3 multiline CheckBox class here

  20. George says:

    Hi Alex!
    Thanks to your example I was able to create a custom class that allows for multiline checkbox.
    You can see it here:
    http://spy6.blogspot.com/2008/09/flex-multiline-checkbox.html

  21. Matteo Lanzi says:

    Hi Alex, thanks for your example. I modified your measure method to work with percentWidht
    this the code
    override protected function measure():void
    {
    if ( ! isNaN(percentWidth) && ( parent && parent is UIComponent)){
    var p : UIComponent = parent as UIComponent ;
    var w : Number = p.getExplicitOrMeasuredWidth() ;
    var tempIcon:IFlexDisplayObject = getCurrentIcon();
    w -= tempIcon.width + getStyle(“horizontalGap”) + getStyle(“paddingLeft”) + getStyle(“paddingRight”)
    + p.getStyle(“paddingLeft”) + p.getStyle(“paddingRight”) + 6
    textField.width = w ;
    }
    if (!isNaN(explicitWidth) )
    {
    tempIcon = getCurrentIcon();
    w = explicitWidth;
    if (tempIcon)
    w -= tempIcon.width + getStyle(“horizontalGap”) + getStyle(“paddingLeft”) + getStyle(“paddingRight”);
    textField.width = w;
    }
    super.measure();
    }

  22. Gaurav says:

    Hey Alex,
    It works for a button. But could someone please let me know how this could be done onto a TabNavigator. There does not seem to be a textField property on a tab navigator so how can i go about it.
    Your response would be highly appreciated.
    Thanks.
    ——————–
    Alex responds:
    The Tabs in the TabNavigator are buttons

  23. Gaurav says:

    I am pretty new to Flex actually, how should one go about to make those buttons in the tab navigator as the custom buttons. The tabnavigator class only has a method by the name getTabAt(index) which returns a button. Is this button which is returned by the method supposed to be played with? textField being an internal property of a button it would’nt be accessible via getTabAt(index)’s returned button.
    Could you please tell me how should i go about it.
    Thanks a lot!!
    —————————-
    Alex responds:
    That’s too much for me to tackle via blog comments. You might want to see if the third-party SuperTabNavigator supports multline buttons or makes it easier to substitute Tabs. Otherwise, ask on FlexCoders.

  24. Tristan says:

    Great component Alex, it was having trouble updating when binding. Not sure if this is the best way to do it but this fixes it.
    override public function set label(value:String):void {
    super.label = value;
    updateDisplayList(this.width, this.height);
    }
    ————————–
    Alex responds:
    In general, you shouldn’t call updateDisplayList yourself. Calling invalidateDisplayList should be good enough.

  25. Great job, Alex!
    With minor alteration, I created Multi Line Text Label Button!
    I appreciate and congratulate your efforts. 🙂

  26. Mohan says:

    Hi Alex,
    Great stuff 🙂 I was wondering if you could help me in getting the same effect for the labels of a HSlider component. I understand that the inherent methods are different, but just a pointer in the right direction would help a lot.
    Thanks in advance,
    ————————–
    Alex responds:
    I’d probably hide the labels and put my Text components where needed.

  27. CHO_ON says:

    Thank’s alot Alex,
    Your example very helpful, but the source code is for Radio Button multiline only.Base on your source code I had created a Button multiline example here

  28. mahesh says:

    Hi
    i am able to create multiline radio button.
    but my problem is i need to place that radio button visuval component i.e circle at 1st line
    i had 3 lines of text i need to place that radio button circle at 1st line
    please help me to solve this problem
    Regards
    Mahesh

  29. Alex Harui says:

    The icon can be moved in an override of updateDisplayList.

  30. slaingod says:

    I have created an updated version of this code (based on Flex 3.5) that fixes a couple of problems with dynamic sizing and styling. In particular, when commitProperties is called (if you say bold the font after the checkbox/radiobutton is created) then the UITextField gets recreated without the multiline hacking.
    http://blog.slaingod.com/articles/2010/04/11/adobe-flex-multiline-checkbox-and-radiobutton

  31. Rick Veenstra says:

    Hi,
    I’m trying to add htmlText to the textField to allow for some bold words. But it doesn’t seem to update the htmlText at all. When debugging the code and I step beyond the htmlText set the same htmlText is still shown. In the end the label is not set and thus empty.
    if (!textField)
    {
    textField = new NoTruncationUITextField();
    textField.styleName = this;
    textField.htmlText = “Testing html coding. [bold]Beware![/bold]: The previous text is bold”;
    addChild(textField as DisplayObject);
    }
    * Typed [bold] as the html tags so this editor doesn’t convert them 😉

  32. Alex Harui says:

    Try creating a simple test case in an ActionScript-only project

  33. slaingod says:

    @Rick You may be having font issues. You might want to try using FlexSpy or tracing to verify that the control has the value you set, but just isn’t showing it because the font isn’t loading/being used. This can happen if you set the font on a control to an embedded font but use a system font in the control, amoong other scenarios.

  34. romey says:

    hello,
    i was used your multiline radio button but i have a problem with that one that radio button was showing middle not at first line can you give a suggession to avoid that one.
    Thanks

    • Alex Harui says:

      Maybe the radiobutton needs to be a bit taller. Remember that you have to fix the width in order to have the height calculated properly

  35. Danii Oliver says:

    How do I implement this class in Flash Professional.
    I can’t get it to work for the life of me.

    What I have been trying are math functions…
    pad = Math.round (radioB.textField.numLines * r + 10);

    radioB.y = questionFields.y + radioB.textField.textHeight * r + pos + questionFields.height + radioB.textField.numLines + 2 * pos;

    pos += pad//radioB.textField.textHeight //questionFields.y + pad + ;

    • Alex Harui says:

      The main principle is to constrain the width of the textfield so it will measure multiple lines correctly.

  36. AndiV says:

    Hi Alex,

    I want to use your example in a commercial project. Therefore I wanted to ask for your allowance and wanted to know, if you claim any rights in this case?

    Thanks for your help so far.

    Reg. Andi

  37. Pat says:

    Hi Slaingod,
    The link you provided is the one I am looking for. I can see the SWF, but the source code is not there anymore. Can you post the source code again.

    Thanks so much!

    Here’s your like,
    http://blog.slaingod.com/articles/2010/04/11/adobe-flex-multiline-checkbox-and-radiobutton

  38. slaingod says:

    Hopefully you figured it out from the comments on my blog, but you need to click thru to the Example SWF instead of trying to use the one embedded in the blog page, to get to the source view. My first attempt at using srcview didn’t work out as well as I wanted 🙂

  39. asmae says:

    hi Alex,
    I created a quizz in flash (actionscript 3) where I used many checkboxes, and sometimes the answer is too long, and I don’t know how to make a multiline checkbox ? and how can I align the button and its label vertically in flash (I don’t want it to be in the middle)?
    unfortunately I don’t understand anything in flex
    thanks for your help

  40. Cam says:

    Would you know how to get text formatting working with your code? (I need to change alignment to left justify). I’ve tried several variations of applying UITextFormat/TextFormat to the textField instance but nothing seems to work!

  41. fabian rios says:

    If you’re using AS3 components, you can start with this:

    var tf:TextField = myRadioButton.textField;
    tf.multiline = tf.wordWrap = true;
    tf.autoSize=”left”;

  42. Chris says:

    Thanks! This is exactly what I was looking for. One question though, is there any way to remove all the padding from the left and right sides of the button? I’ve tried setStyle(“paddingLeft”, “0”) in the createChildren() method but it doesn’t take. Any suggestions?

  43. Umesh says:

    i’m making some changes in Code and Make Radio Button Label to HtmlText now my problem is when some image comes(e.g ) MultilavelRadio button not get resize with image , my image disply like crop image and concert about TExt it will looks gud what’s problem

    i’m just addd following line of code in this script for htmlText Label

    override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void
    {
    super.updateDisplayList(unscaledWidth, unscaledHeight);
    textField.htmlText = label;
    }