免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1513 | 回复: 0
打印 上一主题 下一主题

FLEX自定义组件2_第一次实践 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-22 08:54 |只看该作者 |倒序浏览
转载:http://www.ibm.com/developerworks/cn/web/1011_simq_flexlifecycle/index.html?ca=drs-
首先学习《FLEX组件生命周期1_原理》

1.关于 createChildren()方法
       代码1-1显示了组件 ImageViewer 的 createChildren() 方法。
代码1-1. ImageViewer 的 createChildren() 方法
  1. override protected function createChildren():void
  2.         {
  3.             trace('createChildren');
  4.             super.createChildren();
  5.             
  6.             //创建边框CSS
  7.             if(!this.border){
  8.                 createBorder();
  9.             }
  10.             
  11.             //创建控制按钮容器
  12.             if (!controlBar)
  13.                 controlBar = new UIComponent();
  14.             
  15.             //创建放大按钮
  16.             if (!zoomInButton){
  17.                 zoomInButton = new Button();
  18.                 zoomInButton.label = "+";
  19.                 zoomInButton.addEventListener(MouseEvent.CLICK, zoomInButtonClickHandler);
  20.                 controlBar.addChild(zoomInButton);
  21.             }
  22.             
  23.             //创建缩小按钮
  24.             if (!zoomOutButton){
  25.                 zoomOutButton = new Button();
  26.                 zoomOutButton.label = "-";
  27.                 zoomOutButton.addEventListener(MouseEvent.CLICK, zoomOutButtonClickHandler);
  28.                 controlBar.addChild(zoomOutButton);
  29.             }
  30.             
  31.             // 将控制按钮容器添加到显示节点
  32.             addChild(controlBar);
  33.         }
       在该方法的末尾才把controlBar 添加到 Display List 上,正如之前提到的那样,我们只在需要的时候装配他。同时,此时也是为子节点添加监听器的好地方。

2.关于 commitProperties()方法
       CommitProperties()是验证方法 invalidateProperties()所对应的提交方法,也是初始化阶段会被调用的第一个提交方法。他的目的是使得任何通过 set 方法提交的数值更改生效。所以您可以看到在 set scale()方法里,按照 invalidation-validation 模式,我们调用了 invalidateProperties()方法从而将值的生效延迟到了 commitProperties()里,并且为了做到 “避免对一个属性连续设置多个值,从而避免了不必要的资源浪费”,我们使用了标志位 scaleChanged。

代码2-1 set scale()函数
  1. public function set scale(value : Number):void{
  2.           if (_scale != value)
  3.           {
  4.                 _scale = value;
  5.                 
  6.                 //避免对一个属性连续设置多个值,从而避免了不必要的资源浪费
  7.                 scaleChanged = true;
  8.                 
  9.                 //由于调用本方法时,可能对象未创建
  10.                 //通过调用invalidateProperties(),将值的生效延迟到了commitProperties()里
  11.                 invalidateProperties();
  12.                 dispatchEvent(new Event("scaleChanged"));
  13.           }
  14. }
代码2-2  commitProperties()函数
  1. override protected function commitProperties():void{
  2.             trace('commitProperties');
  3.             super.commitProperties();         
  4.             
  5.             //如果image控件不存在,则新建并添加
  6.             if (sourceChanged){
  7.                 if(!this.image){
  8.                     image = new Image();                 
  9.                     this.addChild(image);
  10.                     image.source = this._source;                 
  11.                 }else{
  12.                     image.source = this._source;
  13.                 }
  14.                 sourceChanged = false;
  15.             }
  16.             
  17.             //如果scale属性改变了,则修改imageWidth
  18.             if(scaleChanged){
  19.                 this.imageWidth = this.imageWidth * this.scale;
  20.                 this.imageHeight = this.imageHeight * this.scale;
  21.                 scaleChanged = false;
  22.             }
  23. }
       为什么在 commitProperties()会有添加子节点的操作呢?
       对于有些子节点,他的诞生可能是和某些属性值相关联的,也就是我们在之前提到的动态创建或者数据驱动的子节点。这些子节点,由于他们并不是随着组件的产生而产生,而是要受属性值的变化而产生或者变化,甚至在某些情况下,根本就不需要存在。所以我们应该在值的提交阶段,也就是 commitProperties()方法调用的时候,当新值真正生效的时候再去创建它。

