收藏本站腾讯微博新浪微博

经典论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

蓝色理想 最新研发动态 网站开通淘帖功能 - 蓝色理想插件 论坛内容导读一页看论坛 - 给官方提建议

论坛活动及任务 地图和邮件任务 请多用悬赏提问 热夏来袭,选一款蓝色理想的个性T恤吧!

手机上论坛,使用APP获得更好体验 急需前端攻城狮,获得内部推荐机会 论坛开通淘帖功能,收藏终于可以分类了!

搜索
查看: 10231|回复: 10

[AS3] 让Flash自带的滚动条支持设置宽度的方法

[复制链接]
发表于 2010-8-12 15:10:57 | 显示全部楼层 |阅读模式
相信从事Flash/Flex,乃至其他应用程序开发的朋友或多或少都有这样的体会:一个项目的整体进度要达到95%,并不需要耗费太多精力,而剩下的5%却占用了你开发总时间的95%才得以完成。而这5%的工作,不是弥补程序里的小缺陷,就是修复一些令人苦笑不得的Bug。

不可否认,程序中的Bug相当一部分系因开发人员思维不够慎密而造成的。然而,现在能使用机器语言进行编程的人可谓凤毛麟角,我们需要依赖于系统平台,编译器,甚至解释器才可以进行编程并得到成品。所有的依赖因素,都不可避免地存在漏洞,随时都有可能影响到程序员的开发进程。

AS开发也不例外,尽管FlashPlayer具有跨平台的特性,但它本身的bug,就已经让不少Aser忍无可忍,如果要结合JS,则还需要考虑浏览器的兼容问题。一个项目,时间往往要浪费在处理这些问题上,幸亏大多数客户不懂技术,看到整体进度基本过关,即使项目一拖再拖,客户也是愿意等待的。

目前我的时间相对宽松一些,故计划把以前遇到过的一些问题进行整理,然后在此处发帖,并提出解决方案以抛砖引玉。

第一帖打算先向大家汇报一个密码文本框的Bug。按常规来讲,密码字段不可以通过右键菜单及快捷键等基本方法进行复制,但Flash的密码文本却没有屏蔽掉Ctrl+C,在非密码字段粘贴一下,密码字符串便一览无余。这个Adode公司,竟连密码框最基本的安全意识都缺乏,枉他还做了几年的安全沙箱。曾计划向Adobe提交此Bug,无奈国内访问速度过慢,再者密码框查看工具也已经比较成熟,我就没再考虑提交了。

按我原来的安排,今天先把自己为修复此Bug而扩展的PasswordTextField类在本论坛公开,不过我今天很意外地发现,FlashPlayer10.1已经对此进行了修正,我的PasswordTextField也可以功成身退了。

所以,今天向各位汇报的,是另一个问题。为了让Adobe用户开发更为方便,Adobe的AS程序员为Flash及Flex都开发了一套UI组件,基本上能满足中小型Web应用程序的需求。但是,这当中包含的一些小Bug非常让AS程序员头痛,有的人为了修正它,调用组件后,写一些有针对性的函数去处理,有的人则干脆放弃自带组件,进行自主开发,或者用其他组件库如Aswing、apple等,有的则退而求其次,说服其他部门的同事,在非技术层面上采用其他方案代替。

由于Adobe的组件开源,我们还可以通过直接修改代码,重新编译。但我在使用FlashCS5的过程中,修改组件代码,重新编译,组件并没有发生任何变化,在ComponentShim里编译swc,也得不到我修改后的结果,将这个类库的目录添加到项目的源路径也一样不奏效,最后尝试反编译来修改,结果报出一堆错误。

无奈之下,我只能选择扩展原有类,通过重写某些方法来修复这些带Bug的组件。

Flash/Flex自带的UIScrollBar不支持纵滚动条宽度和横滚动条高度的设置,把设置尺寸和修改样式的函数通通试了一遍,没有一个可以达到目的。即使用Embed标签嵌入尺寸不等于默认值的图片,发布后,组件也会自动将图片调整为默认尺寸。

查看ScrollBar(UIScrollBar的父类)类的源代码,发现有以下几处代码写得很死:


  1. public static const WIDTH:Number = 15;
