views:

1039

answers:

3

The initial height of a text area is much larger than the content, I cannot find a way of making it always the same height as the text content:

<mx:TextArea id="textarea" borderStyle="solid" width="100%" wordWrap="true" selectable="false" backgroundAlpha="0" focusAlpha="0" text="this is a little test" />

Gives a bordered box that is much taller than needed.

This also gives an unintential problem if you have links within the content in that a link 'mouseover' is triggered when nowhere near the link.

<mx:Script>
<![CDATA[
public function onInit():void
{
    var style:StyleSheet = new StyleSheet();

    var aLink:Object = new Object();
    aLink.color = "#0000FF";

    var aHover:Object = new Object();
    aHover.color = "#00FF00";
    aHover.textDecoration = "underline";

    style.setStyle( "a:hover", aHover );
    style.setStyle( "a:link", aLink );

    textarea.styleSheet = style;
}
]]>
</mx:Script>


<mx:TextArea id="textarea" width="100%" wordWrap="true" borderStyle="solid" selectable="false" backgroundAlpha="0" focusAlpha="0" >
    <mx:htmlText>
    <![CDATA[<a href='event:http://www.adobe.com'&gt;Navigate to Adobe.com.</a> this is testing nothing at all really]]>
    </mx:htmlText>
</mx:TextArea>

The Text component doesnt suffer from this, but I cannot attach a stylesheet to a text component.

Hoping someone can help. Or is there some other component I can use where I can add a stylesheet to stylise anchor tags.

I found this overridable in the TextArea.as source and if I override it and remove the "2 x" multiplier it almost works but unfortunately it means that the content doesnt get bigger when it needs to and vertically scrolls instead, so its almost there:

override protected function measure():void
{
    super.measure();

    measuredMinWidth = DEFAULT_MEASURED_MIN_WIDTH;
    measuredWidth = DEFAULT_MEASURED_WIDTH;
    // TextArea is minimum of two lines of text
    measuredMinHeight = measuredHeight = 2 * DEFAULT_MEASURED_MIN_HEIGHT;
}
A: 

Based on Bedwyr's link, I thought I would try recalcing the height myself and this seems to work fine (not noticed any bad side-effects yet, but there may be):

this.addEventListener( Event.CHANGE, onReMeasure );
this.addEventListener( Event.RESIZE, onReMeasure );

override protected function measure():void
{
     super.measure();

     measuredMinWidth = DEFAULT_MEASURED_MIN_WIDTH;
     measuredWidth = DEFAULT_MEASURED_WIDTH;

     var lm:TextLineMetrics = getLineMetrics( 0 );
     measuredMinHeight = measuredHeight = DEFAULT_MEASURED_MIN_HEIGHT;
}

private function onReMeasure( eventObj:Event ):void
{
    var ht:Number = 0;
    for( var n:int = 0; n < textField.numLines; n++ )
    {
     ht += textField.getLineMetrics(n).height;
    }
    ht += 10; // padding

    height = ht;
    validateNow();
}
Dan
There are too many side effects with this not quite drawing right and maclema's update worked so inheriting from Text and having your own get/set stylesheet is best answer
Dan
+1  A: 

I haven't tried what you're attempting, but this link looks like it might help:

http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&amp;postId=13628&amp;productId=2.

bedwyr
+2  A: 

If you extend Text, you can add a getter/setter that allows you to set the styleSheet of the underlying UITextField object.

package
{
    import flash.events.Event;
    import flash.text.StyleSheet;

    import mx.controls.Text;

    import mx.core.mx_internal;

    use namespace mx_internal;

    public class StyledText extends Text
    {
     public function StyledText()
     {
      super();
     }

     private var _styleSheet:StyleSheet = null;

     [Bindable("stylesheetChanged")]
     public function get styleSheet():StyleSheet {
      return _styleSheet;
     }

     public function set styleSheet(value:StyleSheet):void {
      _styleSheet = value;

      if ( textField ) {
       textField.styleSheet = _styleSheet;
      }

      dispatchEvent(new Event("stylesheetChanged"));
     }

     override protected function createChildren():void {
      super.createChildren();

      //textField is created in the createChildren 
      //method of the Label class
      if ( textField && styleSheet ) {
       textField.styleSheet = _styleSheet;
      }
     }

    }
}

Then you can use the component like so:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="*" preinitialize="onInit()">
    <mx:Script>
    <![CDATA[
    public function onInit():void
    {
        var style:StyleSheet = new StyleSheet();

        var aLink:Object = new Object();
        aLink.color = "#0000FF";

        var aHover:Object = new Object();
        aHover.color = "#00FF00";
        aHover.textDecoration = "underline";

        style.setStyle( "a:hover", aHover );
        style.setStyle( "a:link", aLink );

        text.styleSheet = style;
    }
    ]]>
    </mx:Script>


    <ns1:StyledText id="text" x="0" y="79">
     <ns1:htmlText>
     <![CDATA[<a href='event:http://www.adobe.com'&gt;Navigate to Adobe.com.</a> this is testing nothing at all really]]>
     </ns1:htmlText>
    </ns1:StyledText>

</mx:Application>
maclema
I like the idea but it didnt really work, textField is null so the setter doesnt work, possibly as its before its been created due to doing it on the preInitialised. So I set the style on Event.COMPLETE instead but it doesnt actually set the styles of the control.
Dan
I updated the code to handle textField being null. Try it out, let me know if it works.
maclema
I tried it a different way before I noticed your comment, basically i set the styles in an overridden function "override protected function initializationComplete():void" and it worked fine. So I am afraid I hadnt tried your solution exactly,
Dan
Found out this solution has another nastyy side effect, if i scroll around my list view that contains one of these text boxes in a custom item renderer then sometimes the text does not appear. Its taken me ages to figure out that this solution is the cause of my problem. Help!
Dan
Are you still using the "override protected function initializationComplete():void"? If so maybe try the createChildren(). Maybe also try adding invalidateDisplayList() in the stylesheet setter.
maclema