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

经典论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

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

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

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

搜索
查看: 4567|回复: 0

[AS3] Flash TextInput焦点框的一个Bug

[复制链接]
发表于 2010-8-18 11:43:37 | 显示全部楼层 |阅读模式
Flash/Flex组件的框架尽管已经开源,但修复Bug的任务依然举步维艰。近期的一个聊天室项目,要求网页中的Flash可以在全屏和正常模式下自由切换。作者使用了TextInput组件作为聊天内容输入的文本框,切换全屏的时候,发现了一个Bug,如果当前舞台焦点为TextInput,在全屏时,让TextInput组件的尺寸适应宽度变化,将会发现,焦点框并未随之缩放。作者在写此教程前,也对TextArea做了类似测试,却未发现问题。可见,Adobe的AS开发人员并未忽略此问题,可能仅为粗心大意所致。
另一方面,作者还分别测试了Flex SDK3.2,3.5,4.0的这两个组件,均不存在这个Bug。
由于作者已经选择了Flash组件,所以不愿为此改用Flex的框架,幸运的是,修复这一个Bug,所做的事情还是比较简单的。但更痛苦的事情还在后面,全屏后禁用键盘才是项目的关键问题之一,光为了这一个限制,作者就耗了3天多的时间才得以勉强解决。下一篇教程我会将全屏禁用键盘的几种解决方案贴上。
TextInputBug.jpg
首先,作者先贴上Flash TextInput组件焦点框Bug的测试代码(测试要求fla的库里已经加入TextInput组件):

  1. package com.hbro.documents {
  2.        
  3.         import fl.controls.TextInput;
  4.        
  5.         import flash.display.MovieClip;
  6.         import flash.events.Event;       
  7.         import flash.display.StageAlign;
  8.         import flash.display.StageScaleMode;       
  9.        
  10.         public class FlashTextInputTest extends MovieClip {
  11.                
  12.                 //设置页边距
  13.                 private var _margin:Number=10;
  14.                
  15.                 //TextInput组件
  16.                 private var _myTxt:TextInput;
  17.                
  18.                
  19.                 public function FlashTextInputTest() {
  20.                         // constructor code
  21.                         init();
  22.                 }
  23.                        
  24.                 private function init():void
  25.                 {
  26.                         //将文本框添加到舞台上
  27.                         _myTxt=new TextInput();
  28.                         addChild(_myTxt);
  29.                        
  30.                         if(stage)
  31.                         {
  32.                                 updateWhenAddedToStage();
  33.                         }else{
  34.                                 addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  35.                         }
  36.                 }
  37.                        
  38.                 private function addedToStageHandler(event:Event):void
  39.                 {
  40.                         removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  41.                         updateWhenAddedToStage();
  42.                 }
  43.                
  44.                 private function updateWhenAddedToStage():void
  45.                 {
  46.                         stage.align=StageAlign.TOP_LEFT;
  47.                         stage.scaleMode=StageScaleMode.NO_SCALE;
  48.                         stage.addEventListener(Event.RESIZE,resizeHandler);
  49.                         updateLayout();
  50.                 }
  51.                        
  52.                 private function resizeHandler(event:Event):void
  53.                 {
  54.                         //舞台缩放时,重新布局组件
  55.                         updateLayout();
  56.                 }
  57.                        
  58.                 private function updateLayout():void
  59.                 {
  60.                         //根据页边距及舞台尺寸对Txt组件进行移动和缩放
  61.                         _myTxt.move(_margin*stage.stageWidth/20,_margin);
  62.                         _myTxt.width=stage.stageWidth-_margin*2;
  63.                 }
  64.                
  65.         }
  66.        
  67. }

复制代码


进行测试,拖动Flash窗口,就会发现上图的Bug,无论在Flash IDE,Standalone Player还是浏览器,均出现这一问题,而且,即使用setSize方法设置width,结果也没有变化。