复制代码

滚动条宽度写死在了一个常数上,因此无法在运行时进行设置。下面我们再来观察绘制组件的相关代码:


  1. /**
  2.          * @private (protected)
  3.          *
  4.          * @langversion 3.0
  5.          * @playerversion Flash 9.0.28.0
  6.                  */               
  7.                 override protected function configUI():void {
  8.                         super.configUI();
  9.                        
  10.                         track = new BaseButton();
  11.                         track.move(0,14);
  12.                         track.useHandCursor = false;
  13.                         track.autoRepeat = true;
  14.                         track.focusEnabled = false;
  15.                         addChild(track);

  16.                         thumb = new LabelButton();
  17.                         thumb.label = "";
  18.                         thumb.setSize(WIDTH,15);
  19.                         thumb.move(0,15);
  20.                         thumb.focusEnabled = false;
  21.                         addChild(thumb);
  22.                        
  23.                         downArrow = new BaseButton();
  24.                         downArrow.setSize(WIDTH,14);
  25.                         downArrow.autoRepeat = true;
  26.                         downArrow.focusEnabled = false;
  27.                         addChild(downArrow);
  28.                        
  29.                         upArrow = new BaseButton();
  30.                         upArrow.setSize(WIDTH,14);
  31.                         upArrow.move(0,0);
  32.                         upArrow.autoRepeat = true;
  33.                         upArrow.focusEnabled = false;
  34.                         addChild(upArrow);
  35.                        
  36.                         upArrow.addEventListener(ComponentEvent.BUTTON_DOWN,scrollPressHandler,false,0,true);
  37.                         downArrow.addEventListener(ComponentEvent.BUTTON_DOWN,scrollPressHandler,false,0,true);
  38.                         track.addEventListener(ComponentEvent.BUTTON_DOWN,scrollPressHandler,false,0,true);
  39.                         thumb.addEventListener(MouseEvent.MOUSE_DOWN,thumbPressHandler,false,0,true);
  40.                        
  41.                         enabled = false;
  42.                 }
复制代码

至此真相水落石出,轨道,按钮的尺寸全部写死在一个常数上。

与此同时,draw方法也没有调用过setSize函数所设定的width属性,整个重绘跟width属性无关(对纵滚动条而言)


  1. /**
  2.          * @private (protected)
  3.          *
  4.          * @langversion 3.0
  5.          * @playerversion Flash 9.0.28.0
  6.                  */
  7.                 override protected function draw():void {       
  8.                         if (isInvalid(InvalidationType.SIZE)) {
  9.                                 var h:Number = super.height;
  10.                                 downArrow.move(0,  Math.max(upArrow.height, h-downArrow.height));
  11.                                 track.setSize(WIDTH, Math.max(0, h-(downArrow.height + upArrow.height)));
  12.                                 updateThumb();
  13.                         }
  14.                         if (isInvalid(InvalidationType.STYLES,InvalidationType.STATE)) {
  15.                                 setStyles();
  16.                         }
  17.                         // Call drawNow on nested components to get around problems with nested render events:
  18.                         downArrow.drawNow();
  19.                         upArrow.drawNow();
  20.                         track.drawNow();
  21.                         thumb.drawNow();
  22.                         validate();
  23.                 }
复制代码


所以,要让组件支持滚动条宽度设置,必须重写这两个函数。
在我的源码里,几乎没有调用过super,因为常数写得过于分散,直接调用超类函数再添加自己的修正代码也特别麻烦。

由于BaseScrollPane(及其子类),TextArea等类均应用了滚动条,所以若要让那些组件的滚动条支持宽度设置,同样需要重写相应的重绘方法,同时把ScrollBar或者UIScrollBar组件换成你扩展过的。