3.关于 measure() 方法
       measure()方法是组件自动计算尺寸大小的地方,在例子 ImageViewer 的 measure()方法里(如代码3-1 所示).如果已经指定了尺寸大小,即 width 和 height 值,measure()方法不会被调用。所以一旦您的组件在组装阶段被设置了 with 和 height 属性值,那么请不要期望在 measure 里会执行您的业务逻辑。
代码3-1 measure()函数
  1. override protected function measure():void{
  2.             trace('measure ');
  3.             super.measure();
  4.             if(!image){
  5.                 //如果image控件不存在,则本组件的宽度为controlBar的宽度
  6.                 measuredWidth = controlBar.getExplicitOrMeasuredWidth();
  7.                 measuredHeight = controlBar.getExplicitOrMeasuredHeight();
  8.             }else{
  9.                 //如果image控件存在,则本组件的宽度为controlBar的宽度
  10.                 measuredWidth = image.width + Math.max(image.width, controlBar.getExplicitOrMeasuredWidth()) ;
  11.                 measuredHeight = image.height + controlBar.getExplicitOrMeasuredHeight();
  12.             }
  13.             measuredMinWidth = measuredWidth;
  14.             measuredMinHeight = measuredHeight;
  15. }
 
4.关于 updateDisplayList ()方法
       updateDisplayList()方法用于对组件内容进行布局以及渲染,一切屏幕上可见的内容都需要在这里被处理,所以 updateDisplayList()可以说是最繁忙的一个提交方法,他所包含的实现可以非常多。代码4-1中,我们省略了部分代码。只留下了需要讲解的部分。

代码4-1 updateDisplayList()函数部分代码
  1. override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number): void {
  2.             super.updateDisplayList(unscaledWidth, unscaledHeight);
  3.             // 省略部分代码
  4.             zoomInButton.setActualSize(50, 20);
  5.             zoomOutButton.setActualSize(50, 20);
  6.             var tmpx : Number = 20;
  7.             controlBar.setActualSize(tmpx, 20);
  8.             controlBar.move(0, unscaledHeight-25);
  9.             zoomInButton.move(tmpx, 0);
  10.             tmpx +=60;
  11.             zoomOutButton.move(tmpx, 0);
  12.             if (imageHeightChanged ||imageWidthChanged){
  13.                 image.width = this.imageWidth;//w;
  14.                 image.height = this.imageHeight;//h - 20;
  15.                 var tempX : Number = x+ (w-imageWidth) * 0.5;
  16.                 var tempY : Number = y + (h-imageHeight) * 0.5;
  17.                 image.x = tempX;
  18.                 image.y = tempY;
  19.                 imageHeightChanged = false ;
  20.                 imageWidthChanged = false ;
  21.                 var g:Graphics = graphics;
  22.                 g.clear();
  23.                 g.beginFill(0x6F7777);
  24.                 g.drawRect(tempX-1, tempY-1, imageWidth+2, imageHeight+2);
  25.                 g.endFill();
  26.             }
  27. }
       在 measure()方法里我们可以获取 Flex 自动计算的尺寸(如果被调用的话),这些数据需要在 updateDisplayList() 方法里被应用处理,所以我们会大量使用 setActualSize()方法,特别是子元素比较多的时候。
       updateDisplayList()的最重要的职责之一就相对应的 invalidateDisplayList()方法的更新请求进行响应。比如说对set imageWidth()方法进行了相应。并且就像在 commitProperties()部分里介绍的那样,这里同样使用了“标志位”方法来进行“局部跟新”。

       局部更新是普遍应用于提交方法里的一种技巧,因为我们知道这三个提交方法是公用的,任何更新的提交都会在这几个方法里被处理。而每次更新都可能只是局部的更改,所以是当地使用标志位方法进行局部更新可以有效地优化代码的执行。

       渲染屏幕的职责也决定了 updateDisplayList()方法是调用 Flash Player 绘图 API 的好地方。所以我们在代码4-1 中特意使用了 drawRect()方法为图片家了一个边框。


参考文献
1.http://www.ibm.com/developerworks/cn/web/1011_simq_flexlifecycle/index.html?ca=drs-

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP