This post began as a plea for help, but in the course of writing it I
landed on a solution I can live with. I am posting it anyway, on the
chance that it might help someone else, or in case somebody has a
better idea.
The problem came up when I was trying to create a custom HSlider
using a programmatic skin to render a simple white line in place of
the default track skin. I wanted two thumb handles initially
positioned at either end of the component. With my custom track skin
in effect, Flex was ignoring the initial values and positioning both
handles at the far left end of the track. The problem is the same
when using a single thumb handle positioned anywhere beyond the
minimum value.
Here is the mxml declaration:
<mx:HSlider id="myCustomSlider" width="100"
minimum="0" maximum="100" thumbCount="2"
trackSkin="myCustomTrackSkin"
values="[0,100]"/>
And here is the code for the custom skin:
// file myCustomTrackSkin.as
package
{
import mx.skins.ProgrammaticSkin;
public class MyCustomTrackSkin extends ProgrammaticSkin
{
private static const LINE_THICKNESS:int=1;
override public function get height():Number
{
return LINE_THICKNESS;
}
override protected function updateDisplayList(
w:Number, h:Number):void
{
graphics.clear();
super.updateDisplayList(w, h);
graphics.beginFill(0xFFFFFF);
graphics.drawRect(0,0, w, LINE_THICKNESS);
graphics.endFill();
}
}
}
It seemed the component was getting 0 for the track width at creation
time, and placing both handles at that position. Subsequent re-
positioning of the handles (by dragging or by setting the slider's
values in code) worked fine.
I came up with 2 workarounds, neither of which I liked very much:
1) In myCustomTrackSkin.as, added the following:
override public function get width():int
{
return 100; // Yikes... a magic number, not very reusable!
}
2) skipped the override of get width(), and instead changed the mxml:
trackSkin="myCustomTrackSkin"
was replaced by:
creationComplete=
"mySlider.setStyle('trackSkin',myCustomTrackSkin)"
Both of these "solutions" work, but both are undesirable. #1 is
clearly not very reusable. #2 is a bit better, but requires some
oddball contortions in the mxml.
Here is the final solution I came up with:
3) In myCustomTrackSkin.as, added the following:
override public function get width():int
{
var w:Number;
try
{
w = parent.parent.width;
} catch (anyError:Error) {
w = 0;
}
return w;
}
The try/catch block is needed because Flex calls get width() multiple
times, including when this.parent and/or this.parent.parent is null.