Thursday, September 11, 2008

Bullet Class

A little while ago, I was working a little project that had several lists of bullets. I couldn't find any suitable solutions that gave the designer what he craved; a list of bullets with well-wrapped text.

Sample xml;
<SAMPLE_TEXT>• Bullet item one.
• Bullet item two. Long enough to wrap because I've typed a little bit too much and it definitely is too long to fit in one line.
• Bullet item three. There's nothing like seeing text wrapping to make you realize that bullets are the bane of your existence. Nothing, I say.
• Bullet item four.</SAMPLE_TEXT>


Here's what you get when you just set up a normal textfield and do what you normally do.

var tf:TextField = new TextField;
tf.width = 300;
tf.multiline = true;
tf.wordWrap = true;
tf.text = SAMPLE_TEXT;
addChild(tf);




As you can see, the text wraps under the bullet because flash only sees it as a block of text.

I realized that the best solution, for me anyway, was to separate the bullet and the line, make two textfields and line them up. This way the copy aligns as it should and doesn't wrap under the bullet. So I set up a little class to take care of it for me.

The XML had to change to accomodate TextFormatter, but only a little;
<SAMPLE_TEXT bulletString="•" ffont="Arial" fsize="18" fcolor="0x000000">• Bullet item one.
• Bullet item two. Long enough to wrap because I've typed a little bit too much and it definitely is too long to fit in one line.
• Bullet item three. There's nothing like seeing text wrapping to make you realize that bullets are the bane of your existence. Nothing, I say.
• Bullet item four.</SAMPLE_TEXT>

package com.display
{
import flash.display.Sprite;
import com.utils.TextFormatter;
import flash.text.TextField;
public class BulletBuilder extends Sprite
{
private var content:Sprite;
private var bulletCharacter:String;
private var bulletArr:Array;
private var contentArray:Array;
private var bullet:TextField;
private var copy:TextField;
private var bulletHeight:Number = 0;
private var fieldWidth:Number;
/*====================
provide the constructor with;
the xml node
what character to look for
the width of the end field
sample;
var bulletBuilder:BulletBuilder = new BulletBuilder(sampleNode,"•",415);
addChild(bulletBuilder);
=====================*/
public function BulletBuilder(_copy:XML,_bulletCharacter:String,_fieldWidth:Number)
{
content = new Sprite;
bulletCharacter = _bulletCharacter;
fieldWidth = _fieldWidth;
bulletArr = _copy.toString().split(bulletCharacter+" ");
setBulletFields(_copy);
}
/*=====================
setBulletFields separates the copy
into an array based on the provided bullet character.
it then uses two textfields; one for the bullet character, one for the copy.
places the copy at the same y position as the bullet
and moving it to the right of the bullet
it then adds the two fields to the sprite and updates the y position for the next bullet
finally, the function adds the content sprite
========================*/
private function setBulletFields(_copy:XML):void{
contentArray = []
for(var i:int = 1;i<bulletArr.length;i++){
contentArray[i] = new Sprite;
bullet = new TextField;
copy = new TextField;
copy.width = fieldWidth;
copy.multiline = true;
copy.wordWrap = true;
new TextFormatter(bullet,_copy.@fcolor,_copy.@fsize,bulletCharacter,_copy.@ffont);
new TextFormatter(copy,_copy.@fcolor,_copy.@fsize,bulletArr[i],_copy.@ffont);
copy.x = bullet.width;
contentArray[i].addChild(bullet);
contentArray[i].addChild(copy);
contentArray[i].y = bulletHeight;
bulletHeight +=contentArray[i].height;
content.addChild(contentArray[i]);
}
addChild(content);
}
}
}



Here's sample with the package(s)

Labels: , , ,