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 TextArea

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.

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.

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.

Animating Spark List Items.

Previously in Flex 3 List Components came with a style property called the itemsChangeEffect. This allowed you to specify a sequence of effects to apply to the item renderers when a change to the dataProvider occurred.

eg.

Because I was writing a Flex 4 Application I couldn’t find anything similar to this property in the Spark List components, so I decided to roll my own utilising a Custom layout for the List Component.

With the Flex 3 itemsChangeEffect you had to wait for your data to change before the effect would take place. With my effect I wanted the user to be able to drag an item around the list with the other elements moving away to allow for placement of the dragged item. Kind of like moses parting the waves with a draggable item.

Writing the custom layout:

Positioning the Elements.

Inside the custom layout it’s the override of the updateDisplayList that does the hard yakka positioning and sizing the List items. It makes sure that the items x and y positions do not overlap or exceed the width of the component. In this instance the first item is in the first row and any subsequent elements are beneath this in pairs.

Drag and Drop

For this layout I still needed the the drag and drop functionality so I extended the TileLayout.
If you still need the drag and drop functionality you may need to override a handful of the methods needed to calculate the dropLocations,indices and the location of the dropIndicator.

calculateDropLocation
calculateDropIndex
calculateDropCellIndex
calculateDropIndicatorBounds

Animating the elements – things to remember

With animating a Flex container you need to set the autoLayout flag to false before the animation to prevent flex from updating the containers layout after a child element is resized or repositioned. Once the animation has finished the autoLayout flag can be set back to it’s default value of true.

Only animate the elements that need animating. This is fairly obvious but can become a real bottleneck especially when dealing with large datasets. Test an elements previous position to determine whether it needs to be included in the sequence.

Depending on your interactivity you may need to set useVirtualLayout to false. Because virtualisation uses an estimate of elements displayed on screen for positioning and sizing, I found that with scrolling and dragging elements beyond the containers current scroll index, these elements were not being resolved. By setting it to false all elements are created and positioned allowing any calculations needed by those not currently displayed on the UI to still be allowed.

You can view and example of the layout here.

You can read more about the Spark SkinnableDataContainers here

Here is a nice article on creating custom layouts with Spark here