Flex 3에서 DataGrid의 Header부분의 Separator는 headerSeparatorSkin 스타일로 정의되어 있다. 화면은 Flex DataGrid에 Separator가 붙은 보통의 모습이다.
위 프로그램은 아래와 같이 프로그래밍 한다.
<?xml version="1.0" encoding="utf-8"?> <!-- http://blog.flexexamples.com/2009/03/20/removing-the-header-separator-on-the-datagrid-control-in-flex/ --> <mx:Application name="DataGrid_headerSeparatorSkin_test" xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="white" layout="vertical"> <mx:DataGrid id="dataGrid"> <mx:dataProvider> <mx:ArrayCollection> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> </mx:ArrayCollection> </mx:dataProvider> </mx:DataGrid> </mx:Application>
만약 Separator를 지우고 싶다면 단순히 headerSeparatorSkin 에 mx.skins.ProgrammaticSkin으로 정의하면 된다. 아래는 실행화면과 소스코드이다. mx.skins.ProgrammaticSkin는 프로그램적으로 스킨을 만들 필요가 있을때 사용하는 클래스로 이 클래스 내부에서는 어떤 렌더링도 하지 않기 때문에 headerSeparatorSkin 을 이 클래스로 대체하는 것만으로도 Header의 separator를 삭제할 수 있는 것이다.
<?xml version="1.0" encoding="utf-8"?> <!-- http://blog.flexexamples.com/2009/03/20/removing-the-header-separator-on-the-datagrid-control-in-flex/ --> <mx:Application name="DataGrid_headerSeparatorSkin_test" xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="white" layout="vertical"> <mx:DataGrid id="dataGrid" headerSeparatorSkin="mx.skins.ProgrammaticSkin"> <mx:dataProvider> <mx:ArrayCollection> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> </mx:ArrayCollection> </mx:dataProvider> </mx:DataGrid> </mx:Application>
위 코드 대신 아래 코드처럼 <Style/> 블록이나 외부 .CSS 파일을 이용해서 headerSeparatorSkin의 스타일을 바꿀 수 있다.
<?xml version="1.0" encoding="utf-8"?> <!-- http://blog.flexexamples.com/2009/03/20/removing-the-header-separator-on-the-datagrid-control-in-flex/ --> <mx:Application name="DataGrid_headerSeparatorSkin_test" xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="white" layout="vertical"> <mx:Style> DataGrid { headerSeparatorSkin: ClassReference("mx.skins.ProgrammaticSkin"); } </mx:Style> <mx:DataGrid id="dataGrid"> <mx:dataProvider> <mx:ArrayCollection> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> </mx:ArrayCollection> </mx:dataProvider> </mx:DataGrid> </mx:Application>
또는 ActionScript 를 사용해 버튼을 누를때 동적으로 headerSeparatorSkin 스타일을 변경할 수 있도록 다음 코드처럼 만들 수 있다.
<?xml version="1.0" encoding="utf-8"?> <!-- http://blog.flexexamples.com/2009/03/20/removing-the-header-separator-on-the-datagrid-control-in-flex/ --> <mx:Application name="DataGrid_headerSeparatorSkin_test" xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="white" layout="vertical"> <mx:Script> <![CDATA[ import mx.skins.ProgrammaticSkin; private function btn_click(evt:MouseEvent):void { dataGrid.setStyle("headerSeparatorSkin", ProgrammaticSkin); } ]]> </mx:Script> <mx:Button id="btn" label="Set header separator skin" click="btn_click(event);" /> <mx:DataGrid id="dataGrid"> <mx:dataProvider> <mx:ArrayCollection> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> </mx:ArrayCollection> </mx:dataProvider> </mx:DataGrid> </mx:Application>
좀더 파헤쳐보자.
DataGrid에는 drawSeparators() 메소드가 protected로 지정되어 있다. 만약 DataGrid를 커스터마이징해서 Separator 그리는 방식을 바꾸고 싶다면 drawSeparators() 부터 찾아가면 된다. 아래 코드는 DataGrid의 drawSeparators() 메소드 정의이다
/**
* Creates and displays the column header separators that the user
* normally uses to resize columns. This implementation uses
* the same Sprite as the lines and column backgrounds and adds
* instances of the headerSeparatorSkin
and attaches mouse
* listeners to them in order to know when the user wants
* to resize a column.
*/
protected function drawSeparators():void
{
DataGridHeader(header)._drawSeparators();
if (lockedColumnHeader)
DataGridHeader(lockedColumnHeader)._drawSeparators();
}
위 코드에서 볼 수 있듯이 결국 DataGridHeader에 정의된 _drawSeparators()쪽을 살펴봐야한다. 아래는 DataGridHeader의 _drawSeparators()와 drawSeparators() 부분이다.
mx_internal function _drawSeparators():void
{
drawSeparators();
}
/**
* Creates and displays the column header separators that the user
* normally uses to resize columns. This implementation uses
* the same Sprite as the lines and column backgrounds and adds
* instances of the headerSeparatorSkin
and attaches mouse
* listeners to them in order to know when the user wants
* to resize a column.
*/
protected function drawSeparators():void
{
if (!separators)
separators = [];
var lines:UIComponent = UIComponent(getChildByName("lines"));
if (!lines)
{
lines = new UIComponent();
lines.name = "lines";
addChild(lines);
}
else
setChildIndex(lines, numChildren - 1);
// required to deal with some 2.x clipping behavior
lines.scrollRect = new Rectangle(0, 0, unscaledWidth, unscaledHeight + 1);
if (headerSepSkinChanged)
{
headerSepSkinChanged = false;
clearSeparators();
}
var n:int = visibleColumns ? visibleColumns.length : 0;
if (!needRightSeparator && n > 0)
n--;
for (var i:int = 0; i < n; i++)
{
var sep:UIComponent;
var sepSkin:IFlexDisplayObject;
if (i < lines.numChildren)
{
sep = UIComponent(lines.getChildAt(i));
sepSkin = IFlexDisplayObject(sep.getChildAt(0));
}
else
{
var headerSeparatorClass:Class =
getStyle("headerSeparatorSkin");
sepSkin = new headerSeparatorClass();
if (sepSkin is ISimpleStyleClient)
ISimpleStyleClient(sepSkin).styleName = this;
sep = new UIComponent();
sep.addChild(DisplayObject(sepSkin));
lines.addChild(sep);
separators.push(sep);
}
// if not separator
if ( !(i == visibleColumns.length-1 && !needRightSeparatorEvents) )
{
DisplayObject(sep).addEventListener(
MouseEvent.MOUSE_OVER, columnResizeMouseOverHandler);
DisplayObject(sep).addEventListener(
MouseEvent.MOUSE_OUT, columnResizeMouseOutHandler);
DisplayObject(sep).addEventListener(
MouseEvent.MOUSE_DOWN, columnResizeMouseDownHandler);
}
else
{
// if not separator
if ( (i == visibleColumns.length-1 && !needRightSeparatorEvents) )
{
DisplayObject(sep).removeEventListener(
MouseEvent.MOUSE_OVER, columnResizeMouseOverHandler);
DisplayObject(sep).removeEventListener(
MouseEvent.MOUSE_OUT, columnResizeMouseOutHandler);
DisplayObject(sep).removeEventListener(
MouseEvent.MOUSE_DOWN, columnResizeMouseDownHandler);
}
}
var cols:Array = visibleColumns;
if (!(cols && cols.length > 0 || dataGrid.headerVisible))
{
sep.visible = false;
continue;
}
sep.visible = true;
sep.x = headerItems[i].x +
visibleColumns[i].width - Math.round(sepSkin.measuredWidth / 2);
if (i > 0)
{
sep.x = Math.max(sep.x,
separators[i - 1].x + Math.round(sepSkin.measuredWidth / 2));
}
sep.y = 0;
sepSkin.setActualSize(sepSkin.measuredWidth, Math.ceil(cachedHeaderHeight));
// Draw invisible background for separator affordance
sep.graphics.clear();
sep.graphics.beginFill(0xFFFFFF, 0);
sep.graphics.drawRect(-separatorAffordance, 0,
sepSkin.measuredWidth + separatorAffordance,
cachedHeaderHeight);
sep.graphics.endFill();
sep.mouseEnabled = true;
}
while (lines.numChildren > n)
{
lines.removeChildAt(lines.numChildren - 1);
separators.pop();
}
}
DataGridHeader의 drawSeparators()에서 headerSeparatorSkin 스타일을 사용하는 것을 찾아볼 수 있다. 개발자는 이 부분을 커스터마이징할 수 있는 것이다.
DataGrid나 DataGridHeader를 커스터마이징할 필요없이 스킨만 변경하고 싶다면 headerBackgroundSkin의 기본 스킨인 mx.skins.halo.DataGridHeaderSeparator를 커스터 마이징하거나 mx.skins.Programmatics를 확장해서 사용하면 되겠다. 아래코드는 DataGrid에서 headerBackgroundSkin이 Style로 정의된 것을 보여주고 있다.
/** * The class to use as the skin that defines the appearance of the * background of the column headers in a DataGrid control. * @default mx.skins.halo.DataGridHeaderSeparator */ [Style(name="headerBackgroundSkin", type="Class", inherit="no")]
아래 코드는 mx.skins.halo.DataGridHeaderSeparator를 보여준다.
//////////////////////////////////////////////////////////////////////////////// // // ADOBE SYSTEMS INCORPORATED // Copyright 2005-2007 Adobe Systems Incorporated // All Rights Reserved. // // NOTICE: Adobe permits you to use, modify, and distribute this file // in accordance with the terms of the license agreement accompanying it. // //////////////////////////////////////////////////////////////////////////////// package mx.skins.halo { import flash.display.Graphics; import mx.skins.ProgrammaticSkin; /** * The skin for the separator between column headers in a DataGrid. */ public class DataGridHeaderSeparator extends ProgrammaticSkin { include "../../core/Version.as"; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. */ public function DataGridHeaderSeparator() { super(); } //-------------------------------------------------------------------------- // // Overridden properties // //-------------------------------------------------------------------------- //---------------------------------- // measuredWidth //---------------------------------- /** * @private */ override public function get measuredWidth():Number { return 2; } //---------------------------------- // measuredHeight //---------------------------------- /** * @private */ override public function get measuredHeight():Number { return 10; } //-------------------------------------------------------------------------- // // Overridden methods // //-------------------------------------------------------------------------- /** * @private */ override protected function updateDisplayList(w:Number, h:Number):void { super.updateDisplayList(w, h); var g:Graphics = graphics; g.clear(); // Highlight g.lineStyle(1, 0xFFFFFF, 0.5); g.moveTo(0, 0); g.lineTo(0, h); g.lineStyle(1, getStyle("borderColor")); g.moveTo(1, 0); g.lineTo(1, h); } } }
이외로 단순해서 놀랬는가? 결국 이 스킨은 borderColor 스타일로 지정된 색으로 구분자 선만 그어준다. 나는 이것을 바꿔서 실선을 점선을 그리도록 해보겠다. 아래 코드는 이를 구현한 DataGridHeaderDotSeparator 클래스이다.
package { import flash.display.Graphics; import mx.skins.halo.DataGridHeaderSeparator; /** * DataGrid Header에 점선을 그린다. */ public class DataGridHeaderDotSeparator extends DataGridHeaderSeparator { /** * Constructor. */ public function DataGridHeaderDotSeparator() { super(); } /** * @private */ override protected function updateDisplayList(w:Number, h:Number):void { var g:Graphics = graphics; g.clear(); g.lineStyle(1, getStyle("borderColor"), 1); var i:int; for( i = 0; i < h; i+=4 ) { g.drawCircle( 1.5, i, 0.5 ); } } } }
아래 코드는 DataGridHeaderDotSeparator 스킨을 사용하는 예제이다.
<?xml version="1.0" encoding="utf-8"?> <!-- http://blog.flexexamples.com/2009/03/20/removing-the-header-separator-on-the-datagrid-control-in-flex/ --> <mx:Application name="DataGrid_headerSeparatorSkin_test" xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="white" layout="vertical"> <mx:DataGrid id="dataGrid" headerSeparatorSkin="DataGridHeaderDotSeparator"> <mx:dataProvider> <mx:ArrayCollection> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> <mx:Object c1="1. One" c2="1. Two" c3="1. Three"/> </mx:ArrayCollection> </mx:dataProvider> </mx:DataGrid> </mx:Application>
아래는 위 코드를 실행한 화면이다. Header부분에 구분자(Separator)가 점선으로 되었다. 좀 뭉뚝하지만 그냥 예제일 뿐이니깐 넘어가자. ^^;
Flex는 이처럼 프로그램적으로 스킨을 변경할 수 있다. 물론 이미지를 이용하는 방법도 있다. 이와 같은 방법으로 스킨을 변경하는 것은 Flex의 모든 컴포넌트에서 지원하므로 이런 스킬에 익숙해질 필요가 있겠다.
원본 예제 : Removing the header separator on the DataGrid control in Flex
주절주절 : 그냥 이렇게 가볍게 포스팅하는 것이 좋을 것 같다는 생각이 든다.
글쓴이 : 지돌스타(http://blog.jidolstar.com/546)
'비공개 > Adobe Flex, ActionScript 3.0' 카테고리의 다른 글
[Flex/AIR]UIComponent 클래스의 라이프 사이클(Life Cycle)을 표현한 그림 (2) | 2009.07.14 |
---|---|
[Flex 4]Flex 4 CSS 탄생의 비밀 - Adobe Bug Reporting System (5) | 2009.07.09 |
ActionScript 3.0을 알자! (7) | 2009.06.26 |
[Flash,ActionScript3.0]Vector와 Bitmap 이미지를 이용한 최적화된 애플리케이션 만들기 (12) | 2009.06.15 |
[Flash,ActionScript 3.0]DisplayObject cacheAsBitmap 속성의 적용시점 문제 (10) | 2009.06.10 |