[英]In Flex, what is a better way to build UI component whose height is based on width and content?
我需要构建一个基于UIComponent的新UI控件。 控件的高度应与宽度具有一定的比例,并且还取决于显示的内容(内部文本的数量)。 有人可以推荐我该怎么做吗?
我试过谷歌搜索,但似乎所有文章只是试图避免谈论案件。 我个人的感觉是,Flex渲染的方式,即无效和更新显示列表,本身就无法有效地处理这种情况。
以下是我的代码。 它工作得很好,但似乎这不是最有效的方法,因为高度是在updateDisplayList()内部计算的,它会触发另一个updateDisplayList()。
控件在移动项目中使用,因此当旋转设备时,将更改父级的大小,并且还需要调整控件的大小。
那么,有几个问题:
以下是我的意思的一个例子。
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import mx.core.UIComponent;
public class MyControl extends UIComponent
{
public function MyControl()
{
super();
}
public var textPadding:Number = 15;
public var heightRatio:Number = 1.61803398875;
private var _label:String;
private var labelChanged:Boolean = false;
public function get label():String
{
return _label;
}
public function set label(value:String):void //can be long text with about 20-30 lines
{
if (_label != value)
{
_label = value;
labelChanged = true;
invalidateProperties();
invalidateSize();
invalidateDisplayList();
}
}
private var text:TextField;
override protected function createChildren():void
{
super.createChildren();
if (!text)
{
text = new TextField();
text.autoSize = TextFieldAutoSize.LEFT;
text.multiline = true;
text.wordWrap = true;
addChild(text);
}
}
override protected function commitProperties():void
{
super.commitProperties();
if (labelChanged)
{
text.text = label;
labelChanged = false;
}
}
override protected function measure():void
{
super.measure();
//What should I do here?
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
text.width = unscaledWidth;
if (text.height < unscaledWidth / heightRatio)
{
height = unscaledWidth / heightRatio + textPadding * 2;
}
else
{
height = text.height + textPadding * 2;
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
text.x = textPadding;
text.y = textPadding;
}
}
我需要构建一个基于UIComponent的新UI控件。 控件的高度应与宽度具有一定的比例,并且还取决于显示的内容(内部文本的数量)。 有人可以推荐我该怎么做吗?
从技术上讲,你做不到。
您对Flex工作原理的整体方法/理解存在根本缺陷。
Flex组件永远不会自行调整大小。 它始终由其父级调整大小。 measure()方法将设置理想值:measuredWidth,measuredHeight,measuredMinWidth和measuredMinHeight。 但是,它们只是提供给父容器的建议; 可能会也可能不会使用它们。
MXML掩盖了这个概念,你的误解很常见。
在大多数情况下,默认的Flex布局容器将尽力遵守这些值,但它们具有处理空间不足的情况的逻辑。 例如; 具有两个子项的VGroup都设置为100%高度不会将两个子项的大小设置为VGroup的100%。
如果没有看到使用和调整组件大小的代码,就很难说出发生了什么。 很可能你设置的“高度”不会被父容器覆盖; 这是我相信这种方法有效的唯一原因。
我在这里做一些假设; 但我认为你的测量方法应该是这样的:
override protected function measure():void
{
super.measure();
this.measuredwidth = text.getMeasuredOrExplicitWidth();
this.measuredHeight = text.getMeasuredOrExplicitHeight()/heightRatio + textPadding * 2;
}
updateDisplayList(),应该是这样的:
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
text.width = unscaledWidth;
text.height = unscaledWidth / heightRatio;
super.updateDisplayList(unscaledWidth, unscaledHeight);
text.x = textPadding;
text.y = textPadding;
}
组件的父容器中的updateDisplayList()应该执行以下操作:
myControlInstance.height = myControlInstance.measuredHeight;
myControlInstance.width = myControlInstance.measuredWidth;
Spark框架使用所有相同的方法; 但有时候会把它们拖了一下。 因此,updateDisplayList()和measure()通常在皮肤类中; 或布局类。
根据Adobe文档http://livedocs.adobe.com/flex/3/html/help.html?content=ascomponents_advanced_2.html,measure ()用于测量默认大小,updateDisplayList()用于调整和放置子项组件。
回答你的问题:
1)我会说什么也不做,因为你对默认大小不感兴趣。
2)我认为,这并不重要,因为值更改不会立即生效(因为您将再次调用updateDisplayList)。
我的建议是有一个widthChanged事件的监听器,并使用它计算适当的高度。 并在更改标签时进行高度计算。
没有办法绕过额外的更新周期,这只是具有文本重排的布局的本质。 通常它是如何完成的(或者至少它是如何在flex组件中完成的)是首先根据它的首选宽度进行测量,如果测量没有明确边界的文本,这可能相当宽。 但是,此测量非常重要,因为它会在layoutBoundsWidth或layoutBoundsHeight中设置uper limit之前,如果及何时尝试扩展宽度,则通知父容器。 一旦在第一次调用updateDisplayList中设置了边界,就应该调整文本大小并使invalidSize()无效,这样就可以测量第二遍的高度。 对不起我手机上没有代码示例。 如果你需要它们,我可以在办公室时张贴一些。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.