[英]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.