Automatic font size adjuster

1 year ago | in Actionscript 3, Flash, Interaction design | 12 Comments »

First I have to say sorry to all the not ‘actionscript-geeks’, but I have another script I want to share. I made a TextField behaviour that might come in handy for other people too.. I made a short video to show how it works.

It is called AutomaticFontSizeBehaviour AutomaticFonSizeBehavior :)

package  
{
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
 
	/**
	 *  @author Jankees.van.Woezik
	 */
	public class AutomaticFonSizeBehavior 
	{
 
		private var _textField:TextField;
		private var _startSize:Number;
		private var _currentSize:Number;
		private var _prevText:String;
		private var _maxHeight:Number;
		private var _minimalFontSize:uint;
 
		/**
		 * Usage:
		 * 
		 * _updater = new AutomaticFonSizeBehavior(textField);
		 * 
		 * // this is enough for input fields, if you set text using code you should call the update function after you have set the text like this:
		 * 
		 * _updater.update();
		 * 
		 */
		public function AutomaticFonSizeBehavior(inTextField:TextField,inStartSize:Number = 40,inMinimalFontSize:uint = 9, willUpdateOnInput = true) 
		{
			_minimalFontSize = inMinimalFontSize;
			_startSize = inStartSize;
			_currentSize = inStartSize;
			_textField = inTextField;
			_prevText = "";
 
			_maxHeight = _textField.height;
 
			_textField.addEventListener(Event.REMOVED_FROM_STAGE,dispose);
 
			if(willUpdateOnInput) addEventListeners();
 
			setFontSize(_startSize);
 
			update();
		}
 
		public function update(event:Event = null):void 
		{
			_textField.scrollV = 0;
 
			if(_prevText.length > _textField.length)
                setFontSize(_startSize);
 
			while (_maxHeight < _textField.textHeight + (4 * _textField.numLines)) 
			{ 
				if(_currentSize <= _minimalFontSize) break;
				setFontSize(_currentSize - 0.5);
			}
 
			if(_currentSize <= _minimalFontSize) 
			{
				_textField.text = _prevText;
			} 
			else 
			{
				_prevText = _textField.text;
			}
		}
 
		private function addEventListeners():void 
		{
			_textField.addEventListener(Event.CHANGE,update);
			_textField.addEventListener(KeyboardEvent.KEY_UP,update);
		}
 
		private function setFontSize(inSize:Number):void 
		{
			_currentSize = inSize;
 
			var currentTextFormat:TextFormat = _textField.getTextFormat();
			currentTextFormat.size = _currentSize;
 
			_textField.setTextFormat(currentTextFormat);
			_textField.defaultTextFormat = currentTextFormat;
		}
 
		/**
		 * Dispose everything
		 */
		private function dispose(event:Event):void 
		{
			_textField.removeEventListener(KeyboardEvent.KEY_UP,update);
			_textField.removeEventListener(Event.CHANGE,update);
			_textField.removeEventListener(Event.REMOVED_FROM_STAGE,dispose);
 
			_textField = null;
		}
	}
}

update: Thanks to Thijs for the update! Copy & paste is now supported!
update: Thanks to Sandro Padin for the improvements!!

Comments:

Sweet, nicely designed class dude.

erik at 12:41 on 13/08/2009

Thanks! The project ‘#endathetmespijt’ will be launched next monday! I post a message when it is live!

jankees at 12:45 on 13/08/2009

VET VET VET!!!!

Really nice. I am definitely going to use this.

But I didn’t know TextFields dispatches KeyBoardEvents? I thought only the Stage does it. Maybe you should also listen to the flash.events.TextEvent.TEXT_INPUT event?

Does it work when I do ‘copy-paste’?

Thijs at 19:33 on 13/08/2009

@Thijs Textfields do dispatch Keyboard Events, this is done by the InteractiveObject class and it’s the super of TextField.

@JanKees Nice! Added the class to my repos ;)
Like Thijs said it would be nice if it will work with ‘copy-paste’. I tried it @ the demo you showed me yesterday and it didn’t work.

Bernard at 21:34 on 13/08/2009

Thanks! Do you have any idea how to solve the copy paste thing? The only thing I can come up with is overwriting the setter ‘text’ in textfield, which is a bit dirty…?

Jankees at 07:55 on 14/08/2009

I fixed your copy-paste thing!!!

Just add:

_textField.addEventListener(TextEvent.TEXT_INPUT,update);

And it will work!

Thijs at 08:56 on 14/08/2009

Thanks!

Maybe it would be nice that an update woudn’t be exucuted if there is no text change… it gets fired 3 times for every keystroke…

Jankees at 09:01 on 14/08/2009

This looks great. One question though, how do you use it? Would you need some sort of global variable and do var tf: AutomaticFontSizeBehaviour = new AutomaticFontSizeBehaviour(myTextField); ?

Thanks!

Sandro at 19:09 on 07/10/2009

One other suggestion.. This class is great not just for input text, but for dynamic text that is only set once, like item titles or descriptions. I modified your constructor to add a willUpdate boolean property, then I only add the event listeners if the textfield is meant to be updated more than once.

Sandro

Sandro at 19:30 on 07/10/2009

@Sandro, Thanks for you feedback, if you send me your adjustments I will post it here.

Best,

Jankees at 20:36 on 07/10/2009

Thijs at 16:01 on 08/01/2010

Please leave a comment