大部分时候,我们会放弃系统的默认镶边,自定义自己想要的镶边。这个时候,就需要自己手动来写效果了。基本过程是这样的。
1,屏蔽系统的镶边。
2,自己写皮肤,写逻辑(拖拽窗体,resize窗体,最大化,最小化,关闭,恢复等)。
每个AIR都有一个默认的xml配置文件,这里边定义了一些参数。通过打开注释,改变下边两个参数来关闭系统的镶边。一个是关闭镶边,另一个是打开透明。
<!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. --> <systemChrome>none</systemChrome> <!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. --> <transparent>true</transparent>
通过以上的设置,关闭了系统的镶边显示。然后来看怎么写自定义的镶边。最大化,最小化这些,比较好处理。这里主要讲下自由拖拽和自由resize。air提供了一个很好的方法(nativeWindow.startResize),来启动窗体的自由resize。里边可以带参数。参数标明拖拽的八个方向。仅仅这个是不够的,还要定义鼠标效果。鼠标移上去,拖拽光标要显示出来,拖拽的时候,光标跟着走。这里细节还是比较多。先记下光标的实现。
1,自己定义光标的显示对象。(位图,自己绘制都行)。
2,通过Mouse.registerCursor注册光标。registerCursor方法有两个参数,第一个参数是光标的名字,后边调用的时候需要,第二个参数是一个BitmapData的数组。就是光标的显示。
3,通过调用Mouse.cursor方法来更换光标。
其实,到了这里。在做这些之前,系统就已经有了一些光标效果。如鼠标遇到输入的时候的输入光标,遇到按钮的时候手型光标。当然通过上边的步骤,可以实现光标的定义。
下边说下拖拽。八个方向(上,上左,上右,左,右,下,下左,下右),通过定义sprite和范围来启动。可以通过定义一个sprite,然后通过Rectange来区分,调用resize,也可以通过建立八个sprite,分配好坐标来resize。我自己用的是后边一种方法。感觉还行。
建立八个sprite,然后对八个sprite进行侦听MouseDown,RollOver,RollOut事件。MouseDown事件,用来启动拖拽的,RollOver来显示光标的,RollOut来恢复到默认光标的。
RollOver的时候,根据不同的Sprite,取不同的光标效果。然后按下的时候,关掉mouseChildren属性。要不拖拽的时候,会出现泄露等瑕疵。同时,侦听stage的mouseUp事件,这个用来恢复默认光标。仅仅RllOut是不够的。还有,在RollOut的时候,如果鼠标状态是mouseDown状态,应不恢复默认光标。
上边这些可以定义到一个父类里边,以后用的时候,直接继承过来。至于按钮这些,可以定义在子类中。还有如果窗体是不规则的,可以自由对待。好了,细节有一些。贴出完整的代码吧。还需要更完善一些。
package com.vini123.chrome { import flash.display.NativeWindow; import flash.display.NativeWindowResize; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.MouseEvent; import flash.events.NativeWindowBoundsEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.ui.MouseCursor; public class ChromeBase extends Sprite { /** * 其他显示对象的容器 */ protected var contentContainer:Sprite; protected var win:NativeWindow; /** * 拖拽的范围(顶部的高度) */ protected var dragHeadHeight:int; /** * 拖拽,引动resize对象 */ private const DRAG_WEIGHT:int = 12; private var dragContainer:Sprite; private var dragTLButton:Sprite; private var dragTButton:Sprite; private var dragTRButton:Sprite; private var dragRButton:Sprite; private var dragBRButton:Sprite; private var dragBButton:Sprite; private var dragBLButton:Sprite; private var dragLButton:Sprite; private var _width:Number; private var _height:Number; public function ChromeBase() { addEventListener(Event.ADDED_TO_STAGE , addToStageHandler); } protected function addToStageHandler(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE , addToStageHandler); stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; win = stage.nativeWindow; contentContainer = new Sprite(); addChild(contentContainer); dragContainer = new Sprite(); addChild(dragContainer); initializeDragButton(); redrawDragButton(new Rectangle(0 , 0 , stage.stageWidth , stage.stageHeight)); dragHeadHeight = 30; win.minSize = new Point(480 , 360); win.maxSize = new Point(1280 , 720); win.addEventListener(NativeWindowBoundsEvent.RESIZE , boundsResizeHandler); contentContainer.addEventListener(MouseEvent.MOUSE_DOWN , mouseDownHandler); dragContainer.addEventListener(MouseEvent.ROLL_OUT , dragRollOutHandler); } private function upHandler(e:MouseEvent):void { mouseChildren = true; stage.removeEventListener(MouseEvent.MOUSE_UP , upHandler); WinCursor.cursor = MouseCursor.AUTO; } private function dragMouseDownHandler(e:MouseEvent):void { stage.addEventListener(MouseEvent.MOUSE_UP , upHandler); mouseChildren = false; switch(e.currentTarget) { case dragTLButton: win.startResize(NativeWindowResize.TOP_LEFT); break; case dragBRButton: win.startResize(NativeWindowResize.BOTTOM_RIGHT); break; case dragTButton: win.startResize(NativeWindowResize.TOP); break; case dragBButton: win.startResize(NativeWindowResize.BOTTOM); break; case dragTRButton: win.startResize(NativeWindowResize.TOP_RIGHT); break; case dragBLButton: win.startResize(NativeWindowResize.BOTTOM_LEFT); break; case dragLButton: win.startResize(NativeWindowResize.LEFT); break; case dragRButton: win.startResize(NativeWindowResize.RIGHT); break; } } private function dragRollOverHandler(e:MouseEvent):void { switch(e.currentTarget) { case dragTLButton: case dragBRButton: WinCursor.cursor = WinCursor.DESKTOP_RESIZE_TL; break; case dragTButton: case dragBButton: WinCursor.cursor = WinCursor.DESKTOP_RESIZE_TB; break; case dragTRButton: case dragBLButton: WinCursor.cursor = WinCursor.DESKTOP_RESIZE_TR; break; case dragLButton: case dragRButton: WinCursor.cursor = WinCursor.DESKTOP_RESIZE_LR; break; } } /** * * @param e * 手型移出 */ private function dragRollOutHandler(e:MouseEvent):void { if(e.buttonDown) return; WinCursor.cursor = MouseCursor.AUTO; } /** * * @param e * 窗口大小改变 */ private function boundsResizeHandler(e:NativeWindowBoundsEvent):void { var rect:Rectangle = e.afterBounds; redrawDragButton(rect); } /** * * @param e * 拖动窗口 */ private function mouseDownHandler(e:MouseEvent):void { if(mouseY < dragHeadHeight) win.startMove(); } private function initializeDragButton():void { dragTLButton = getDragButton(null , new Rectangle(0 , 0 , DRAG_WEIGHT , DRAG_WEIGHT) , dragMouseDownHandler , dragRollOverHandler); dragTButton = getDragButton(null , new Rectangle(0 , 0 , DRAG_WEIGHT , DRAG_WEIGHT) , dragMouseDownHandler , dragRollOverHandler); dragTRButton = getDragButton(null , new Rectangle(0 , 0 , DRAG_WEIGHT , DRAG_WEIGHT) , dragMouseDownHandler , dragRollOverHandler); dragRButton = getDragButton(null , new Rectangle(0 , 0 , DRAG_WEIGHT , DRAG_WEIGHT) , dragMouseDownHandler , dragRollOverHandler); dragBRButton = getDragButton(null , new Rectangle(0 , 0 , DRAG_WEIGHT , DRAG_WEIGHT) , dragMouseDownHandler , dragRollOverHandler); dragBButton = getDragButton(null , new Rectangle(0 , 0 , DRAG_WEIGHT , DRAG_WEIGHT) , dragMouseDownHandler , dragRollOverHandler); dragBLButton = getDragButton(null , new Rectangle(0 , 0 , DRAG_WEIGHT , DRAG_WEIGHT) , dragMouseDownHandler , dragRollOverHandler); dragLButton = getDragButton(null , new Rectangle(0 , 0 , DRAG_WEIGHT , DRAG_WEIGHT) , dragMouseDownHandler , dragRollOverHandler); } private function redrawDragButton(value:Rectangle):void { var half:int = DRAG_WEIGHT * 0.5; getDragButton(dragTLButton , new Rectangle(-half , -half , DRAG_WEIGHT , DRAG_WEIGHT) , null);//顶左 getDragButton(dragTButton , new Rectangle(half , -half , value.width - DRAG_WEIGHT , DRAG_WEIGHT) , null); //顶 getDragButton(dragTRButton , new Rectangle(value.width - half , -half , DRAG_WEIGHT , DRAG_WEIGHT) , null); //顶右 getDragButton(dragRButton , new Rectangle(value.width - half , half , DRAG_WEIGHT , value.height - DRAG_WEIGHT) , null); //右 getDragButton(dragBRButton , new Rectangle(value.width - half , value.height -half , DRAG_WEIGHT , DRAG_WEIGHT) , null); //底右 getDragButton(dragBButton , new Rectangle(half , value.height - half , value.width - DRAG_WEIGHT , DRAG_WEIGHT) , null); //底 getDragButton(dragBLButton , new Rectangle(-half , value.height-half , DRAG_WEIGHT , DRAG_WEIGHT) , null); //底左 getDragButton(dragLButton , new Rectangle(-half , half , DRAG_WEIGHT , value.height - DRAG_WEIGHT) , null); //左 width = value.width; height = value.height; } private function getDragButton(sp:Sprite , value:Rectangle , downHandler:Function = null , overHandler:Function = null , outHandler:Function = null):Sprite { if(!sp) { sp = new Sprite(); dragContainer.addChild(sp); } sp.graphics.clear(); sp.graphics.beginFill(0xffffff, 0.0); sp.graphics.drawRect(value.x , value.y , value.width , value.height); sp.graphics.endFill(); if(downHandler) { sp.addEventListener(MouseEvent.MOUSE_DOWN , downHandler); } if(overHandler) { sp.addEventListener(MouseEvent.ROLL_OVER , overHandler); } if(outHandler) { sp.addEventListener(MouseEvent.ROLL_OUT , outHandler); } return sp; } override public function set width(value:Number):void { if(_width != value) { _width = value; redraw(); } } override public function get width():Number { return _width; } override public function set height(value:Number):void { if(_height != value) { _height = value; redraw(); } } override public function get height():Number { return _height; } protected function redraw():void { } } }
package com.vini123.chrome { import flash.display.Bitmap; import flash.display.BitmapData; import flash.geom.Point; import flash.ui.Mouse; import flash.ui.MouseCursorData; public class WinCursor extends Object { [Embed(source="/assets/cursor/tl.png")] private static const TLSkin:Class; [Embed(source="/assets/cursor/tb.png")] private static const TBSkin:Class; [Embed(source="/assets/cursor/tr.png")] private static const TRSkin:Class; [Embed(source="/assets/cursor/lr.png")] private static const LRSkin:Class; private static var hasRegData:Boolean = false; public function WinCursor():void { super(); } public static function get cursor() : String { return Mouse.cursor; } public static function set cursor(param1:String) : void { if((_locked) || Mouse.cursor == param1) { return; } if(!hasRegData) { regData(); } Mouse.cursor = param1; } private static var _locked:Boolean = false; public static function get locked() : Boolean { return _locked; } public static function set locked(param1:Boolean) : void { _locked = param1; } public static const DESKTOP_CIRCLE:String = "appCircle"; public static const DESKTOP_RESIZE_TL:String = "desktop_resize_tl"; //左上 - 右下 public static const DESKTOP_RESIZE_TB:String = "desktop_resize_tb"; //上下 public static const DESKTOP_RESIZE_TR:String = "desktop_resize_tr"; //右上 - 左下 public static const DESKTOP_RESIZE_LR:String = "desktop_resize_lr"; //左右 private static function regData() : void { var bitmapData:BitmapData; var mouseCursorData:MouseCursorData; bitmapData = (new TLSkin() as Bitmap).bitmapData; mouseCursorData = new MouseCursorData(); mouseCursorData.data = new <BitmapData>[bitmapData]; mouseCursorData.hotSpot = new Point(bitmapData.width * 0.5 , bitmapData.height * 0.5); Mouse.registerCursor(DESKTOP_RESIZE_TL , mouseCursorData); bitmapData = (new TBSkin() as Bitmap).bitmapData; mouseCursorData = new MouseCursorData(); mouseCursorData.data = new <BitmapData>[bitmapData]; mouseCursorData.hotSpot = new Point(bitmapData.width * 0.5 , bitmapData.height * 0.5); Mouse.registerCursor(DESKTOP_RESIZE_TB , mouseCursorData); bitmapData = (new TRSkin() as Bitmap).bitmapData; mouseCursorData = new MouseCursorData(); mouseCursorData.data = new <BitmapData>[bitmapData]; mouseCursorData.hotSpot = new Point(bitmapData.width * 0.5 , bitmapData.height * 0.5); Mouse.registerCursor(DESKTOP_RESIZE_TR , mouseCursorData); bitmapData = (new LRSkin() as Bitmap).bitmapData; mouseCursorData = new MouseCursorData(); mouseCursorData.data = new <BitmapData>[bitmapData]; mouseCursorData.hotSpot = new Point(bitmapData.width * 0.5 , bitmapData.height * 0.5); Mouse.registerCursor(DESKTOP_RESIZE_LR , mouseCursorData); hasRegData = true; } } }
package com.vini123.chrome { import com.vini123.library.component.display.ScaleBitmap; import flash.display.Bitmap; import flash.geom.Rectangle; public class Chrome extends ChromeBase { [Embed(source="/assets/background.png")] private var Background:Class; private var background:ScaleBitmap; public function Chrome() { super(); } override protected function redraw():void { if(!width|| !height) return; if(!background) { background = new ScaleBitmap((new Background() as Bitmap).bitmapData); background.scale9Grid = new Rectangle(15 , 15 , 50 , 20); contentContainer.addChild(background); } background.width = width; background.height = height; } } }
默认窗体外的其他窗体,可以通过New NativeWindow出来。参数可以这样定义。
package com.vini123.window { import flash.display.NativeWindowInitOptions; import flash.display.NativeWindowSystemChrome; import flash.display.NativeWindowType; import flash.utils.Dictionary; public class WindowOptions { /** * 使用chrome系统镶边 */ public static const USE_CHROME:String = "use_chrome"; /** * 不使用chrome系统镶边 */ public static const NO_USE_CHROME:String = "no_use_chrome"; private static var optionsDic:Dictionary; public function WindowOptions() { } public static function getOptions(value:String):NativeWindowInitOptions { if(!optionsDic) optionsDic = new Dictionary(); if(optionsDic[value]) return optionsDic[value]; var useChrome:String = ""; var transparent:Boolean = false; switch(value) { case USE_CHROME: useChrome = NativeWindowSystemChrome.STANDARD; transparent = false; break; case NO_USE_CHROME: useChrome = NativeWindowSystemChrome.NONE; transparent = true; break; default: if(optionsDic[USE_CHROME]) { return optionsDic[USE_CHROME]; } useChrome = NativeWindowSystemChrome.STANDARD; transparent = false; break; } var options:NativeWindowInitOptions = new NativeWindowInitOptions(); options.systemChrome = useChrome; options.transparent = transparent; options.type = NativeWindowType.UTILITY; optionsDic[value] = options; return options; } } }