I came upon a challenge creating a custom ToggleButtonBar component. The challenge was to display dynamic text on each button while displaying button states (up, over, down, selected). This is not a problem when you have simple formatted text. You can assign and style the text via the label property of the button. But, I needed to display two text values. One value that needed to be rotated and formatted a different way.
By programmaticly skinning the buttons, I was able to add uniquely formatted text to a sprite that is then drawn to the button state skin. If you're new to Programmatic Skinning, check out Joey Lott and Chafic Kazoun's book - Programming Flex 2.
Here is a scaled down version of this functionality. In most cases, you would use a different background image per button state. In this example, I am embedding one background image and a text element with an embedded font.
package com.myProject.skins
{
import flash.display.BitmapData;
import flash.display.IBitmapDrawable;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.AntiAliasType;
import mx.controls.Button;
import mx.core.UIComponent;
import mx.skins.ProgrammaticSkin;
public class CustomButtonSkin extends ProgrammaticSkin
{
[Embed(source='C:\\WINDOWS\\Fonts\\framd.ttf',
fontName='FranklinMed', mimeType='application/x-font')]
private var FranklinMed:Class;
/* This path is assuming that you have an image in this folder */
[Embed(source="assets/images/skinsRed.png")]
private var skinImgRed:Class;
public function CustomButtonSkin(){}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
var _backgroundImg:Sprite = new Sprite();
var _mainSprite:Sprite = new Sprite();
var _bitmapData:BitmapData =
new BitmapData(int(unscaledWidth), int(unscaledHeight));
var _mainBitmapData:BitmapData =
new BitmapData(int(unscaledWidth), int(unscaledHeight));
var _skinImg:IBitmapDrawable = new skinImgRed();
/*
Drawing the embedded image to sprite(backgroundImg)
and then add it to mainSprite.
*/
_bitmapData.draw(_skinImg);
_backgroundImg.graphics.beginBitmapFill(_bitmapData);
_backgroundImg.graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
_backgroundImg.graphics.endFill();
_mainSprite.addChild(_backgroundImg);
/*
Create and format the textfield. Then add it to mainSprite.
Note: Using an embedded font in order to change the rotation.
*/
var _labelName:TextField = new TextField();
_labelName.embedFonts = true;
_labelName.textColor = 0xffffff;
_labelName.autoSize = TextFieldAutoSize.RIGHT;
_labelName.text = "dynamic text"; // example - Button.Data property
var _textFormat:TextFormat = new TextFormat();
_textFormat.font = "FranklinMed";
_textFormat.size = 14;
_labelName.antiAliasType = AntiAliasType.ADVANCED;
_labelName.setTextFormat(_textFormat);
_labelName.rotation = -90;
_labelName.y = 10 + _labelName.textWidth;
_mainSprite.addChild(_labelName);
/* Draw mainSprite to CustomButtonSkin object */
_mainBitmapData.draw(_mainSprite);
graphics.beginBitmapFill(_mainBitmapData);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
}
}
}
Is a CreationComplete event required when adding the TextField to the sprite?
I have a problem where the right of my text is chopped off even though the text field I set is much larger than the text (the font isn’t italic or anything). Wondering if it’s maybe because I’m drawing it before it’s initialised properly.
Thanks.