一个实现Tab切换的容器扩展

来源:互联网 发布:js点击展开 隐藏切换 编辑:程序博客网 时间:2024/05/16 09:20

这是一个Sprite的扩展类,增加了Tab管理机制,允许用户通过Tab键(或方向键的左右),来切换内部显示对象的焦点,按Enter代表确认(触发Touch事件)。一般情况下我们的应用是运行在PC或移动设备上的,但现在随着其它一些平台,比如智能电视的发展,如果我们的代码可以支持无鼠标无touch的环境,就可以进一步增强跨平台的特性。

Tab sprite.jpg

运行实例: 点击这里

首先看一下使用方式,非常方便。Starling的入口类就不说了:

package{import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.utils.setTimeout;import starling.core.Starlingimport test.Gamepublic class TabSpriteTest extends Sprite{private var _starling:Starling; public function TabSpriteTest(){stage.align = StageAlign.TOP_LEFT;stage.scaleMode = StageScaleMode.NO_SCALE;setTimeout(initUI,100);} private function initUI():void{_starling = new Starling(Game, stage);_starling.start();}}}

来看看Game类的实现,我们只需要让Game继承TabSprite(代替Sprite),然后注册需要焦点管理的显示对象:

package test{import com.techmx.component.TabSpriteimport flash.display.Bitmap;import flash.geom.Rectangleimport starling.display.Button;import starling.display.DisplayObject;import starling.display.Image;import starling.display.Sprite;import starling.events.Touch;import starling.events.TouchEvent;import starling.events.TouchPhase;import starling.text.TextField;import starling.textures.Texture/** * Some domo code show you for how to use TabSprite * @author <a href="http://weibo.com/guoshaorui">NeoGuo</a> */public class Game extends TabSprite{/**create a textfield to display message*/private var textField:TextField[Embed(source="../assets/button_bg.jpg")]private var buttonBGClazz:Class[Embed(source="../assets/Media_flying.png")]private var birdClass:Classpublic function Game(){//create a textfield to display messagetextField = new TextField(400, 40, "Press Tab (or keyboard arrow left and right) change focus, press enter confirm");textField.border = true;textField.y = 260;addChild(textField);//create two buttonsvar btnBg:Bitmap = new buttonBGClazz();for (var i:int = 0; i < 2; i++) {var button:Button = new Button(Texture.fromBitmap(btnBg),"button"+i);button.name = "button"+i;button.x = i*100+20;button.y = 20;addChild(button);button.addEventListener(TouchEvent.TOUCH,touchHandler);touchedObjects.push(button);}//a bird image and six rangevar birdBmp:Bitmap = new birdClass();var birdImg:Image = new Image(Texture.fromBitmap(birdBmp));birdImg.name = "bird";birdImg.x = 20;birdImg.y = 60;addChild(birdImg);birdImg.addEventListener(TouchEvent.TOUCH,touchHandler);for (var j:int = 0; j < 6; j++) {var itemWidth:Number = birdImg.width/3;var itemHeight:Number = birdImg.height/2;var xIndex:int = j%3;var yIndex:int = j/3;var rect:Rectangle = new Rectangle(xIndex*itemWidth,yIndex*itemHeight,itemWidth,itemHeight);touchedObjects.push({target:birdImg,range:rect});}}/**listener for touch*/private function touchHandler(event:TouchEvent):void{var touch:Touch = event.touches[0];if(touch.phase == TouchPhase.ENDED){textField.text = (event.currentTarget as Object).name + ":" + touch.globalX + "," + touch.globalY;}}}}

这样就可以了,您可以通过Tab或方向键的左右,来切换焦点,按下Enter,则代表touch这个对象。

以下是TabSprite类的实现代码:

package com.techmx.component{import flash.display.BitmapData;import flash.display.Shape;import flash.geom.Point;import flash.geom.Rectangle;import flash.ui.Keyboardimport starling.core.Starling;import starling.core.starling_internal;import starling.display.DisplayObject;import starling.display.DisplayObjectContainer;import starling.display.Image;import starling.display.Sprite;import starling.events.Event;import starling.events.KeyboardEvent;import starling.events.Touch;import starling.events.TouchEvent;import starling.events.TouchPhase;import starling.textures.Texture; use namespace starling_internal; /** * 一个容器,允许用户通过Tab键(或方向键的左右),来切换内部显示对象的焦点,按Enter代表确认(触发Touch事件)。 * 适用于一些不能Touch的场合(比如智能TV)。 * @author <a href="http://weibo.com/guoshaorui">NeoGuo</a> */public class TabSprite extends Sprite{/**一个数组,包含可被焦点管理器管理的显示对象。 * 可接受类型为显示对象,或一个对象:{target:myMC,range:new Rectangle(0,0,100,100)},通过后面的方法,可以指定一个对象的某个区域为焦点响应区域。 * 您可以把需要被焦点管理器管理的对象添加到这个数组,当显示对象处于显示列表之后,他们就可以用Tab键(或方向键的左右)进行控制。 */public var touchedObjects:Vector.<Object>;/**用户必须通过键盘先激活Tab模式*/protected var enabled:Boolean = false;/**处于焦点的索引*/protected var tabIndex:int = 0;/**处于焦点的显示对象*/protected var tabChild:DisplayObject;/**处于焦点的显示对象区域*/protected var tabChildRect:Rectangle;/**容纳四边形显示的容器*/protected var rectHostContainer:DisplayObjectContainer;/**显示四边形的Image*/protected var rectImage:Image;/**用于修正滚动容器中造成的计算误差,比如用了Foxhole库。如果没有用到这个类库,请忽略这个属性。*/protected var touchPointOffset:Point;/** * CONSTRATOR */public function TabSprite(){super();this.addEventListener(Event.ADDED_TO_STAGE,initTabSprite);this.addEventListener(Event.REMOVED_FROM_STAGE,clearTabSprite);touchedObjects = new Vector.<Object>();rectHostContainer = this;}/** * 初始化容器 */protected function initTabSprite(...args):void{stage.addEventListener(KeyboardEvent.KEY_DOWN,onSpriteKeyDown);}/** * 临时清理容器 */protected function clearTabSprite(...args):void{stage.removeEventListener(KeyboardEvent.KEY_DOWN,onSpriteKeyDown);clearTabRect();}/** * 侦听键盘按下,切换焦点 * @param event KeyboardEvent */protected function onSpriteKeyDown(event:KeyboardEvent):void{if(!visible || !touchable || touchedObjects == null || touchedObjects.length == 0 )return;if(event.keyCode == Keyboard.ENTER){if(tabChild != null)touchCurrentChild();clearTabRect();return;}if(event.keyCode != Keyboard.TAB && event.keyCode != Keyboard.LEFT && event.keyCode != Keyboard.RIGHT)return;if(!enabled){enabled = true;tabIndex = 0;}else if(event.keyCode == Keyboard.TAB || event.keyCode == Keyboard.RIGHT){tabIndex++;if(tabIndex == touchedObjects.length)tabIndex = 0;onTabKeyPress();}else if(event.keyCode == Keyboard.LEFT){tabIndex--;if(tabIndex < 0)tabIndex = touchedObjects.length-1;onTabKeyPress();}if(touchedObjects[tabIndex] is DisplayObject){tabChild = touchedObjects[tabIndex] as DisplayObject;tabChildRect = null;}else{tabChild = touchedObjects[tabIndex]["target"];tabChildRect = touchedObjects[tabIndex]["range"];}if(tabChild == null || !tabChild.visible || !tabChild.touchable)return;showTabRect();}/**供继承类来实现*/protected function onTabKeyPress():void{ }/** * 当用户按下Enter键,模拟Touch */private function touchCurrentChild():void{var position:Point;if(tabChildRect != null)position = new Point(tabChild.x+tabChildRect.x+tabChildRect.width/2,tabChild.y+tabChildRect.y+tabChildRect.height/2);elseposition = new Point(tabChild.x+tabChild.width/2,tabChild.y+tabChild.height/2);if(touchPointOffset != null){position.x -= touchPointOffset.x;position.y -= touchPointOffset.y;}var touch:Touch = new Touch(0,position.x,position.y,TouchPhase.ENDED,this);touch.setTimestamp(Starling.current.juggler.elapsedTime);//touch.var touchs:Vector.<Touch> = new Vector.<Touch>();touchs.push(touch);var touchEvent:TouchEvent = new TouchEvent(TouchEvent.TOUCH,touchs,true,true,true);tabChild.dispatchEvent(touchEvent);}/**清理焦点显示*/protected function clearTabRect():void{if(rectImage == null)return;if(rectImage.parent != null)rectImage.removeFromParent();if(rectImage != null || rectImage.texture != null){rectImage.texture.dispose();rectImage.dispose();rectImage = null;}}/**显示当前焦点区域*/protected function showTabRect():void{clearTabRect();//get rectvar rect:Rectangle = tabChild.getBounds(this);if(tabChildRect != null){rect.x += tabChildRect.x;rect.y += tabChildRect.y;rect.width = tabChildRect.width;rect.height = tabChildRect.height;}//drawvar shape:Shape = new Shape();shape.graphics.lineStyle(12,0xD9D919,1);shape.graphics.moveTo(0,0);shape.graphics.lineTo(rect.width,0);shape.graphics.lineTo(rect.width,rect.height);shape.graphics.lineTo(0,rect.height);shape.graphics.lineTo(0,0);var bmd:BitmapData = new BitmapData(rect.width,rect.height,true,0x000000);bmd.draw(shape);var texture:Texture = Texture.fromBitmapData(bmd,false);rectImage = new Image(texture);rectImage.touchable = false;rectImage.x = rect.x;rectImage.y = rect.y;rectHostContainer.addChild(rectImage);bmd.dispose();}/** * 取消这个容器的Tab管理,和普通容器一致 */public function cancelTabManagement():void{touchedObjects = null;removeEventListener(Event.ADDED_TO_STAGE,initTabSprite);removeEventListener(Event.REMOVED_FROM_STAGE,clearTabSprite);if(stage != null)stage.removeEventListener(KeyboardEvent.KEY_DOWN,onSpriteKeyDown);tabChild = null;}/**@private*/override public function dispose():void{touchedObjects = null;tabChild = null;removeEventListener(Event.ADDED_TO_STAGE,initTabSprite);removeEventListener(Event.REMOVED_FROM_STAGE,clearTabSprite);clearTabRect();super.dispose();}}}
点击打开链接
0 0
原创粉丝点击