Grrr如此接近但仍然失败......
我在Flex中显示这个树,它包含两个节点类型:
请注意,我的问题是当我动态添加新的(HTML)节点到我的树时。
那么......我如何显示HTML节点?
因此我现在有:
[icon] [label]
[文本组件]
为什么?
默认标签是纯文本组件,不支持HTML,因此额外的组件:我想显示新人并忘记默认标签。
updateDisplayList()
,如果节点是一个丰富的节点,我将标签的高度设置为零,将我的组件的x和y设置为标签'x和y。所以...我错过了什么?啊,是的:我需要设置节点的高度,因为HTML文本可以比文本更大或更小。
measure()
这给了我一个相当可靠的不可靠的结果!
当我折叠/展开我的树时,每隔一段时间,我似乎得到了一个正确的HTML节点高度。另一次我得到'4'的高度恰好是HTML组件的填充,没有内容。
我知道我必须在这里做一些相当愚蠢的事......但我不确定是什么。我会发布我的代码,如果我的漫无目的,无法理解......
****编辑:这是我的渲染器的源代码 如您所见,只有'notes'节点使用HTML。 我添加一个'htmlComponent'子项,它将显示富文本,而默认标签为零大小并消失。 它绝对是非常原始的代码,因为它正在进行中!
package com.voilaweb.tfd
{
import mx.collections.*;
import mx.controls.Text;
import mx.controls.treeClasses.*;
import mx.core.UITextField;
import mx.core.UIComponent;
import flash.text.TextLineMetrics;
public class OutlinerRenderer extends TreeItemRenderer
{
private function get is_note():Boolean
{
return ('outlinerNodeNote' == XML(super.data).name().localName);
}
override public function set data(value:Object):void
{
super.data = value;
var htmlComponent:Text = super.getChildByName("htmlComponent") as Text;
if(!htmlComponent)
{
htmlComponent = new Text();
htmlComponent.name = "htmlComponent";
addChild(htmlComponent);
}
if(is_note)
htmlComponent.htmlText = XML(super.data).attribute('nodeText');
else
htmlComponent.htmlText = null;
setStyle('verticalAlign', 'top');
}
/*
* Today we've learnt a valuable lesson: there is no guarantee of when createChildren() will be invoked.
* Better be dirty and add children in set data()
override protected function createChildren():void
{
super.createChildren();
var htmlComponent:Text = new Text();
htmlComponent.name = "htmlComponent";
addChild(htmlComponent);
}
*/
override protected function measure():void
{
if(is_note)
{
super.measure();
var htmlComponent:Text = super.getChildByName("htmlComponent") as Text;
//Setting the width of the description field
//causes the height calculation to happen
htmlComponent.width = explicitWidth - super.label.x;
//We add the measuredHeight to the renderers measured height
//measuredHeight += (htmlComponent.measuredHeight - label.measuredHeight);
// Note the silly trick here...hopefully in the future I figure out how to avoid it
//
// Here is what happens: we check if measuredHeight is equal to decoration such as margin, insets...rather than that + some height
// If so, then we need to come up with an actual height which we do by adding textHeight to this height
// Note that I care about text being equal to margin etc but do not have proper access to these
// For instance UITextField.TEXT_HEIGHT_PADDING == 4 but is not accessible
// I am going to check if "<10" that will cover this case...
trace("For text " + htmlComponent.htmlText);
trace("width = " + htmlComponent.getExplicitOrMeasuredWidth()+" x height = " + htmlComponent.getExplicitOrMeasuredHeight());
var m:TextLineMetrics = htmlComponent.measureHTMLText(htmlComponent.htmlText);
//if(10 > htmlComponent.measuredHeight && !isNaN(htmlComponent.explicitHeight))
//htmlComponent.explicitHeight = m.height + htmlComponent.measuredHeight;
//if(htmlComponent.measuredHeight < 10) htmlComponent.explicitHeight = 50;
//measuredHeight += (htmlComponent.getExplicitOrMeasuredHeight() - super.label.getExplicitOrMeasuredHeight());
measuredHeight += (htmlComponent.getExplicitOrMeasuredHeight() - label.getExplicitOrMeasuredHeight());
trace("m:"+m.height+" Height: " + htmlComponent.getExplicitOrMeasuredHeight());
}
else
{
super.measure();
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
label.height = label.getExplicitOrMeasuredHeight(); // If you tell me my height, then I shall use my variable height!
graphics.clear();
if(is_note)
{
label.height = 0;
var htmlComponent:Text = super.getChildByName("htmlComponent") as Text;
htmlComponent.x = label.x;
htmlComponent.y = label.y;
htmlComponent.height = htmlComponent.getExplicitOrMeasuredHeight();
graphics.beginFill(0x555555);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
}
var complete:XMLList = XML(super.data).attribute('complete');
if(complete.length() > 0 && true == complete[0])
{
var startx:Number = data ? TreeListData(listData).indent : 0;
if(disclosureIcon)
startx += disclosureIcon.measuredWidth;
if(icon)
startx += icon.measuredWidth;
graphics.lineStyle(3, getStyle("color"));
var y:Number = label.y + label.getExplicitOrMeasuredHeight() / 2;
graphics.moveTo(startx, y);
graphics.lineTo(startx + label.getExplicitOrMeasuredWidth(), y);
}
}
}
}
答案 0 :(得分:1)
您对默认渲染器中的标签组件做出了错误的假设 - 它能够显示html内容。这个渲染器适合我:
public class HtmlTreeItemRenderer extends TreeItemRenderer {
override protected function commitProperties():void {
super.commitProperties();
label.htmlText = data ? listData.label : "";
invalidateDisplayList();
}
}
答案 1 :(得分:0)
如果您可以发布一些代码,肯定会有所帮助。
我想知道你为什么使用自定义html渲染器。是因为你想提到[icon] [label],你想在标签旁边显示一个图标?如果是这样,你可能最好使用iconField或iconFunction。
我想到的另一件事是variableRowHeight属性。如果您的节点具有不同的高度,则可能需要设置此值。
答案 2 :(得分:0)
试试吧。
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%" height="100%" verticalScrollPolicy="off"
horizontalScrollPolicy="off">
<mx:Script>
<![CDATA[
import mx.core.UITextField;
private var texto:UITextField;
override protected function createChildren():void
{
super.createChildren();
texto = new UITextField();
texto.setColor(0xFFFFFF);
texto.multiline = true;
texto.wordWrap = true;
texto.autoSize = TextFieldAutoSize.LEFT;
this.addChild(texto);
//texto.text = data.title;
}
override public function set data(value:Object):void
{
super.data = value;
if (value)
{
texto.htmlText = value.title;
this.invalidateDisplayList();
}
}
override protected function measure():void
{
super.measure();
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (texto)
texto.width = this.width;
}
]]>
</mx:Script>
</mx:Canvas>