- UID
- 145379
- 在线时间
- 小时
- 积分
- 33342
- 帖子
- 离线
- 18646 天
- 注册时间
- 2004-12-1
|
Flash/Flex组件的框架尽管已经开源,但修复Bug的任务依然举步维艰。近期的一个聊天室项目,要求网页中的Flash可以在全屏和正常模式下自由切换。作者使用了TextInput组件作为聊天内容输入的文本框,切换全屏的时候,发现了一个Bug,如果当前舞台焦点为TextInput,在全屏时,让TextInput组件的尺寸适应宽度变化,将会发现,焦点框并未随之缩放。作者在写此教程前,也对TextArea做了类似测试,却未发现问题。可见,Adobe的AS开发人员并未忽略此问题,可能仅为粗心大意所致。
另一方面,作者还分别测试了Flex SDK3.2,3.5,4.0的这两个组件,均不存在这个Bug。
由于作者已经选择了Flash组件,所以不愿为此改用Flex的框架,幸运的是,修复这一个Bug,所做的事情还是比较简单的。但更痛苦的事情还在后面,全屏后禁用键盘才是项目的关键问题之一,光为了这一个限制,作者就耗了3天多的时间才得以勉强解决。下一篇教程我会将全屏禁用键盘的几种解决方案贴上。
首先,作者先贴上Flash TextInput组件焦点框Bug的测试代码(测试要求fla的库里已经加入TextInput组件):
- package com.hbro.documents {
-
- import fl.controls.TextInput;
-
- import flash.display.MovieClip;
- import flash.events.Event;
- import flash.display.StageAlign;
- import flash.display.StageScaleMode;
-
- public class FlashTextInputTest extends MovieClip {
-
- //设置页边距
- private var _margin:Number=10;
-
- //TextInput组件
- private var _myTxt:TextInput;
-
-
- public function FlashTextInputTest() {
- // constructor code
- init();
- }
-
- private function init():void
- {
- //将文本框添加到舞台上
- _myTxt=new TextInput();
- addChild(_myTxt);
-
- if(stage)
- {
- updateWhenAddedToStage();
- }else{
- addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
- }
- }
-
- private function addedToStageHandler(event:Event):void
- {
- removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
- updateWhenAddedToStage();
- }
-
- private function updateWhenAddedToStage():void
- {
- stage.align=StageAlign.TOP_LEFT;
- stage.scaleMode=StageScaleMode.NO_SCALE;
- stage.addEventListener(Event.RESIZE,resizeHandler);
- updateLayout();
- }
-
- private function resizeHandler(event:Event):void
- {
- //舞台缩放时,重新布局组件
- updateLayout();
- }
-
- private function updateLayout():void
- {
- //根据页边距及舞台尺寸对Txt组件进行移动和缩放
- _myTxt.move(_margin*stage.stageWidth/20,_margin);
- _myTxt.width=stage.stageWidth-_margin*2;
- }
-
- }
-
- }
复制代码
进行测试,拖动Flash窗口,就会发现上图的Bug,无论在Flash IDE,Standalone Player还是浏览器,均出现这一问题,而且,即使用setSize方法设置width,结果也没有变化。
Flex3.2,3.5,4.0的TextInput均未在上述三种环境下的任一种内出现问题,在浏览器中,缩放浏览器窗口时,焦点框会自动消失(显然也不算Bug),所以,对于Flex,作者还附加了如下的测试代码:
- myTxt.addEventListener(Event.CHANGE,changeHandler);
-
- private function changeHandler(event:Event):void
- {
- myTxt.width=200;
- }
复制代码
在输入文字后,文本框尺寸更改了,而且焦点框也自动适应了文本框大小。
所以,测试的结论:只有Flash的TextInput组件有这Bug,而且不同的测试环境下都存在。
修复此Bug比滚动条要容易很多,因为UIComponent提供了drawFocus方法,所以只需在调整大小以后调用重绘组件焦点框的函数即可。
drawFocus有一个Boolean参数,指示是否进行焦点框的绘制。所以,在调用该方法时,还需要通过FocusManager得知文本框是否为当前的焦点。
在设置大小后追加代码
- _myTxt.drawFocus(_focusManager.getFocus()==_myTxt);
复制代码
具体修复代码如下:
- package com.hbro.documents {
-
- import fl.controls.TextInput;
- [color=red]import fl.managers.FocusManager;[/color]
-
- import flash.display.MovieClip;
- import flash.events.Event;
- import flash.display.StageAlign;
- import flash.display.StageScaleMode;
-
- public class FlashTextInputTest extends MovieClip {
-
- //设置页边距
- private var _margin:Number=10;
-
- //TextInput组件
- private var _myTxt:TextInput;
-
-
- public function FlashTextInputTest() {
- // constructor code
- init();
- }
-
- private function init():void
- {
-
- [color]//初始化焦点管理器
- _focusManager=new FocusManager(this);[/color]
-
- //将文本框添加到舞台上
- _myTxt=new TextInput();
- addChild(_myTxt);
-
- if(stage)
- {
- updateWhenAddedToStage();
- }else{
- addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
- }
- }
-
- private function addedToStageHandler(event:Event):void
- {
- removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
- updateWhenAddedToStage();
- }
-
- private function updateWhenAddedToStage():void
- {
- stage.align=StageAlign.TOP_LEFT;
- stage.scaleMode=StageScaleMode.NO_SCALE;
- stage.addEventListener(Event.RESIZE,resizeHandler);
- updateLayout();
- }
-
- private function resizeHandler(event:Event):void
- {
- //舞台缩放时,重新布局组件
- updateLayout();
- }
-
- private function updateLayout():void
- {
- //根据页边距及舞台尺寸对Txt组件进行移动和缩放
- _myTxt.move(_margin*stage.stageWidth/20,_margin);
- _myTxt.width=stage.stageWidth-_margin*2;
-
- [color=red]//重绘焦点框
- _myTxt.drawFocus(_focusManager.getFocus()==_myTxt);[/color]
- }
-
- }
-
- }
复制代码
很多时候我们不希望每次都要通过组件外部主动调用drawFocus,所以,可以直接监听Resize事件,并将该部分的实现代码进行封装。
- package com.hbro.controls {
-
- import fl.controls.TextInput;
- import fl.managers.FocusManager;
- import flash.events.Event;
- public class BugFixedTextInput extends TextInput {
- //焦点管理器
- private var _focusManager:FocusManager;
-
- public function BugFixedTextInput() {
- // constructor code
- super();
- init();
- }
-
- protected function init():void
- {
- addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
- //监听组件缩放事件
- addEventListener(Event.RESIZE,resizeHandler);
- }
-
- private function addedToStageHandler(event:Event):void
- {
- removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
- addEventListener(Event.REMOVED_FROM_STAGE,removedFromStageHandler);
- //添加到舞台时初始化焦点管理器
- _focusManager=new FocusManager(this.stage);
- }
-
- private function removedFromStageHandler(event:Event):void
- {
- removeEventListener(Event.REMOVED_FROM_STAGE,removedFromStageHandler);
- //从舞台移除后,撤掉焦点管理器
- _focusManager=null;
- }
-
- private function resizeHandler(event:Event):void
- {
- //组件缩放的时候,自动绘制焦点框
- if(_focusManager!=null)
- {
- drawFocus(_focusManager.getFocus()==this);
- }
- }
-
- }
- }
复制代码
封装以后,仅需设置width或者setSize就可以修复焦点框不实时更新的Bug。
- package com.hbro.documents {
-
- import com.hbro.controls.BugFixedTextInput;
-
- import flash.display.MovieClip;
- import flash.events.Event;
- import flash.display.StageAlign;
- import flash.display.StageScaleMode;
-
- public class FlashTextInputTest extends MovieClip {
-
- //设置页边距
- private var _margin:Number=10;
-
- //TextInput组件,改用修复了Bug的扩展
- private var _myTxt:BugFixedTextInput;
-
-
- public function FlashTextInputTest() {
- // constructor code
- init();
- }
-
- private function init():void
- {
-
- //将文本框添加到舞台上
- _myTxt=new BugFixedTextInput();
- addChild(_myTxt);
-
- if(stage)
- {
- updateWhenAddedToStage();
- }else{
- addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
- }
- }
-
- private function addedToStageHandler(event:Event):void
- {
- removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
- updateWhenAddedToStage();
- }
-
- private function updateWhenAddedToStage():void
- {
- stage.align=StageAlign.TOP_LEFT;
- stage.scaleMode=StageScaleMode.NO_SCALE;
- stage.addEventListener(Event.RESIZE,resizeHandler);
- updateLayout();
- }
-
- private function resizeHandler(event:Event):void
- {
- //舞台缩放时,重新布局组件
- updateLayout();
- }
-
- private function updateLayout():void
- {
- //根据页边距及舞台尺寸对Txt组件进行移动和缩放
- _myTxt.move(_margin,_margin);
-
- //设置width即可,无需再调用drawFocus方法
- _myTxt.width=stage.stageWidth-_margin*2;
-
- }
-
- }
-
- }
复制代码
[[i] 本帖最后由 HBrO 于 2010-8-18 12:03 编辑 ] |
|