Flex定制Tree外观

来源:互联网 发布:居民社保退休工资算法 编辑:程序博客网 时间:2024/05/29 02:54

定制Tree 的外观

Flex 中的Tree是mx前缀的组件,spark组件中没有替代品。
以下解决Flex4 项目中外观的定制化。

更换背景

backgroundColor 和 backgroundAlpha两个样式属性无法在flex4的项目中使用。替代的只有一个属性:contentBackgroundColor,没有找到背景透明度的相关设置功能。

更换图标

图标包括叶子节点的图标、分支节点的图标、分支节点的打开关闭图标
需要分别设置:defaultLeafIcon、folderClosedIcon、folderOpenIcon、disclosureClosedIcon、disclosureOpenIcon属性,它们的值需要是绑定的图标文件Class。

定制项内容

指定Tree的项渲染器,项渲染器要以MXTreeItemRenderer扩展。

<?xml version="1.0" encoding="utf-8"?><s:MXTreeItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"                       xmlns:s="library://ns.adobe.com/flex/spark"                       xmlns:mx="library://ns.adobe.com/flex/mx" height="55"                           >    <fx:Script>        <![CDATA[            override public function set data(value:Object):void {                super.data = value;                if(treeListData.hasChildren)                {                    setStyle("fontWeight", 'bold');                    labelField.text =  treeListData.label;                }                else                {                    setStyle("fontWeight", 'normal');                    labelField.text =  treeListData.label;                }              }        ]]>    </fx:Script>    <s:states>        <s:State name="normal" />                    <s:State name="hovered" />        <s:State name="selected" />    </s:states>    <s:Rect left="0" right="0" top="0" bottom="0">        <!--填充颜色-->        <s:fill>            <s:SolidColor color="0x0" alpha="0.85" />        </s:fill>    </s:Rect>       <s:HGroup left="0" right="0" top="0" bottom="0" verticalAlign="middle">        <s:Rect id="indentationSpacer" width="{treeListData.indent}" percentHeight="100" alpha="0">            <s:fill>                <s:SolidColor color="0xFF0000" alpha="1" />            </s:fill>        </s:Rect>        <s:Group id="disclosureGroup">            <s:BitmapImage source="{treeListData.disclosureIcon}" visible="{treeListData.hasChildren}" />        </s:Group>        <s:BitmapImage source="{treeListData.icon}" />        <s:Label id="labelField" color="#FFFFFF" fontSize="18" text="{treeListData.label}" paddingTop="2"/>    </s:HGroup>    <s:Line left="10" right="10" bottom="0">        <s:stroke>            <s:SolidColorStroke color="0x505050"/>        </s:stroke>    </s:Line></s:MXTreeItemRenderer>

控制项间隙

需要指定Tree的paddingBottom和paddingTop 属性。
如果不需要间距可以将他们都设置为0。

指定Tree的纵向滚动条皮肤

需要指定Tree的verticalScrollBarStyleName,他是一个样式名称。

一个没生效的做法

.MyStyleName {        skinClass:ClassReference("skins.bookdetailVScrollBar.BookDetailVScrollbarSkin")}

其中的皮肤类修改自spark VScrollBarSkin,其中指定了滑轨、滑块、上下按钮的样式。

这个方法不生效,原因未知。

一个可行的方法

.MyStyleName {    downArrowSkin: ClassReference(null);    upArrowSkin: ClassReference(null);trackSkin:ClassReference("skins.bookdetailVScrollBar.BookDetailVScrollBarTackSkin");    thumbSkin:ClassReference("skins.bookdetailVScrollBar.BookDetailVScrollBarThumSkin")}

这个样式写法中,指定了滚动条的四个部分。其中上下按钮不需要,注意他们的写法。

背景透明(spark)

contentBackgroundAlpha=”0”
只保留了渲染项的内容和边框。

背景颜色(spark)

contentBackgroundColor

渲染项颜色和背景的关系处理

背景有时候会超过所有渲染项的高度,如果二者颜色不同,看起来非常不舒服。所以可以设置背景颜色,渲染项多数内容透明。

选中项颜色

selectionColor

鼠标经过项颜色

rollOverColor

给Tree提供数据源

采用ArrayCollection

多级数据需要有“children ”属性,其内容应该是该项的子项内容。

控制Tree的展开闭合

方法

expandChildrenOf

expandItem

判断是否开合

isItemOpen

属性

openItems
可以是数组。将其置为空数组,关闭所有开启菜单。这个操作会清空选中项。

渲染项高度固定情况下,让Tree高度自适应

我们的目标是万一内容过多,Tree在占满了可占空间后,自己出现滚动条;在内容渲染后没有达到这个高度前,有多少内容Tree就显示多高。
这里关键要动态设置rowCount属性。
要设置这个属性,我们就不能同时设置Tree的height属性了。
我们监听updateComplete事件,这时更改的内容已经刷新,我们只需要通过rowCount属性告诉Tree:你要显示n行数据就好了。

接下来就是如何计算这个n了,这里采用了一个笨办法,渲染项的高度或者rowHeight 屬性是表示一行的高度,Tree允許的最大高度也是可以得到的,二者做個除法就好了,當然,要向下取整。

一个更完善的版本

上面的方法如遇到多于两级的数据,在孙子目录开启后,tree的尺寸就不对了。问题的原因是:这时tree正在显示多少项没法计算出来,进而无法准确设置rowCount属性。

更好的方法是不再监听updateComplete事件,改而监听itemOpenitemClose事件,这两个事件在项被打开或者关闭的时候调度,在事件类型中,有当前操作的渲染项实例和操作的数据。有了当前操作的数据,我们可以计算出这次操作影响了多少项,然后我们再根据最多能显示多少项、一级数据的个数,决定rowCount合适的值。

以下是主要的代码:

private var showRow:uint;// tree 当前一共有多少项显示private function findOpenNum(aimItem:Object,openItems:Array):uint{    var numChildren:uint=aimItem.children.length;    for (var i:int = 0; i < aimItem.children.length; i++)     {        var it:Object=aimItem.children[i];        if(it.children)// 有子        {            if(openItems.indexOf(it)!=-1)// 子开            {                numChildren+=findOpenNum(it,openItems);            }        }    }    return numChildren;}protected function chapterTree_itemCloseOpenHandler(event:TreeEvent):void{    var item:Object=event.item;    var tree:Tree=event.currentTarget as Tree;    var numChildren:uint=findOpenNum(item,tree.openItems as Array);    if(event.type==TreeEvent.ITEM_CLOSE)    {        this.showRow-=numChildren;    }else if(event.type==TreeEvent.ITEM_OPEN)    {        this.showRow+=numChildren;    }    if(this.showRow>=this.maxRow)    {        tree.rowCount=this.maxRow;    }else    {        tree.rowCount=this.showRow;    }    trace("变化项个数:"+numChildren+  ",显示个数:"+tree.rowCount);   }

itemOpenitemClose事件共同的监听方法是chapterTree_itemCloseOpenHandler,这个方法中根据操作的数据获得这次操作在tree中添加或者减少了numChildren项数据,进而计算当前tree中有showRow项处于展示状态,接下来比较showRow和maxRow(显示的内容是否多于能显示的最大项数量),决定显示多少行数据。

其中的findOpenNum方法中,用到了递归,计算影响展开项的数量。这个数量包括当前子项和当前子项的展开项的的数量。

修改tree的dataProvider,需要设置showRow为一级数据的长度。

参考内容

Moving to Flex 4

Using a Spark item renderer with an MX control

原创粉丝点击