首页 > 设计 > WEB开发 > 正文

7.13.改变List 中渲染器的大小

2023-08-02 23:09:26
字体:
来源:转载
供稿:网友
7.13.1. 问题
你需要创建一个被选中时是可以改变大小的renderer。
7.13.2. 解决办法
创建一个drop-in itemRenderer,实现IDropInListItemRenderer 接口,并且通过listData 监听List 的Scroll 和Change 事件,当这两个事件中的任意一个事件发生时,比较itemRenderer 中的data 与List 中selectedItem 中的data,如果相等,就设置currentState 为selected,否则设置为base。
7.13.3. 讨论
有一点很重要:itemRenderer 是被list 重用的。当一个renderer 被选中,在你试图设置它的state 的时候,要在每个renderer 里判断自己是不是那个被选中的renderer,这个itemRenderer 的data 必须和List 或DataGridColumn 的选中项的data 相配置,而不是靠seletedIndex 确定。

因为你可以通过listData 访问List 和DataGridColumn,所以你为可以通过listData对listData 或
+展开
-ActionScript
DataGridColumn 增加事件的监听,并且在事件发生时,可以检查renderer的data 和state:
private function resizeEventHandler(event:Event):void {
if ((_listData.owner as List).selectedIndex == ArrayCollection(
(_listData.owner as List).dataProvider).getItemIndex(this.data) &¤tState ! "selected") {
trace("functions"+_listData.rowIndex+" "+(_listData.owner asList).selectedIndex);
currentState = "selected";
else if((_listData.owner as List).selectedIndex !=ArrayCollection((_listData.owner as List).dataProvider).getItemIndex(this.data) &¤tState == "selected") {
currentState = "base";
}
}

下面的代码中假定dataProvider 的数据类型为ArrayCollection,当然我们也可以把代码写的更公用一些,但在一般情况下,ArrayCollection 就足够了。
+展开
-XML
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxmlheight="30"
currentState="baseimplements="mx.controls.listClasses.IDropInListItemRenderer"
verticalScrollPolicy="off">

<mx:Script>
<![CDATA[
import mx.controls.List;
import mx.events.ListEvent;
import mx.controls.listClasses.BaseListData;
import mx.collections.ArrayCollection;
private function resizeFocusInHandler(event:Event):void {
if ((_listData.owner as List).selectedIndex == ArrayCollection((_listData.owner as List).dataProvider).getItemIndex(this.data)&& currentState != "selected") {
trace("functions"+_listData.rowIndex+" "+(_listData.owner as List).selectedIndex);
currentState = "selected";
else if ((_listData.owner as List).selectedIndex != ArrayCollection((_listData.owner as
List).dataProvider).getItemIndex(this.data)&& currentState == "selected") {
currentState = "base";
}
}
override public function set data(value:Object):void { txt.text = value as String; }
override public function get data():Object { return txt.text; }
// Internal variable for the property value.
private var _listData:BaseListData;
// Make the listData property bindable.
[Bindable("dataChange")]
// Define the getter method.
public function get listData():BaseListData { return _listData; }
// set the event listeners for the Change and Scroll events
// that the List or Column will dispatch
public function set listData(value:BaseListData):void {
_listData = value;
_listData.owner.addEventListener(ListEvent.CHANGE, resizeFocusInHandler);
_listData.owner.addEventListener(Event.SCROLL, resizeFocusInHandler);
}

]]>
</mx:Script>
<mx:transitions>
<mx:Transition fromState="*toState="selected">
<mx:Resize heightTo="60target="{this
}
"/>

</mx:Transition>
<mx:Transition fromState="selectedtoState="*">
<mx:Resize heightTo="30target="{this }"/>
</mx:Transition>
</mx:transitions>
<mx:states>
<mx:State name="base"/>
<mx:State name="selected">
<mx:AddChild>
<mx:HBox>
<mx:Label text="some text"/>
<mx:Label text="{'some text = ' +txt.text}"/>
</mx:HBox>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:Text id="txt"/>
</mx:VBox>

(译者注)
看了原文中的例子,没有搞明白作者要监听SCROLL 事件的真正意义,我猜作者的用意可能是:当用户拖动滚动条时,如果被选中的item 移出了显示区,当继续滚动滚动条,item 又显示时,item 下方的那两个label 依然显示(不必再运行effect 了)。但实际是那两个label没有再次再显示。我觉得作者可能忽略了两个问题,1、当某个选中item 不在显示区时,这个item 的renderer 可能己经被其它item 使用了。当拖动滚动条,使这个item 又显示时,系统会把移出显示区的item 的renderer 拿过来重用,又会调renderer 的set listData,又会重新对SCROLL 事件加监听,但这时候加监听己经晚了,因为让这个renderer 显示的拖动事件己经发生完了。所以这个刚刚显示出来的被选中的item 的renderer 不会被设置state,所以下边的两个Label 不会再次显示。可是,如果这时候我再拖动滚动条,使这个item 移动显示区,这时这个renderer 的监听方法生效了,它会满足第一个if 条件,运行第一个effect。这里大家可能会有些不明白,大家可能会认为:虽然if 中第一个条件能满足,但第二个条件中currentState 一定是等于selected,因为它就是在被选中状态,这样就使整个if 条件不满足。但事实不是这样的,我们回过头来再看,当这个renderer 移出显示区时,这个renderer 就被其它item 重用了,但是重用时并没有改变renderer 的currentState,即selected。这时用户又拖动滚动条,这个重用的renderer 会监听到SCROLL事件,并调用resizeFocusInHandler 这时自然就满足第二个if 条件,这个renderer 的currentState 又被设为了base。因为当这个被选中的item 的renderer 在第二次移出显示区时,又一次进入selected state 并再一次运行effect ,只是因为item 移出显示区了,我们在页面中看不到较果。

2、结合第一个问题,如果被选中的item 的renderer 没有被其它item 重用,当用户再次拖动以至这个item 再次被显示时, 它可以及时的监听到SCROLL 事件, 从而调用resizeFocusInHandler 方法,但程序不会满足任何if 条件。label 己经不再了,没有state的改变,它们是不会再出来的。

总之我认为作者监听SCROLL 事件没能达到他的预期效果,可能根本原因是那两个label莫名其妙的没了。

到这里本章己经结束了,在本章中指出了原文中的一些小错误,由于我人个的水平有限,有此错误可能是我的错误判断,望大家见谅。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表