下面是我扩展过的ScrollBar代码:

  1. package com.hbro.controls {
  2.        
  3.         import fl.controls.ScrollBar;
  4.         import fl.core.InvalidationType;
  5.        
  6.         public class ResizableScrollBar extends ScrollBar{
  7.                
  8.                 public function ResizableScrollBar() {
  9.                         // constructor code
  10.                         super();
  11.                 }
  12.                
  13.                 override protected function draw():void {                               
  14.                
  15.                         //代码从ScrollBar类拷贝过来,将常数换成与width有关的变量,以使得在调用setSize或者设置width的时候,可以改变宽度
  16.                         if (isInvalid(InvalidationType.SIZE)) {
  17.                                 var h:Number = super.height;
  18.                                
  19.                                 //滚动条按钮按宽度进行设置,源程序写死了一个常数,导致该大小无法改变,有兴趣的朋友可以在此基础上进行修改,让按钮区域可以不呈现为正方形。
  20.                                 downArrow.setSize(_width,_width);
  21.                                 upArrow.setSize(_width,_width);
  22.                                 downArrow.move(0,  Math.max(upArrow.height, h-downArrow.height));
  23.                                
  24.                                 //轨道宽度也要进行设置
  25.                                 track.move(0,_width);
  26.                                 track.setSize(_width, Math.max(0, h-(downArrow.height + upArrow.height)));
  27.                                 thumb.setSize(_width,thumb.height);
  28.                                 updateThumb();
  29.                         }
  30.                         if (isInvalid(InvalidationType.STYLES,InvalidationType.STATE)) {
  31.                                 setStyles();
  32.                         }
  33.                         // Call drawNow on nested components to get around problems with nested render events:
  34.                         downArrow.drawNow();
  35.                         upArrow.drawNow();
  36.                         track.drawNow();
  37.                         thumb.drawNow();
  38.                         validate();
  39.                 }

  40.         }
  41.        
  42. }
复制代码


本人发布的附件包还包含了UIScrollBar,List及TextArea类的扩展,读者如有兴趣或需要,可以用类似的方法重写其他几个跟滚动条有关的组件(Flash或Flex组件均可)中相应的函数。

调用这些类时,必须保证库里包含了父类的组件,因为调用父类时同样需要库里存在组件的情况下才可以正常编译。
支持滚动条宽度设置的List组件.jpg

可缩放滚动条.rar

555.97 KB, 下载次数: 630

发表于 2010-8-14 19:15:44 | 显示全部楼层
哈哈,HBro赚到了。我经常使用的组件就一个:FlvPlayback,其他自带的组件没用过。
回复 支持 1 反对 0

使用道具 举报

发表于 2010-8-14 19:11:19 | 显示全部楼层
晕,加分加错楼层了……

到目前为止我所有的项目都只有两种选择:用自己的组件库,直接使用FLEX
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2010-8-12 18:08:45 | 显示全部楼层

评分

参与人数 1威望 +3 收起 理由
jimohuoshan + 3 你可真能折腾啊!

查看全部评分

回复 支持 1 反对 0

使用道具 举报

发表于 2010-8-12 15:34:39 | 显示全部楼层
  向大虾学习
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2010-8-12 15:32:47 | 显示全部楼层

回复 2# flash023 的帖子

以前我也不用的,自己写。
但当我两年前发现自己写的那套组件在FlashPlayer10下有太多的Bug以后,深受打击,就开始尝试去使用默认组件了。
回复 支持 1 反对 0

使用道具 举报

发表于 2010-8-12 15:21:25 | 显示全部楼层
  支持,大虾厉害
我就从来不敢用组件
回复 支持 1 反对 0

使用道具 举报

发表于 2010-8-14 22:20:46 | 显示全部楼层
学习了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-8-17 13:43:43 | 显示全部楼层
火山,Flex和Flash不分家,Flash组件有的缺陷和Bug,到Flex里也一样有。
自己写组件库是个明智的选择,但是我比以前懒了很多。
回复 支持 反对

使用道具 举报

发表于 2011-7-19 11:25:00 | 显示全部楼层
比较纳闷为啥fl跟fx都限制了这个属性,雅虎的astra也没做相应修改. 郁闷,这东东我正也需要,谢谢老牛咯  +1000000
回复 支持 反对

使用道具 举报

发表于 2011-12-20 12:01:23 | 显示全部楼层
自己扩展组件是个不错的选择。
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|blueidea.com ( ICP05002321 )  

GMT+8, 2019-12-9 08:11 , Processed in 0.140267 second(s), 16 queries , Gzip On, Memcache On.

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表