繁体   English   中英

在Flex中,构建高度基于宽度和内容的UI组件的更好方法是什么?

[英]In Flex, what is a better way to build UI component whose height is based on width and content?

我需要构建一个基于UIComponent的新UI控件。 控件的高度应与宽度具有一定的比例,并且还取决于显示的内容(内部文本的数量)。 有人可以推荐我该怎么做吗?

我试过谷歌搜索,但似乎所有文章只是试图避免谈论案件。 我个人的感觉是,Flex渲染的方式,即无效和更新显示列表,本身就无法有效地处理这种情况。

以下是我的代码。 它工作得很好,但似乎这不是最有效的方法,因为高度是在updateDisplayList()内部计算的,它会触发另一个updateDisplayList()。

控件在移动项目中使用,因此当旋转设备时,将更改父级的大小,并且还需要调整控件的大小。

那么,有几个问题:

  1. 我应该怎么做measure()? 由于高度基于实际宽度,因此我无法在updateDisplayList()之前获得最终宽度,因为控件的父级宽度定义为百分比。
  2. 在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM