最近開發的一個項目要用到單鍵快速鍵, 遂寫了個快速鍵管理類.
目前能滿足需求, 使用方便, 開放出來, 歡迎大家拍磚
主要功能:
- 各快速鍵可對應多個方法
- 各快速鍵可分別綁定 KeyUp 或 KeyDown 事件
- 已"快速鍵+事件+方法"確定某綁定, 均可單獨註冊/反註冊
下面是代碼 (Shortcut.as) :
package com.douban.utils{ import flash.display.Stage; import flash.events.KeyboardEvent; /** * 快速鍵管理器 * @author Seven Yu */ public class Shortcut { // 註冊/登出快速鍵動作 private static const ACTION_ADD:int = 1; private static const ACTION_DEL:int = -1; // 儲存按鍵與方法映射 private static var _keyMaps:Object = {}; // 綁定鍵盤監聽的 stage private static var _stage:Stage; // 是否開始監聽標記 (可以暫停全部監聽, 改造成非靜態類可以按需暫停/監聽) private static var _started:Boolean = false; // 事件類型對應方法計數器 private static var _upFuncsCount:int = 0; private static var _downFuncsCount:int = 0; /** * 初始化 * @paramstage 綁定鍵盤事件的 stage * @paramautoStart 自動開始監聽 (預設: false) */ public static function init(stage:Stage, autoStart:Boolean = false):void { _stage = stage; autoStart && start(); } /** * 開始監聽鍵盤事件 */ public static function start():void { if (_stage) { _started = true; } } /** * 停止監聽 */ public static function stop():void { _started = false; } /** * 處理快速鍵響應 * @paramevt */ private static function keyHandler(evt:KeyboardEvent):void { trace('event type:', evt.type, 'key code:', evt.keyCode); if (!_started) { return; } var keyName:String = getKeyName(evt.type, evt.keyCode); if (keyName in _keyMaps) { var funcs:Array = _keyMaps[keyName].concat(); for (var i:int = 0, len:int = funcs.length; i < len; i++) { funcs[i](); } } } /** * 註冊快速鍵 * @paramkeyCode * @paramfunc * @paramtype */ public static function register(keyCode:int, func:Function, type:String = KeyboardEvent.KEY_UP):void { trace('shortcat.register', keyCode); var keyName:String = getKeyName(type, keyCode); if (keyName in _keyMaps) { trace(_keyMaps[keyName].indexOf(func)); if (_keyMaps[keyName].indexOf(func) == -1) { _keyMaps[keyName].push(func); checkFuncs(type, ACTION_ADD); } } else { _keyMaps[keyName] = [func]; checkFuncs(type, ACTION_ADD); } } /** * 登出快速鍵 * @paramkeyCode * @paramfunc * @paramtype */ public static function unregister(keyCode:int, func:Function, type:String = KeyboardEvent.KEY_UP):void { trace('shortcat.unregister', keyCode); var keyName:String = getKeyName(type, keyCode); if (keyName in _keyMaps) { var funcIndex:int = _keyMaps[keyName].indexOf(func); if (funcIndex >= 0) { _keyMaps[keyName].splice(funcIndex, 1); checkFuncs(type, ACTION_DEL); } } } /** * 檢測函數註冊數, 以確定綁定或移除事件監聽 * @paramtype 事件類型 * @paramaction 動作(添加或移除) */ private static function checkFuncs(type:String, action:int):void { trace('check funcs', type, action); if (!_stage) { throw new Error('Please call Shortcut.init method first.'); } switch (type) { case KeyboardEvent.KEY_UP: { _upFuncsCount += action; if (1 == _upFuncsCount) { _stage.addEventListener(KeyboardEvent.KEY_UP, keyHandler); } if (0 == _upFuncsCount) { _stage.removeEventListener(KeyboardEvent.KEY_UP, keyHandler); } break; } case KeyboardEvent.KEY_DOWN: { _downFuncsCount += action; if (1 == _downFuncsCount) { _stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHandler); } if (0 == _downFuncsCount) { _stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyHandler); } break; } default: { throw new Error('KeyboardEvent.KEY_UP & KeyboardEvent.KEY_DOWN only.'); break; } } } /** * 擷取映射名 * @paramtype 事件類型 * @paramkeyCode 按鍵索引值 * @return 形如 type_keyCode 的字串 */ private static function getKeyName(type:String, keyCode:int):String { return [type, keyCode].join('_'); } /** * 是否已開始監聽 */ static public function get started():Boolean { return _started; } }}
例: (虛擬碼)
// 初始化快速鍵管理器Shortcut.init(stage, true);// 註冊 空格 + KeyUp + testFunc1 (預設 KeyUp 事件)Shortcut.register(Keys.SPACEBAR, testFunc1);// 註冊 空格 + KeyDown + testFunc1Shortcut.register(Keys.SPACEBAR, testFunc1, KeyboardEvent.KEY_DOWN);// 註冊 S + KeyUp + testFunc2Shortcut.register(Keys.S, testFunc2, KeyboardEvent.KEY_UP);// 反註冊 空格 + KeyUp + testFunc1 (KeyUp 為預設值, 可省略)Shortcut.unregister(Keys.SPACEBAR, testFunc1, KeyboardEvent.KEY_UP);// 反註冊 E + KeyUp + testFunc2 (不會有任何反映, 該組合沒被註冊過)Shortcut.unregister(Keys.E, testFunc2);// 測試函數1private function testFunc1():void{ trace('test function 1');}// 測試函數2private function testFunc2():void{ trace('test function 2');}
另外代碼中還用到一個 Keys 類, 是對一些鍵位相應 KeyCode 常量的定義, 直接改成對應的數字即可, 例如: 空格->32, S->83, E->69可能還有不成熟的地方, 歡迎拍磚, 共同探討