Expandable Text Area
I had an issue recently where there was a standard form item, with a textInput as the entry component. The problem was that a single line was not large enough for the client to enter in the details that they required. Using a text area would be my next logical choice however because of certain real estate restrictions I wanted to keep as many form elements visible on the screen at the one time.
Hence the Expandable Text area, a hybrid of the single lined TextInput and the TextArea. Where typing and removing text would re-size the input component accordingly, and setting a text value would expand the component to cater to the text size.
It's a fairly simple component with the overridden measure method doing most of the work.
measure
Below in the measure command we utilize both the viewMetrics to determine the number or lines and then the measuredHeight of the TextArea2
3 super.measure();
4
5 // Calculate the default size of the control based on the
6 // contents of the TextArea.text property.
7 var lineMetrics:TextLineMetrics = measureText(text);
8
9 // get the edge metrics of the textArea
10 var vm:EdgeMetrics = viewMetrics;
11 var w:Number = (explicitWidth - vm.left - vm.right);
12
13 // calc the line count. If the textFields width has been
14 // updated to the TextAreas explicit
15 // height then we can use it's line count otherwise we use
16 // the lineMetrics width divided
17 // by the explicit width minus the edges
18 var lineCount:int = Math.ceil(lineMetrics.width / w);
19
20 // use the textFields linecount if it's the layout has been initialized
21 if(useLineCount){
22
23 lineCount = textField.numLines;
24
25 }
26
27 // include the total for the line height and the
28 // padding for top bottom and leading values
29 measuredHeight = measuredMinHeight = (lineMetrics.height * lineCount)
30 + vm.top + vm.bottom + lineMetrics.leading;
31
32}
onTextChange
There is also a listener and handler for the "textChanged" event that is dispatched from the extended TextArea. This handler invalidates the size of the component if the number of lines in the textField has been modified. I also had to sets the variable called useLineCount to determine whether the textFields.numLines attribute should be used. As when the component is first initialized with text, the textFields layout is not yet completely set thus returning an incorrect numLines value.2
3 if(_prevLineCount != textField.numLines){
4
5 // becuase the lineCount of the textField is not
6 // set as per the actual size during
7 // the first phase of instanciation we know that
8 // it's correct now so we can set a boolean to
9 // indicate that.
10 useLineCount = true;
11
12 // invalidate the size
13 this.invalidateSize();
14
15 _prevLineCount = textField.numLines;
16
17 }
18
19}
updateDisplayList
And the last piece is the updateDisplayList which sets the actual size of the textField based on the number of lines and the components unscaledWidth. It also sets the explicitWidth of the component if it results in a NaN. This occurs if the component's width is determined by a percentage or layout constraints.2 , unscaledHeight:Number):void{
3
4 // we just need to layout the chrome no need for scrollbars
5 super.layoutChrome(unscaledWidth,unscaledHeight);
6
7 // if the explicitWidth isn't set then set it.
8 // This will force the invalidateSize() to be called.
9 if(isNaN(explicitWidth)){
10
11 explicitWidth = unscaledWidth;
12
13 }
14
15 var vm:EdgeMetrics = viewMetrics;
16
17 textField.move(vm.left, vm.top);
18
19 var w:Number = unscaledWidth - vm.left - vm.right;
20 var h:Number = unscaledHeight - vm.top - vm.bottom;
21
22 // set the actual size of the textField based on the
23 // number of lines and the default measured minimum
24 // height of the component
25 textField.setActualSize(w
26 ,(textField.numLines) * (DEFAULT_MEASURED_MIN_HEIGHT));
27
28}
There it is, unfortunately it's written with the Flex 3 SDK although I'll eventually port it to 4. It's a hybrid between the two text inputs which will enable the user to concentrate on data entry without having to worry about scroll bars and what they'd typed 50 characters ago.