Flex3.2,3.5,4.0的TextInput均未在上述三种环境下的任一种内出现问题,在浏览器中,缩放浏览器窗口时,焦点框会自动消失(显然也不算Bug),所以,对于Flex,作者还附加了如下的测试代码:

  1. myTxt.addEventListener(Event.CHANGE,changeHandler);

  2.                        
  3. private function changeHandler(event:Event):void
  4. {
  5.         myTxt.width=200;
  6. }
复制代码

在输入文字后,文本框尺寸更改了,而且焦点框也自动适应了文本框大小。

所以,测试的结论:只有Flash的TextInput组件有这Bug,而且不同的测试环境下都存在。

修复此Bug比滚动条要容易很多,因为UIComponent提供了drawFocus方法,所以只需在调整大小以后调用重绘组件焦点框的函数即可。
drawFocus有一个Boolean参数,指示是否进行焦点框的绘制。所以,在调用该方法时,还需要通过FocusManager得知文本框是否为当前的焦点。

在设置大小后追加代码

  1. _myTxt.drawFocus(_focusManager.getFocus()==_myTxt);
复制代码


具体修复代码如下:


  1. package com.hbro.documents {
  2.        
  3.         import fl.controls.TextInput;
  4.         [color=red]import fl.managers.FocusManager;[/color]
  5.        
  6.         import flash.display.MovieClip;
  7.         import flash.events.Event;       
  8.         import flash.display.StageAlign;
  9.         import flash.display.StageScaleMode;       
  10.        
  11.         public class FlashTextInputTest extends MovieClip {
  12.                
  13.                 //设置页边距
  14.                 private var _margin:Number=10;
  15.                
  16.                 //TextInput组件
  17.                 private var _myTxt:TextInput;
  18.                
  19.                
  20.                 public function FlashTextInputTest() {
  21.                         // constructor code
  22.                         init();
  23.                 }
  24.                        
  25.                 private function init():void
  26.                 {
  27.                        
  28.                         [color]//初始化焦点管理器
  29.                         _focusManager=new FocusManager(this);[/color]
  30.                        
  31.                         //将文本框添加到舞台上
  32.                         _myTxt=new TextInput();
  33.                         addChild(_myTxt);
  34.                        
  35.                         if(stage)
  36.                         {
  37.                                 updateWhenAddedToStage();
  38.                         }else{
  39.                                 addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  40.                         }
  41.                 }
  42.                        
  43.                 private function addedToStageHandler(event:Event):void
  44.                 {
  45.                         removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  46.                         updateWhenAddedToStage();
  47.                 }
  48.                
  49.                 private function updateWhenAddedToStage():void
  50.                 {
  51.                         stage.align=StageAlign.TOP_LEFT;
  52.                         stage.scaleMode=StageScaleMode.NO_SCALE;
  53.                         stage.addEventListener(Event.RESIZE,resizeHandler);
  54.                         updateLayout();
  55.                 }
  56.                        
  57.                 private function resizeHandler(event:Event):void
  58.                 {
  59.                         //舞台缩放时,重新布局组件
  60.                         updateLayout();
  61.                 }
  62.                        
  63.                 private function updateLayout():void
  64.                 {
  65.                         //根据页边距及舞台尺寸对Txt组件进行移动和缩放
  66.                         _myTxt.move(_margin*stage.stageWidth/20,_margin);
  67.                         _myTxt.width=stage.stageWidth-_margin*2;
  68.                        
  69.                         [color=red]//重绘焦点框
  70.                         _myTxt.drawFocus(_focusManager.getFocus()==_myTxt);[/color]
  71.                 }
  72.                
  73.         }
  74.        
  75. }

复制代码


