问题描述
我有一个AdvancedDataGrid,其可变行高设置为true。
我已经基于DataGroup spark组件编写了一个cutsom项目渲染器。网格中的每一行都有多个实体要显示,实体的x位置和宽度基于实体本身的数据。
我写了一个自定义布局用于基于每个实体的数据来度量和定位每个实体的DataGroup。每行中的每个实体都可以截断或不截断其标签。当标签没有被截断时,我将计算对象的实际宽度并手动验证其大小(以强制标签具有正确的宽度并布置其所有文本行并重新测量其自身),以使用DataGroup的Layout的measure方法来准确地测量数据组本身。
布局,尺寸,尺寸,显示等都可以正常工作。实体报告了不截断标签时所需的正确高度,数据组报告了绘制行中所有实体值所需的正确大小(全部来自需要的度量方法,如UIComponent生命周期内所述)。
在AdvancedDataGrid本身内部时,行的大小不正确。大多数行不需要多行,并且显示得很好。需要多行的代码行高较大,但在大多数情况下不足以容纳整个文本。该行的DataGroup(及其itemRenderers)被裁剪。此外,在滚动网格时,无论数据如何,屏幕上滚动的每一行都是默认的1文本行高度。无论如何,调整AdvancedDataGrid的大小(而不是调整其列的大小,而是调整网格本身的大小)会强制所有行对齐到正确的所需高度。再次滚动会产生大小不正确的行。
此外,行中每个实体的布局还取决于几个外部因素-最常见的是可见范围(沿水平方向)。更改此可见范围将触发所有项目渲染器自行调整大小(通过自定义布局类)为新大小,并重新确定新的DataGroup布局。实际上,这会触发一个自定义层次结构解析器,该解析器将重建AdvandedDataGrid数据提供程序内部使用的所有ArrayCollection,因此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;
私人变量_listData:BaseListData;
private var _data:Object;
private var _listOrData_c:Boolean = false;
公共函数get listData():BaseListData
{
return _listData;
}
公共功能集listData(value:BaseListData):void
{
_listData = value;
_listOrData_c = true;
invalidateProperties();
}
公共函数get data():Object
{
return _data
}
公共函数set data(value:Object) :void
{
_data =值;
_listOrData_c = true;
invalidateProperties();
}
覆盖受保护的函数commitProperties():void
{
if(_listOrData_c)
{
_listOrData_c = false;
label.text = _listData.label;
}
super.commitProperties();
}
]]>
< / fx:Script>
< fx:声明>
<!-在此处放置非可视元素(例如服务,价值对象)->
< / fx:Declarations>
< s:组宽度= 100%>
< s:layout>
< s:BasicLayout clipAndEnableScrolling = true />
< / s:layout>
< s:标签id = label width = 100% />
< / s:Group>
< / s:Scroller>
将其放入AdvancedDataGrid中,并使用非常大的文本块设置一些数据。调整列的大小,然后调整网格本身的大小,希望您可以重现相同的结果。确保在项目渲染器上设置最大高度,例如:
< mx:AdvancedDataGridColumn id = adgc1 headerText =名称 dataField = label>
< mx:itemRenderer>
< fx:Component>
< newLayouts:ScrollingTextItemRenderer maxHeight = 60 />
< / fx:Component>
< / mx:itemRenderer>
< / mx:AdvancedDataGridColumn>
使用Flex 4.1。
感谢
以下是屏幕截图,详细说明了项目渲染器应发挥的功能(因为我已固定测量尺寸,以便在测量之前以明确的当前宽度强制验证标签):
非常宽的列,没有滚动条,标签测量的高度显示在行高
较小的宽度列,一些渲染器已达到最大高度并正在创建滚动条,最后一个渲染器仍在使用标签
的测量高度
较小的静止列,所有最大高度都被击中,并且所有标签都带有滚动条,滚动条在使用时会选择该行,但允许滚动,因此所有文本都可见。
在今天早上进行了更仔细的检查之后,DataGroup渲染器本身的meausre方法在第一次通过测量时并不正确地验证了其子代的大小。
我需要这些项目中的标签具有受限的宽度,以便它们能够自动换行,因此在测量DataGroup行时,我需要设置每个标签的宽度它的孩子,然后测量孩子。问题是validateSize()不能正确验证元素的大小(此时标签没有更新,也没有生成新的文本行)。所有后续测量遍都已经对每个孩子进行了验证,因此再次测量它们是正确的。因此,在调整网格大小时,随后的度量调用起作用。
我采取了强制性措施,验证了DataGroup的measure方法中的每个孩子,并且现在返回了正确的高度,因此
这可能是相当低效的,因为现在每个生命周期都对每个项目进行了两次验证,但是网格的性能符合预期。 / p>
可能与ScrollingLabelItemRenderer类似,因为标签在第一次测量自身时可能未得到宽度验证,因此设置了错误的网格尺寸并用作行高。
我现在再次使ScrollingLabelItemRenderer正常工作,我不得不强行将宽度应用于标签,并在测量渲染器时对其进行验证,因为它是在测量之前仍使用其先前的宽度和文本行,然后在后续的updateDi中应用新的宽度splayList ...
覆盖受保护的函数measure():void
{
label.width = getExplicitOrMeasuredWidth ()-verticalScrollBar.getExplicitOrMeasuredWidth();
label.validateNow();
super.measure();
}
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.
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 ...
override protected function measure():void
{
label.width = getExplicitOrMeasuredWidth() - verticalScrollBar.getExplicitOrMeasuredWidth();
label.validateNow();
super.measure();
}
这篇关于ItemRenderer高度(和高度变化)未反映在AdvancedDataGrid行中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!