다음 예제는 어떻게 indicator skin을 FormItem 컨테이너에 어떻게 설정하는가 보여주고 있다. 기본적으로 이것을 설정하기 위해서는 FormItem에 정의되어 있는 Style속성인 indicatorSkin을 사용하면 되겠다.
[소스보기]
[실행화면]
소스에서 보면 두개의 속성이 눈에 띈다. 즉 indicatorSkin과 indicatorGap 이다.
이 두 속성이 어떻게 적용되는가 살펴봤다.
Flex SDK의 FormItem을 살펴보면 아래와 같이 두 Style속성이 Metadata로 설정되어 있다.
/**
* Number of pixels between the label and child components of the form item.
*
* @default 14
*/
[Style(name="indicatorGap", type="Number", format="Length", inherit="yes")]
/**
* Specifies the skin to use for the required field indicator.
*
* @default mx.containers.FormItem.Required
*/
[Style(name="indicatorSkin", type="Class", inherit="no")]
즉, MXML에서 형태로 참고할 수 있다는 것을 의미한다. 또한 지정되어야할 Style Type과 상속관계가 명시됨으로 더 구체적으로 Style 사용범위를 좁힐 수 있겠다.
indicatorGap은 invalidateSize()시 호출되는 UIComponent에서 오버로딩되어 참조한 measure()함수에서 사용한다.
override protected function measure():void
{
if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_3_0)
{
previousMeasure();
return;
}
super.measure();
if (direction == FormItemDirection.VERTICAL)
measureVertical();
else
measureHorizontal();
}
private function measureVertical():void
{
// use VBox and then take into account label, indictor gap
verticalLayoutObject.measure();
// Need to include label and indictor gap for width
var extraWidth:Number = calculateLabelWidth() + getStyle("indicatorGap");
measuredMinWidth += extraWidth;
measuredWidth += extraWidth;
// need to include label for height
var labelHeight:Number = labelObj.getExplicitOrMeasuredHeight();
measuredMinHeight = Math.max(measuredMinHeight, labelHeight);
measuredHeight = Math.max(measuredHeight, labelHeight);
}
위에서 보면 measuerdWidth를 설정하는데 Label폭과 indicatorGap속성을 참고하는 것을 알 수 있다. 즉, indicatorSkin의 x축 위치는 extraWidth만큼이 된다는 것을 유추해볼 수 있다.
그럼 실제로 indicatorSkin을 설정하는 부분은 어디 있을까?
먼저 UIComponent에서 오버로딩한 updateDisplayList()를 살펴보면
var x:Number = vm.left;
var y:Number = vm.top;
var labelWidth:Number = calculateLabelWidth();
// Set label size.
labelObj.setActualSize(labelWidth, labelObj.getExplicitOrMeasuredHeight());
labelObj.move(x, y);
x += labelWidth;
// Position the "required" indicator.
displayIndicator(x, y);
이런식으로 만들어져 있다. 좌측 label이 위치하고 바로 그 오른쪽에 indicatorSkin을 위치할 수 있도록 코드가 짜여져 있다는 것을 알 수 있다. 그럼 실제적으로 Display 해주는 displayIndicator()함수를 살펴보자.
private function displayIndicator(xPos:Number, yPos:Number):void
{
if (required)
{
if (!indicatorObj)
{
var indicatorClass:Class = getStyle("indicatorSkin") as Class;
indicatorObj = IFlexDisplayObject(new indicatorClass());
rawChildren.addChild(DisplayObject(indicatorObj));
}
indicatorObj.x =
xPos + ((getStyle("indicatorGap") - indicatorObj.width) / 2);
if (labelObj)
{
indicatorObj.y = yPos +
(labelObj.getExplicitOrMeasuredHeight() -
indicatorObj.measuredHeight) / 2;
}
}
else
{
if (indicatorObj)
{
rawChildren.removeChild(DisplayObject(indicatorObj));
indicatorObj = null;
}
}
}
분석하면서 알았지만 위에 required get/set 함수가 있다. 이 함수는 indicatorSkin을 보여줄 것이냐 말것이냐 결정하는 거다.
required속성이 true인 경우 indicatorSkin을 보여주도록 만들어져있다. getStyle()로 indicatorSkin을 읽어오고 IFlexDisplayObject로 오브젝트를 생성한다음 자식으로 추가한다. 다음으로는 x,y를 indicatorGap Style속성, indicatorSkin자체 크기, 그리고 label오브젝트의 크기에 따라서 보기좋게 위치를 지정한다.
대충 indicatorGap과 indicatorSkin Style속성이 어떻게 동작되어지는가 살펴보았다.
이러한 분석은 자신만의 새로운 커스텀 컴포넌트를 만드는데 가이드 역할을 할 수 있다.
그러므로 Flex SDK를 분석해보는 습관도 좋은 것 같다.
소스출처 : blog.flexexamples.com
Trackback URL : http://blog.jidolstar.com/trackback/303
Leave your greetings here.
mello 2008/12/16 11:57 Modify/Delete Reply Address
오호호.. 나이스군요..
지돌스타 2008/12/16 16:20 Modify/Delete Address
ㅎㅎ 예~ 감사합니다.
모험가 2008/12/29 19:35 Modify/Delete Reply Address
좋은글 감사합니다~ 흐흐