laya2.x UI类结构
- 新增加了一个Scene - > Sprite, Scene只有一个子类就是View,Dialog仍然继承View。
- Component也出现了变化:Component implements ISingletonElement, IDestroy。现在的Component变成了一个脚本的基类,它的子类有相对布局插件
Widget,Script,CommonScript。之前的Component现在被重命名为UIComponent。
- AnimationPlayerBase被重命名成为AnimationBase
laya1.0创建的UI:xxUI->View->Box->Component->Sprite
laya2.0创建的UI:xxUI->View->Scene->Sprite(创建时也可以选成Scene类型,xxUI->Scene->Sprite)
需要说明一下,现在创建的UI文件后缀名统一为.scene。
laya2.x的Scene类
1 public function open(closeOther:Boolean = true, param:*=null):void{ 2 if(closeOther) closeAll(); 3 root.addChild(scene); 4 onOpened(param); 5 } 6 public function close():void{ 7 if(autoDestroyAtClosed) this.destory(); 8 else removeSelf(); 9 onClosed(); 10 } 11 12 override public function destroy(destroyChild:Boolean = true):void{ 13 _idMap = null; 14 super.destroy(destroyChild); 15 var list:Array = Scene.unDestroyedScenes; 16 for(var i:int = 0, n:int = list.length; i<n;i++){ 17 if(lsit[i]===this){ 18 list.splice(i,1); 19 return; 20 } 21 } 22 } 23 24 //创建后,还未被销毁的场景列表,方便查看还未被销毁的场景列表,方便内存管理,本属性只读,请不要直接修改 25 public static var unDestroyedScenes:Array = []; 26 public function Scene(){ 27 this._setBit(Const.NOT_READY,true); 28 unDestroyedScenes.push(this); 29 this._scene = this; 30 createChildren(); 31 } 32 33 public static function open(url:String,closeOther:Boolean = true, complete:Handler = null, param:*=null):void{ 34 load(url,Handler.create(null,_onSceneLoaded,[closeOther,complete,param])); 35 } 36 37 private static function _onSceneLoaded(closeOther:Boolean,complete:Handler,param:*,scene:Scene):void{ 38 scene.open(closeOther,param); 39 if (complete) complete.runWith(scene); 40 } 41 42 public static funcion close(url:String,name:String= ""):Boolean{ 43 var flag:Boolean = false; 44 var list:Array = Scene.unDestroyedScenes; 45 for (var i:int=0,n:int=list.length;i<n;i++){ 46 var scene:Scene = list[i]; 47 if (scene.parent && scene.url === url && scene.name == name){ 48 scene.close(); 49 flag = true; 50 } 51 } 52 return flag; 53 } 54 55 public static function closeAll():void { 56 var root:Sprite = Scene.root; 57 for (var i:int = 0, n:int = root.numChildren;i<n;i++){ 58 var scene:Scene = root.getChildAt(0) as Scene; 59 if (scene is Scene) scene.close(); 60 } 61 } 62 63 public static function destroy(url:String,name:String=""):Boolean{ 64 var flag:Boolean = false; 65 var list:Array = Scene.unDestroyedScenes; 66 for (var i:int=0,n:int=list.length;i<n;i++){ 67 var scene:Scene = list[i]; 68 if (scene.url ===url && scene.name == name){ 69 scene.destroy(); 70 flag = true; 71 } 72 } 73 return flag; 74 } 75 76 public static function get root():Sprite{ 77 if(!_root){ 78 _root = Laya.stage.addChild(new Sprite()) as Sprite; 79 _root.name = "root"; 80 Laya.stage.on("resize",null,resize); 81 function resize():void{ 82 _root.size(Laya.stage.width, Laya.stage.height); 83 _root.event(Event.RESIZE); 84 } 85 resize(); 86 } 87 return _root; 88 }
1. autoDestroyAtClosed : 场景被关闭后,是否自动销毁(销毁节点和使用到的资源),默认为false
在close方法中,可以看到if (autoDestroyAtClosed) this.destroy();
2.在open方法中,看到root.addChild(scene);,而在get root中看到_root = Laya.stage.addChild(new Sprite()) as Sprite,这说明所有打开的Scene都被添加到一个叫root的Sprite容器里,这个容器是直接放在stage上了。
3.参考一下官方例子中如何使用scene的:
1 static startScene:any = "test/Test2View.scene"; 2 Laya.Scene.open(GameConfig.startScene);
这里直接调用static open方法,在里面调用了load方法
public static function load(url:String,complete:Handler = null):void{ Laya.loader.resetProgress(); var loader:SceneLoader = new SceneLoader(); loader.on(Event.COMPLETE,null,create); loader.load(url); function create():void { var obj:Object = Loader.getRes(url); if(!obj) throw "Can not find scene:" + url; if(!obj.props) throw "Scene data is error:" + url; var runtime:String = obj.props.runtime ? obj.props.runtime : obj.type; var clas:*=ClassUtils.getClass(runtime); if(obj.props.renderType=="instance"){ var scene:Scene = clas.instance || (clas.instance = new clas()); } else { scene = new clas(); } if (scene && scene is Node){ scene.url = rul; if (!scene._getBit(Const.NOT_READY)) complete.runWith(scene); else{ scene.on("onViewCreated",null,functon():void{ complete && complete.runWith(scene) }) scene.createView(obj); } }else{ throw "Can not find scene:" + runtime; } } }
牵涉到SceneLoader类
public static const LoadableExtensions:Object = {"scene":Loader.JSON}
这个映射会把test/Test2View.scene转化为去加载相应的json文件
Dialog
laya2.x创建的Dialog:xxDialogUI - > Dialog - > View - > Scene - > Sprite
Dialog会把Scene中默认的open方法覆盖掉,转交给DialogManager处理
//Dialog: override public function open(closeOther:Boolean = true, param:* = null):void { _dealDragArea(); _param=param; manager.open(this, closeOther, isShowEffect); manager.lock(false); } //DialogManager: public class DialogManager extends Sprite public function DialogManager() { this.mouseEnabled = maskLayer.mouseEnabled = true; this.zOrder = 1000; Laya.stage.addChild(this); Laya.stage.on(Event.RESIZE, this, _onResize); if (UIConfig.closeDialogOnSide) maskLayer.on("click", this, _closeOnSide); _onResize(null); } public function open(dialog:Dialog, closeOther:Boolean = false, showEffect:Boolean=false):void { if (closeOther) _closeAll(); if (dialog.isPopupCenter) _centerDialog(dialog); addChild(dialog); if (dialog.isModal || this._getBit(Const.HAS_ZORDER)) Laya.timer.callLater(this, _checkMask); if (showEffect && dialog.popupEffect != null) dialog.popupEffect.runWith(dialog); else doOpen(dialog); event(Event.OPEN); }
总结:可以把Scene看做是官方提供的一个场景管理器,像closeOther,closeAll,onOpened,onClosed都是很实用的。
实例:添加按钮切换场景
LayaAir2.x开发思路为组件化,脚本化,场景管理开发,项目采用scene管理方式,来管理场景,LayaAir已经对scene做了一系列方案,使得开发者无需考虑场景,关卡,页面的资源,内存管理,只需要单纯的调用接口,管理场景,其它的交给引擎去做,只需要专注游戏逻辑开发即可。
1.先新建一个脚本
2.在Start.scene中放一个按钮,就可以添加组件了,这样运行时,点击按钮,就会触发onClick方法打开box2d.scene场景。
3.按F9设置启动场景为Start.scene,现在运行后就能看到场景切换效果了。
4.在GameConfig的init方法中就可以看到
1 static init(){ 2 var reg: Function = Laya.ClassUtils.regClass; 3 reg("script/Start.ts",Start); 4 } 5 //ClassUtils: 6 public static function regClass(className:String, classDef:*):void { 7 _classMap[className] = classDef; 8 }
注:参考文章https://www.jianshu.com/p/5701f9f854fa