Friday, August 08, 2008

mx.controls.Text: preventing scroll on select

A minor annoyance in Flex that I've lived with for many moons now is that even though I will provide enough vertical space to show all the text or htmlText in a Text Control, when a user attempts to select the text, often times, the text will scroll up, hiding the first line. The easiest fix is to set selectable='false', and in most cases this will do the trick. There are times however, when a client will demand that text remain selectable. And that same client will be the first to complain about the apparently unnecessary scrolling of text.

I played around with this, but seriously, the mx.controls.Text class really doesn't give one much to work with. On browsing through the sdk source, I discovered I'd probably have better luck working with the wrapped UITextField. In the end I tapped into the scroll event and the alwaysShowSelection attribute of the UITextField to get me where I needed to go.

It's been a long week so I'm just going to post up a link to the solution here, and the source code here.

12 comments:

Harry B. Garland said...

Another way to overcome the limitations of UITextField is by having keystroke and character level control over the text input system.

Check out this open-source project:
http://flexcommandline.googlecode.com

Adobe Air/Flex Tips & architecture said...

nice one!

i've been having this problem some time and always setteed selectable on false. sometimes this is not desireable.

thanx for this solution!

Arnoud Bos

Anonymous said...

Great job! This was just what the user prescribed. Just in the nic of time too.

Thanks for your post.
cj

Anonymous said...

nice solution, but is looks weird when having multiple text components having text selected.

Anonymous said...

In addition to my previous comment, I added some code that handles this:

watch focus out event, and deselect then.

this.addEventListener(FocusEvent.FOCUS_OUT,onFocusOut);

private function onFocusOut (event:FocusEvent)
{
UITextField(getChildAt(0)).setSelection(0,0);
}

Anonymous said...

Awesome thanks =)

Unknown said...

I guess that I've been lucky. After the text changes in my multiline UITextField, I resize the UITextField by calling the method below -- so far, this has done the trick for me to prevent scrolling.

private function adjustExplicitSizeOfTextField(field:UITextField):void
{
const GUTTER_PIXELS:uint = 2;
var textLineMetrics:TextLineMetrics = field.getLineMetrics(0);
var width:Number = Math.ceil(textLineMetrics.width + GUTTER_PIXELS * 2);
var height:Number = Math.ceil(textLineMetrics.height + GUTTER_PIXELS * 2) * field.numLines;
field.explicitWidth = width;
field.explicitHeight = height;
(field.parent as UIComponent).invalidateSize();
}

Anonymous said...

It looks like you can also set leading="0" for a simple fix, but I think that condenses the text vertically....I'm guessing the leading is responsible for the scrolling and they didn't include it in whatever calculations they made to determine if it should scroll?

hitsh sethi said...

nice trick !

Unknown said...

Nice job

Monali said...

Hi,

Nice one!

But i am not able to access your provided link.

i want to view the solution as i am facing the same problem.

Thanks in advanced!

Vic Rubba said...

Don't the other solutions in the comments work?

I've never tried them:)

Anyway, we're working on getting that link fixed, check back in a few days.