很多时候我们不希望每次都要通过组件外部主动调用drawFocus,所以,可以直接监听Resize事件,并将该部分的实现代码进行封装。


  1. package com.hbro.controls {
  2.        
  3.         import fl.controls.TextInput;
  4.         import fl.managers.FocusManager;
  5.         import flash.events.Event;

  6.         public class BugFixedTextInput extends TextInput {

  7.                 //焦点管理器
  8.                 private var _focusManager:FocusManager;
  9.                
  10.                 public function BugFixedTextInput() {
  11.                         // constructor code
  12.                         super();
  13.                         init();
  14.                 }
  15.                        
  16.                 protected function init():void
  17.                 {                       
  18.                         addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  19.                         //监听组件缩放事件
  20.                         addEventListener(Event.RESIZE,resizeHandler);
  21.                 }
  22.                
  23.                 private function addedToStageHandler(event:Event):void
  24.                 {
  25.                         removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  26.                         addEventListener(Event.REMOVED_FROM_STAGE,removedFromStageHandler);
  27.                         //添加到舞台时初始化焦点管理器
  28.                         _focusManager=new FocusManager(this.stage);
  29.                 }
  30.                
  31.                 private function removedFromStageHandler(event:Event):void
  32.                 {
  33.                         removeEventListener(Event.REMOVED_FROM_STAGE,removedFromStageHandler);
  34.                         //从舞台移除后,撤掉焦点管理器
  35.                         _focusManager=null;
  36.                 }
  37.                
  38.                 private function resizeHandler(event:Event):void
  39.                 {
  40.                         //组件缩放的时候,自动绘制焦点框
  41.                         if(_focusManager!=null)
  42.                         {
  43.                                 drawFocus(_focusManager.getFocus()==this);
  44.                         }
  45.                 }
  46.                
  47.         }

  48. }
复制代码


封装以后,仅需设置width或者setSize就可以修复焦点框不实时更新的Bug。


  1. package com.hbro.documents {
  2.        
  3.         import com.hbro.controls.BugFixedTextInput;
  4.        
  5.         import flash.display.MovieClip;
  6.         import flash.events.Event;       
  7.         import flash.display.StageAlign;
  8.         import flash.display.StageScaleMode;       
  9.        
  10.         public class FlashTextInputTest extends MovieClip {
  11.                
  12.                 //设置页边距
  13.                 private var _margin:Number=10;
  14.                
  15.                 //TextInput组件,改用修复了Bug的扩展
  16.                 private var _myTxt:BugFixedTextInput;
  17.                
  18.                
  19.                 public function FlashTextInputTest() {
  20.                         // constructor code
  21.                         init();
  22.                 }
  23.                        
  24.                 private function init():void
  25.                 {
  26.                        
  27.                         //将文本框添加到舞台上
  28.                         _myTxt=new BugFixedTextInput();
  29.                         addChild(_myTxt);
  30.                        
  31.                         if(stage)
  32.                         {
  33.                                 updateWhenAddedToStage();
  34.                         }else{
  35.                                 addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  36.                         }
  37.                 }
  38.                        
  39.                 private function addedToStageHandler(event:Event):void
  40.                 {
  41.                         removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  42.                         updateWhenAddedToStage();
  43.                 }
  44.                
  45.                 private function updateWhenAddedToStage():void
  46.                 {
  47.                         stage.align=StageAlign.TOP_LEFT;
  48.                         stage.scaleMode=StageScaleMode.NO_SCALE;
  49.                         stage.addEventListener(Event.RESIZE,resizeHandler);
  50.                         updateLayout();
  51.                 }
  52.                        
  53.                 private function resizeHandler(event:Event):void
  54.                 {
  55.                         //舞台缩放时,重新布局组件
  56.                         updateLayout();
  57.                 }
  58.                        
  59.                 private function updateLayout():void
  60.                 {
  61.                         //根据页边距及舞台尺寸对Txt组件进行移动和缩放
  62.                         _myTxt.move(_margin,_margin);
  63.                        
  64.                         //设置width即可,无需再调用drawFocus方法
  65.                         _myTxt.width=stage.stageWidth-_margin*2;
  66.                        
  67.                 }
  68.                
  69.         }
  70.        
  71. }
复制代码

[[i] 本帖最后由 HBrO 于 2010-8-18 12:03 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2019-12-16 05:15 , Processed in 0.109101 second(s), 11 queries , Gzip On, Memcache On.

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

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