This blog post is based on creating a multiline checkbox, but it applies for radio buttons and buttons as well.

It's obvious that Flex 4 is a major improvement in terms of customization capabilities for developers. I recently had to make a Spark checkbox to display multiline text. In Flex 3 it took a lot of work and the solution wasn't very flexible.

In Spark it's as easy as skinning the checkbox. I started off by creating a new MXML Skin and chose the Spark checkbox as the host component. That generated the following code which is actually the default checkbox skin code.

1. <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
2. xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabledStates="0.5">
3.
4. <fx:Metadata>
5. <![CDATA[
6. /**
7. * @copy spark.skins.spark.ApplicationSkin#hostComponent
8. */
9. [HostComponent("spark.components.CheckBox")]
10. ]]>
11. </fx:Metadata>
12.
13. <fx:Script fb:purpose="styling">
14. /* Define the skin elements that should not be colorized.
15. For button, the graphics are colorized but the label is not. */
16. static private const exclusions:Array = ["labelDisplay", "check"];
17.
18. /**
19. * @private
20. */
21. override public function get colorizeExclusions():Array {return exclusions;}
22.
23. /* Define the symbol fill items that should be colored by the "symbolColor" style. */
24. static private const symbols:Array = ["checkMarkFill"];
25.
26. /**
27. * @private
28. */
29. override public function get symbolItems():Array {return symbols};
30.
31. /**
32. * @private
33. */
34. override protected function initializationComplete():void
35. {
36. useChromeColor = true;
37. super.initializationComplete();
38. }
39. </fx:Script>
40.
41. <fx:Script>
42. <![CDATA[
43. /**
44. * @private
45. */
46. private static const focusExclusions:Array = ["labelDisplay"];
47.
48. /**
49. * @private
50. */
51. override public function get focusSkinExclusions():Array { return focusExclusions;};
52. ]]>
53. </fx:Script>
54.
55. <s:states>
56. <s:State name="up" />
57. <s:State name="over" stateGroups="overStates" />
58. <s:State name="down" stateGroups="downStates" />
59. <s:State name="disabled" stateGroups="disabledStates" />
60. <s:State name="upAndSelected" stateGroups="selectedStates" />
61. <s:State name="overAndSelected" stateGroups="overStates, selectedStates" />
62. <s:State name="downAndSelected" stateGroups="downStates, selectedStates" />
63. <s:State name="disabledAndSelected" stateGroups="disabledStates, selectedStates" />
64. </s:states>
65.
66. <s:Group verticalCenter="0" width="13" height="13" layoutDirection="ltr">
67. <!-- drop shadow -->
68. <s:Rect left="-1" top="-1" right="-1" bottom="-1">
69. <s:stroke>
70. <s:LinearGradientStroke rotation="90" weight="1">
71. <s:GradientEntry color="0x000000"
72. color.downStates="0xFFFFFF"
73. alpha="0.011"
74. alpha.downStates="0" />
75. <s:GradientEntry color="0x000000"
76. color.downStates="0xFFFFFF"
77. alpha="0.121"
78. alpha.downStates="0.57" />
79. </s:LinearGradientStroke>
80. </s:stroke>
81. </s:Rect>
82.
83. <!-- fill -->
84. <s:Rect left="1" top="1" right="1" bottom="1">
85. <s:fill>
86. <s:LinearGradient rotation="90">
87. <s:GradientEntry color="0xFFFFFF"
88. color.overStates="0xBBBDBD"
89. color.downStates="0xAAAAAA"
90. alpha="0.85" />
91. <s:GradientEntry color="0xD8D8D8"
92. color.overStates="0x9FA0A1"
93. color.downStates="0x929496"
94. alpha="0.85" />
95. </s:LinearGradient>
96. </s:fill>
97. </s:Rect>
98.
99. <!-- fill highlight -->
100. <s:Rect left="1" right="1" top="1" height="5">
101. <s:fill>
102. <s:SolidColor color="0xFFFFFF" alpha="0.33" alpha.downStates="0" />
103. </s:fill>
104. </s:Rect>
105.
106. <!-- layer 6: highlight stroke (all states except down) -->
107. <s:Rect left="1" right="1" top="1" bottom="1" excludeFrom="downStates">
108. <s:stroke>
109. <s:LinearGradientStroke rotation="90" weight="1">
110. <s:GradientEntry color="0xFFFFFF" alpha.overStates="0.33" />
111. <s:GradientEntry color="0xFFFFFF" alpha="0.12" alpha.overStates="0.0396" />
112. </s:LinearGradientStroke>
113. </s:stroke>
114. </s:Rect>
115.
116. <!-- layer 6: highlight stroke (down state only) -->
117. <s:Rect left="1" top="1" bottom="1" width="1" includeIn="downStates">
118. <s:fill>
119. <s:SolidColor color="0x000000" alpha="0.07" />
120. </s:fill>
121. </s:Rect>
122. <s:Rect right="1" top="1" bottom="1" width="1" includeIn="downStates">
123. <s:fill>
124. <s:SolidColor color="0x000000" alpha="0.07" />
125. </s:fill>
126. </s:Rect>
127. <s:Rect left="1" top="1" right="1" height="1" includeIn="downStates">
128. <s:fill>
129. <s:SolidColor color="0x000000" alpha="0.25" />
130. </s:fill>
131. </s:Rect>
132. <s:Rect left="1" top="2" right="1" height="1" includeIn="downStates">
133. <s:fill>
134. <s:SolidColor color="0x000000" alpha="0.09" />
135. </s:fill>
136. </s:Rect>
137.
138. <!-- border - put on top of the fill so it doesn't disappear when scale is less than 1 -->
139. <s:Rect left="0" top="0" right="0" bottom="0">
140. <s:stroke>
141. <s:LinearGradientStroke rotation="90" weight="1">
142. <s:GradientEntry color="0x000000"
143. alpha="0.5625"
144. alpha.downStates="0.6375" />
145. <s:GradientEntry color="0x000000"
146. alpha="0.75"
147. alpha.downStates="0.85" />
148. </s:LinearGradientStroke>
149. </s:stroke>
150. </s:Rect>
151.
152. <!-- checkmark -->
153. <!--- The checkmark in the box for this skin. To create a custom check mark, create a custom skin class. -->
154. <s:Path left="2" top="0" includeIn="selectedStates" id="check" itemCreationPolicy="immediate"
155. data="M 9.2 0.1 L 4.05 6.55 L 3.15 5.0 L 0.05 5.0 L 4.6 9.7 L 12.05 0.1 L 9.2 0.1">
156. <s:fill>
157. <!---
158. @private
159. The solid color fill for the CheckBox's checkmark. The default alpha is .9, and the default fill color is 0x000000.
160. -->
161. <s:SolidColor id="checkMarkFill" color="0" alpha="0.8" />
162. </s:fill>
163. </s:Path>
164. </s:Group>
165.
166. <!-- Label -->
167. <!--- @copy spark.components.supportClasses.ButtonBase#labelDisplay -->
168. <s:Label id="labelDisplay"
169. textAlign="start"
170. verticalAlign="middle"
171. maxDisplayedLines="1"
172. left="18" right="0" top="3" bottom="3" verticalCenter="2" />
173.
174. </s:SparkSkin>
175.
Generated by FlexWebFormater

Then I applied this skin to the checkbox instance


1. <s:CheckBox width="150" height="55" skinClass="CheckSkin"
2. label="Lorem ipsum et doloret ... Lorem ipsum et doloret ... Lorem ipsum et doloret ... Lorem ipsum et doloret ... Lorem ipsum et doloret ... Lorem ipsum et doloret ... Lorem ipsum et doloret ... "/>
Generated by FlexWebFormater

After you run this the checkbox behaves as before, it displays one line of text, adds ... at the end shows a tooltip with the rest of the text on mouse over. This is all because the maxDisplayedLines property of the Label is set to 1. In this case the checkbox will always show at most 1 line.
Next I played with the maxDisplayedLines property to see what else it can do. Basically if you set a number greater than 1 it will truncate the text to allow at most that number of lines.

maxDisplayedLines=0 Displays as much text as can fit, including even incomplete lines. This doesn't look good, but it might be useful in some cases. It also doesn't show any tooltip.




maxDisplayedLines=-1 Displays as much text as can fit, including even incomplete lines. If there is text left out, it adds ... at the end and displays a tooltip with the whole text.





If you remove the height property from the Checkbox, it will autoresize based on the maxDisplayedLines property. If this property is 0 or -1 it will resize to fit all text.