ItemRenderer 高度(和高度变化)未反映在 AdvancedDataGrid 行中
我有一个 AdvancedDataGrid,其可变行高设置为 true。 我编写了一个基于 DataGroup Spark 组件的 cutsom 项目渲染器。网格中的每一行都有多个要显示的实体,实体的x位置和宽度基于实体本身的数据。
我有一个为 DataGroup 编写的自定义布局,它根据每个实体的数据来测量和定位每个实体。每行中的每个实体可以截断或不截断其标签。当标签未被截断时,我在数据组布局的测量方法中计算对象的实际宽度并手动验证其大小(以强制标签具有正确的宽度并布局其所有文本行并重新测量自身),以准确测量对象的实际宽度。数据组本身。
布局、测量、尺寸调整、显示等都正常工作。实体报告在不截断标签时所需的正确高度,数据组报告绘制其所有行的实体所需的正确大小(所有这些都来自测量方法,就像它们在 UIComponent 生命周期下需要的那样)。
在 AdvancedDataGrid 本身内部时,行的大小不正确。大多数行不需要多行并且显示得很好。那些需要多行的行具有较大的行高,但在大多数情况下不足以容纳整个文本。该行的 DataGroup(及其 itemRenderer)被剪裁。此外,滚动网格时,无论数据如何,屏幕上滚动的每一行都是默认的 1 文本行高度。无论如何,调整 AdvancedDataGrid 的大小(不是调整其列的大小,而是调整网格本身的大小)会强制所有行对齐到正确的所需高度。再次滚动会产生大小不正确的行。
此外,行中每个实体的布局由多个外部因素决定 - 最常见的是可见范围(沿水平方向)。更改此可见范围将触发所有项目渲染器将自身大小(通过自定义布局类)调整为新大小并重新测量新的数据组布局。这实际上会触发一个自定义层次结构解析器,该解析器会重建 AdvandedDataGrid 数据提供程序内使用的所有 ArrayCollections,因此 ArrayCollections 正在调度每行的 DataGroup 做出反应的更改事件,因此 DataGroup 本身正在使其大小和布局无效。
这些大小调整不会触发 AdvancedDataGrid 重新测量其行高,并且我必须再次调整 ADG 本身的大小以将行对齐到正确的高度。
任何人都有在 AdvancedDataGrid 或 ItemRenderers 中动态调整行大小的经验,这些行必须强制使 AdvandedDataGrid 重新布局其行?
不幸的是,我无法提供源代码,因为有大量的类、层次结构数据、将封闭节点卷成多行、自定义层次结构解析器、大量项目渲染器 - 这也是政府合同。
我在一个更简单的项目渲染器上遇到了类似的问题,基本上是一个尊重最大高度的标签,根据其自动换行数据需要将其自身调整到该高度,然后为自己创建滚动条。同样,创建网格时数据大小几乎是正确的,然后更改网格内的列宽不会在项目渲染器调整到其新宽度时调整行高的大小。只有在调整网格本身大小时,项目渲染器才能正确调整大小,创建滚动条,并且网格行高度正确。该项目渲染器的来源:
<s:Scroller xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
implements="mx.controls.listClasses.IDropInListItemRenderer,mx.controls.listClasses.IListItemRenderer"
horizontalScrollPolicy="off" width="100%">
<fx:Script>
<![CDATA[
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.events.ResizeEvent;
private var _listData:BaseListData;
private var _data:Object;
private var _listOrData_c:Boolean = false;
public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = value;
_listOrData_c = true;
invalidateProperties();
}
public function get data():Object
{
return _data
}
public function set data(value:Object):void
{
_data = value;
_listOrData_c = true;
invalidateProperties();
}
override protected function commitProperties():void
{
if(_listOrData_c)
{
_listOrData_c = false;
label.text = _listData.label;
}
super.commitProperties();
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Group width="100%">
<s:layout>
<s:BasicLayout clipAndEnableScrolling="true" />
</s:layout>
<s:Label id="label" width="100%"/>
</s:Group>
</s:Scroller>
将其放入 AdvancedDataGrid 中并使用非常大的文本块设置一些数据。调整列的大小,然后调整网格本身的大小,希望您可以重现相同的结果。确保在项目渲染器上设置最大高度,例如:
<mx:AdvancedDataGridColumn id="adgc1" headerText="Name" dataField="label">
<mx:itemRenderer>
<fx:Component>
<newLayouts:ScrollingTextItemRenderer maxHeight="60" />
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
使用 Flex 4.1。
感谢您的帮助。
以下是详细说明项目渲染器应有功能的屏幕截图(因为我已修复测量以在测量之前强制验证显式当前宽度的标签):
非常宽的列,没有滚动条,测量的标签高度显示在行高中
宽度列较小,某些渲染器已达到最大高度并正在创建滚动条,最后一个渲染器仍在使用测量的标签高度
较小的静止列,达到所有最大高度,并且所有标签都存在滚动条,滚动条将选择该行使用时但允许滚动,以便所有文本都可见。
I have an AdvancedDataGrid with variable row height set to true.
I have written a cutsom item renderer based on the DataGroup spark component. Each row in the grid has multiple entities to display, the x position and width of the entites are based on the data of the entity itself.
I have a custom layout written for the DataGroup that measures and posistions each entity based on its data. Each entity in each row can either truncate or not truncate its label. When the labels are not truncated, I calculate the actual width of the object and validate its size manualy (to force the label to have the correct width and layout all its text lines and remeasure itself) within the DataGroup's Layout's measure method to accurately measure the datagroup itself.
The layouts, measuring, sizing, display, etc all work correctly. The entitys report the correct height they need when not truncating the labels, the datagroup reports the correct size it needs to draw all of its row's worth of entities (all from measure methods like they need to under the UIComponent lifecycle).
When inside the AdvancedDataGrid itself, rows are not sized correctly. The majority of the rows do not require multiple lines and display just fine. Those that require multiple lines have larger row heights, but not large enough to accomodate the entire text in most cases. The DataGroup for that row (and its itemRenderers) are clipped. Furthermore, When scrolling the grid, every row scrolled onscreen is the default 1 text line height, irregardless of data. In any case, resizing the AdvancedDataGrid (not resizing its columns, but the grid itself) forces all rows to snap to the correct desired height. Scrolling again produces incorreclty sized rows.
Additionally, the layout of each entity in the row is determined by several external factors - most commonly being visible range (along the horizontal). Changing this visible range will trigger all item renderers to resize themselves (through the custom layout class) to their new sizes and remeasuring the new DataGroup layout. This actually triggers a custom hierarchy parser which rebuilds all the ArrayCollections used inside the AdvandedDataGrid data provider, so ArrayCollections are dispatching change events that each row's DataGroup reacts to, so the DataGroup itself is invalidating its size and layout.
These resizes do not trigger the AdvancedDataGrid to remeasure its row heights, and I must rezise the ADG itself again to snap the rows to the correct height.
Anyone have any experience with dynamically sized rows in an AdvancedDataGrid or ItemRenderers which must forcibly make the AdvandedDataGrid re-layout its rows?
Unfortunately, I cannot provide source code as there are a huge number of classes going into this, hierarchial data, rolling up closed nodes into multiple rows, custom hierarchy parsers, a multitude of item renderers - that and its a Government contract.
I have run into a similar issue with a much simpler item renderer, basically a label that will respect a max height, resize itself upto that height as its wordwrapping data will require, and then create scrollbars for itself. Again, the data sizes almost correclty when the grid is created, then changing the column width within the grid does not resize the row height as the item renderer adjusts to its new width. Only in resizing the grid itself do the item renderers resize correctly, create scroll bars, and the grids row heights are correct. The source for that item renderer:
<s:Scroller xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
implements="mx.controls.listClasses.IDropInListItemRenderer,mx.controls.listClasses.IListItemRenderer"
horizontalScrollPolicy="off" width="100%">
<fx:Script>
<![CDATA[
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.events.ResizeEvent;
private var _listData:BaseListData;
private var _data:Object;
private var _listOrData_c:Boolean = false;
public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = value;
_listOrData_c = true;
invalidateProperties();
}
public function get data():Object
{
return _data
}
public function set data(value:Object):void
{
_data = value;
_listOrData_c = true;
invalidateProperties();
}
override protected function commitProperties():void
{
if(_listOrData_c)
{
_listOrData_c = false;
label.text = _listData.label;
}
super.commitProperties();
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Group width="100%">
<s:layout>
<s:BasicLayout clipAndEnableScrolling="true" />
</s:layout>
<s:Label id="label" width="100%"/>
</s:Group>
</s:Scroller>
Throw it into a AdvancedDataGrid and set some data with very large text blocks. Resize columns, then resize the grid itself, hopefully you can reproduce the same results. Make sure you set a max height on the item renderers like:
<mx:AdvancedDataGridColumn id="adgc1" headerText="Name" dataField="label">
<mx:itemRenderer>
<fx:Component>
<newLayouts:ScrollingTextItemRenderer maxHeight="60" />
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
Using Flex 4.1.
Thanks for the help.
Here are screenshots detailing the item renderer as it should function (as I have fixed the measuring to forcibly validate the label at the explicit current width before measuring):
Very wide column, no scroll bars, the labels measured height is shown in the row height
Smaller width column, some renderers have hit max height and are creating scroll bars, the last renderer is still using the measured height of the label
Smaller still column, all max heights are hit and scrollers are present for all labels, scrollers will select the row when used but allow scrolling so all text is viewable.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
今天早上经过更仔细的检查后,数据组渲染器本身的 meausre 方法在第一次测量时无法正确验证其子级的大小。
我需要这些项目中的标签具有有限的宽度,以便它们能够适当地自动换行,因此当我测量 DataGroup 行时,我需要设置其每个子项的宽度,然后测量子项。问题是 validateSize() 没有正确验证元素大小(此时标签尚未更新并生成新的文本行)。所有后续测量通道都已验证每个孩子的宽度,因此再次测量它们是正确的。因此,当调整网格大小时,后续的测量调用起作用了。
我开始强制验证 DataGroup 的测量方法中的每个子项,并且现在返回正确的高度,因此 AdvancedDataGrid 现在正在正确调整其行的大小。
这可能效率相当低,因为现在每个项目在每个生命周期都会验证两次,但网格正在按预期执行。
ScrollingLabelItemRenderer 可能会发生类似的情况,因为标签在第一次测量自身时可能不会验证其宽度,因此设置了网格接受并用作行高的错误测量尺寸。
我的 ScrollingLabelItemRenderer 现在再次正常运行,我必须强制向标签应用宽度并在测量渲染器时验证它,因为在测量时它仍在使用以前的宽度和文本行,然后在后续 updateDisplayList 中应用新宽度。 。
After much closer inspection this morning, the meausre method for the DataGroup renderers themselves was not correclty validating the size of its children upon first measure pass.
I need the labels in those items to have a restricted width so they will wordwrap appropriately, so when I am measuring the DataGroup row I need to set the width of each of its children and then measure the child. The problem was validateSize() was not correctly validating the elements size (the label was not being updated and generating its new text lines at this point). All subsequent measure passes already had a width validated to each child so measuring them again was correct. So when resizing the grid, the subsequent measure calls worked.
I took to forcibly validating each child within the DataGroup's measure method and the correct heights are now being returned and as such the AdvancedDataGrid is acutally sizing its rows correclty now.
This can be rather inefficient as each item is validated twice per lifecycle pass now, but the grid is performing as desired.
Probably something similar going on with the ScrollingLabelItemRenderer as the label probably doesn't get its width validated when it measures itself the first time thus sets the wrong measured size which the grid accepts and uses as row height.
I have the ScrollingLabelItemRenderer functioning correctly now again, I had to forcibly apply a width to the label and validate it when measuring the renderer becuase it was still using its previous width and text lines when measuring before applying a new width in the subsequent updateDisplayList ...
我花了几周的时间试图让 MX
AdvancedDataGrid
正确处理可变行高,但错误并没有真正成功。总会有一些高度不正确的情况。所有这些都是关于调用网格渲染器重新布局,这是一个非常长的操作,使得项目极其缓慢。我建议您迁移到基于
Spark AdvancedDataGrid
code>Spark DataGrid 并且对于复杂的渲染器来说工作速度更快。I've spent a few weeks trying to make MX
AdvancedDataGrid
handle variable row heights correctly bug did not really succeed. There are always some cases when heights are incorrect. All this is about calling grid renderers re-layouting which is a very long operation making the project extremely slow.I suggest you to move to
Spark AdvancedDataGrid
that is based onSpark DataGrid
and works much faster for complex renderers.