- A+
Laya1.0 UI模式
目录
Laya1.0的UI模式有内嵌模式,加载模式和分离模式,总共3种模式。本文将介绍各种模式的差异,并通过示例演示3种模式如何使用。
内嵌模式(默认模式)
内嵌模式是IDE默认使用的方式,这种模式下,进行UI页面的导出时,会将配置信息等内容导出为项目的代码文件。最终发布成游戏时,UI页面配置信息会全部出现在游戏的js文件中。这种模式下,由于js文件较大(因为包含了UI页面信息),会导致启动页index.html加载较慢,另外对于微信小游戏来说,也占用了小游戏本地包的体积。
加载模式
加载模式是将所有UI页面的配置信息导出为一份json文件,跟UI页面定义代码分离的一种模式。该模式下,需要先加载UI的全局json配置文件,才能在游戏中打开各个UI页面。由于分离了UI页面配置信息,js文件的体积也会相应降低,适合在微信小游戏中使用此模式。另外该模式,简单易用,不需要修改过多代码,即可从内嵌模式修改为加载模式。
分离模式
分离模式与加载模式类似,加载模式将所有UI页面配置信息导出为一份json配置文件,而分离模式,则是按UI页面分别导出json文件,并不会把所有的页面配置合并在一个json文件中。所以,分离模式最终导出的是多份json配置文件。该模式在使用时,需要先加载对应UI页面的json配置文件后,才能打开对应的UI页面。另外,此模式下,需要在UI页面创建时主动调用createView方法
,而UI代码又是自动生成的,所以使用起来比较麻烦,需要通过修改IDE相关代码才能实现自动添加createView方法
。此模式相较加载模式的优点是,没打开的页面不进行加载,也减少了一定的内存,而且首次加载需要的流量也更小,毕竟只加载了需要的UI配置而不是全部UI配置。缺点,需要修改IDE代码实现自动化,另外可能还需要修改相应的项目代码,总的来说比较麻烦。
使用示例
下面将使用layaIDE 1.7.21进行演示。
建立测试用项目
- 新建as3的空UI项目
-
快捷键
Alt + w
切换到编辑模式
-
右键新建UI页面a
-
打开a.ui页面,并切换到代码模式,修改代码如下:
<View width="600" sceneColor="#000000" height="400" editorInfo="compId=1"> <Button y="197" x="74" width="450" var="btnA" skin="comp/button.png" sizeGrid="6,15,9,15" labelSize="60" label="跳转到B" height="166" editorInfo="compId=2"/> <Label y="35" x="86" width="428" text="我是A页面" styleSkin="comp/label.png" height="92" fontSize="80" color="#f8f0ef" bold="true" editorInfo="compId=3"/> </View>
-
切换回视图模式,并且按
ctrl+s
保存UI修改。 -
最后a页面如下图所示
-
创建多一个
b.ui
页面,不过我们这里尝试将b.ui
文件置于文件夹test
下 -
打开b.ui页面,并切换到代码模式,修改代码如下:
<View width="600" sceneColor="#000000" height="400" editorInfo="compId=1"> <Button y="197" x="74" width="450" var="btnB" skin="comp/button.png" sizeGrid="6,15,9,15" labelStrokeColor="#f61915" labelStroke="2" labelSize="60" label="跳转到A" height="166" editorInfo="compId=2"/> <Label y="49" x="86" width="428" text="我是B页面" styleSkin="comp/label.png" strokeColor="#f31815" stroke="1" height="92" fontSize="80" color="#91a5f3" bold="true" editorInfo="compId=3"/> </View>
- 切换回视图模式,并且按
ctrl+s
保存UI修改,最后b.ui页面如下
内嵌模式演示
-
快捷键
ctrl+F12
清理并导出UI代码 -
快捷键
Alt+Q
切换到代码模式我们可以看到aUI.as文件内容如下:
/**Created by the LayaAirIDE,do not modify.*/ package ui { import laya.ui.*; import laya.display.*; public class aUI extends View { public var btnA:Button; public static var uiView:Object =/*[STATIC SAFE]*/{"type":"View","props":{"width":600,"height":400},"child":[{"type":"Button","props":{"y":197,"x":74,"width":450,"var":"btnA","skin":"comp/button.png","sizeGrid":"6,15,9,15","labelSize":60,"label":"跳转到B","height":166}},{"type":"Label","props":{"y":35,"x":86,"width":428,"text":"我是A页面","styleSkin":"comp/label.png","height":92,"fontSize":80,"color":"#f8f0ef","bold":true}}]}; override protected function createChildren():void { super.createChildren(); createView(uiView); } } }
从代码可以看出,类aUI不仅包含了按钮btnA的声明,还包含了ui页面大小,字体,按钮颜色文字等各种信息。
以上就是内嵌模式生成的UI类,相对来说比较臃肿。 -
我们写个简单代码来使用aUI和bUI。修改
LayaSample.as
代码如下:package { import laya.events.Event; import laya.ui.View; import laya.utils.Handler; import laya.webgl.WebGL; import ui.aUI; import ui.test.bUI; import laya.net.Loader; public class LayaSample { private var newUI:*; public function LayaSample() { //初始化引擎 Laya.init(0, 0,WebGL); Laya.stage.scaleMode = "full"; //加载图集 Laya.loader.load(["res/atlas/comp.atlas"], Handler.create(this, onLoaded)); } //显示UI切换界面的通用函数 private function showUI(UIname:*,delUI:*=null):void { if(delUI != null) delUI.removeSelf();//删除指定UI //实例化新的UI newUI = new UIname(); //添加UI在舞台 Laya.stage.addChild(newUI); } //图集加载后回调 private function onLoaded():void { showUI(aUI); //监听按钮btnA的点击事件,触发后处理 newUI.btnA.on(Event.CLICK, this, showB); } //显示B页 private function showB():void { showUI(bUI,newUI) //监听按钮btnB的点击事件,触发后处理 newUI.btnB.on(Event.CLICK, this, showA); } //显示A页 private function showA():void { showUI(aUI,newUI) //监听按钮btnA的点击事件,触发后处理 newUI.btnA.on(Event.CLICK, this, showB); } } }
- 快捷键
F5
编译运行程序,可看到如下图,有A,B两个页面点击后相互跳转。 -
内嵌模式下,当UI页面使用的资源文件
res/atlas/comp.atlas
加载完成后,可以直接对页面进行操作,不需要额外编写代码。
加载模式演示
-
快捷键
Alt+w
再次切换到编辑模式,使用F9
打开项目设置面板。并做如上图所示修改,修改
UI模式
为加载模式
,修改加载UI发布目录
为bin/h5/ui.json
,并点击确定按钮。这样我们再重新清理导出UI,所有的UI配置就会写入到ui.json
文件中。 -
快捷键
ctrl+F12
清理并导出UI。 -
快捷键
Alt+Q
切换到代码模式,并重新打开aUI.as
文件。我们可以看到代码如下:
/**Created by the LayaAirIDE,do not modify.*/ package ui { import laya.ui.*; import laya.display.*; public class aUI extends View { public var btnA:Button; override protected function createChildren():void { super.createChildren(); loadUI("a"); } } }
很明显,相较于内嵌模式,代码量减少了,减少了UI页面相关的配置信息。那配置信息去哪里了呢?
-
快捷键
ctrl+P
并输入ui.json
打开ui.json
文件。看到
ui.json
内容如下:{"a":{"type":"View","props":{"width":600,"height":400},"child":[{"type":"Button","props":{"y":197,"x":74,"width":450,"var":"btnA","skin":"comp/button.png","sizeGrid":"6,15,9,15","labelSize":60,"label":"跳转到B","height":166}},{"type":"Label","props":{"y":35,"x":86,"width":428,"text":"我是A页面","styleSkin":"comp/label.png","height":92,"fontSize":80,"color":"#f8f0ef","bold":true}}]},"test/b":{"type":"View","props":{"width":600,"height":400},"child":[{"type":"Button","props":{"y":197,"x":74,"width":450,"var":"btnB","skin":"comp/button.png","sizeGrid":"6,15,9,15","labelStrokeColor":"#f61915","labelStroke":2,"labelSize":60,"label":"跳转到A","height":166}},{"type":"Label","props":{"y":49,"x":86,"width":428,"text":"我是B页面","styleSkin":"comp/label.png","strokeColor":"#f31815","stroke":1,"height":92,"fontSize":80,"color":"#91a5f3","bold":true}}]}}
可以看到
ui.json
包含了UI页面a和b的页面配置信息。 -
修改加载代码。
由于页面配置信息被分离开来,所以我们需要先加载UI页面的配置文件
ui.json
,之后才能对UI页面进行操纵。修改函数
LayaSample
和函数onLoaded
如下:public function LayaSample() { //初始化引擎 Laya.init(0, 0,WebGL); Laya.stage.scaleMode = "full"; //加载图集 // Laya.loader.load(["res/atlas/comp.atlas"], Handler.create(this, onLoaded)); Laya.loader.load([{ url: "res/atlas/comp.atlas", type: Loader.ATLAS },{ url: "ui.json", type: Loader.JSON }], Handler.create(this, this.onLoaded)); } private function onLoaded():void { View.uiMap = Laya.loader.getRes("ui.json"); showUI(aUI); //监听按钮btnA的点击事件,触发后处理 newUI.btnA.on(Event.CLICK, this, showB); }
- 快捷键
F5
,编译运行程序可以看到程序正常运行,并且加载了
ui.json
文件。 -
加载模式步骤总结
总的来说,加载模式需要以下几个步骤:
- 导出UI代码的时候以加载模式进行导出。
- 先加载所有UI的配置文件
ui.json
。 - 对
View.uiMap
进行赋值,即View.uiMap = Laya.loader.getRes("ui.json");
。
分离模式演示
- 快捷键
Alt+w
再次切换到编辑模式,使用F9
打开项目设置面板。并做如上图所示修改,修改
UI模式
为加载模式
,修改加载UI发布目录
为bin/h5/ui
,并点击确定按钮。这样我们再重新清理导出UI,所有的UI配置就会分别写入到bin/h5/ui
文件夹中。 -
快捷键
ctrl+F12
清理并导出UI。 -
快捷键
Alt+Q
切换到代码模式,并重新打开aUI.as
文件。我们可以看到代码如下:
/**Created by the LayaAirIDE,do not modify.*/ package ui { import laya.ui.*; import laya.display.*; public class aUI extends View { public var btnA:Button; override protected function createChildren():void { super.createChildren(); loadUI("a"); } } }
此时,我们发现,
aUI.as
的代码与加载模式
下的代码是一样的。事实上,这代码仍需修改才能运行,需要主动调用createView函数
- 修
aUI.as
代码,如下:/**Created by the LayaAirIDE,do not modify.*/ package ui { import laya.ui.*; import laya.display.*; public class aUI extends View { public var btnA:Button; override protected function createChildren():void { super.createChildren(); this.createView(Laya.loader.getRes("ui/a.json")); loadUI("a"); } } }
从上可以看到增加了
this.createView(Laya.loader.getRes("ui/a.json"));
这一行代码 -
修
bUI.as
代码,如下:/**Created by the LayaAirIDE,do not modify.*/ package ui.test { import laya.ui.*; import laya.display.*; public class bUI extends View { public var btnB:Button; override protected function createChildren():void { super.createChildren(); this.createView(Laya.loader.getRes("ui/test/b.json")); loadUI("test/b"); } } }
从上可以看到增加了
this.createView(Laya.loader.getRes("ui/test/b.json"));
这一行代码 -
修改
LayaSample.as
代码,使其采用分离加载
的模式。修改
LayaSample
函数如下:public function LayaSample() { //初始化引擎 Laya.init(0, 0,WebGL); Laya.stage.scaleMode = "full"; //加载图集 Laya.loader.load(["res/atlas/comp.atlas"], Handler.create(this, onLoaded)); }
修改
onLoaded
函数如下:private function onLoaded():void { Laya.loader.load([{ url: "ui/a.json", type: Loader.JSON }], Handler.create(this, function():void { showUI(aUI); //监听按钮btnA的点击事件,触发后处理 newUI.btnA.on(Event.CLICK, this, showB); })); }
修改
showB
函数如下:private function showB():void { Laya.loader.load([{ url: "ui/test/b.json", type: Loader.JSON }], Handler.create(this, function():void { showUI(bUI,newUI) //监听按钮btnB的点击事件,触发后处理 newUI.btnB.on(Event.CLICK, this, showA); })); }
修改
showA
函数如下:private function showA():void { Laya.loader.load([{ url: "ui/a.json", type: Loader.JSON }], Handler.create(this, function():void { showUI(aUI,newUI) //监听按钮btnA的点击事件,触发后处理 newUI.btnA.on(Event.CLICK, this, showB); })); }
- 快捷键
F5
编译运行程序可以看到先加载了
a.json
配置。在点击了跳转后,再加载了
b.json
配置。到这里,分离模式就能正常运作了。
- 分离模式步骤总结:
总的来说,分离模式也是三个步骤:
- 导出UI代码的时候以分离模式进行导出。
- 在打开对应的UI界面时,先加载对应UI界面的json配置文件。
- 在UI类中调用createView方法,来将配置与UI关联。
分离模式下IDE自动生成createView代码
从上面的分离模式演示示例中,我们是在aUI.as
和bUI.as
文件中编码this.createView(Laya.loader.getRes("ui/a.json"));
和this.createView(Laya.loader.getRes("ui/test/b.json"));
。但这种做法,是不正确的,因为aUI.as
和bUI.as
可能在无意中被IDE修改。
那怎样才能做到在UI类文件中自动添加如上代码呢?
可以考虑以下两个方案:
1. 写一个额外的脚本,对生成后的UI类代码进行处理,自动往UI类代码添加createView调用。
2. 让IDE生成代码的时候,自动帮我们加上createView调用。
由于第一个方案相当于是2次处理,虽然在某些时候很方便,但是需要在生成代码后,运行多一次额外脚本,稍显麻烦,所以下面我采用第二种方案,直接修改IDE生成代码的脚本,实现我们的功能。
修改IDE的UI导出生成代码
我的layaAir IDE
安装路径是E:\H5\LayaIDE
,以下是基于我这个路径来讲解的。
- 新增分离模式代码模板
打开文件夹
E:\H5\LayaIDE\resources\app\out\vs\layaEditor\codeTemplate
,并拷贝asCodeTpl.txt.load
重命名为asCodeTpl.txt.fenli
并修改
asCodeTpl.txt.fenli
代码如下:/**Created by the LayaAirIDE,do not modify.*/ package {!pack!} { {!imports!} public class {!className!} extends {!classType!} { {!vars!} override protected function createChildren():void { {!viewClassMap!} super.createChildren(); this.createView(Laya.loader.getRes("ui/{!uiPath!}.json")); loadUI("{!uiPath!}"); {!dataBinds!} } {!addCodes!} } }
-
修改IDE生成UI的js代码
打开
E:\H5\LayaIDE\resources\app\out\vs\layaEditor\h5
目录,并打开layabuilder.max.js
文件在如下图所示位置,新增代码
CodeTplManager.asCodeTplFenli=FileManager.readTxtFile(FileManager.getAppPath(Paths.ASCodeTemplate+".fenli"));
这行代码的作用就是将CodeTplManager.asCodeTplFenli指向我们刚才的模板文件。
然后再修改
CodeTplManager.getCodeTpl
函数,当选择的是分离模式时,使用我们的模板文件。只需在如下图的地方将原先的代码CodeTplManager.getCodeTpl=function(codeType,isPreset,isLoad,isEfc){ (isEfc===void 0)&& (isEfc=false); if(isLoad){ CodeTplManager.setCodeTpls("Load"); }else{ CodeTplManager.setCodeTpls("NoLoad"); }; var tplStr; codeType=Math.ceil(codeType); switch(codeType){ case 0: tplStr=CodeTplManager.asCodeTpl; if(isEfc){ tplStr=CodeTplManager.asCodeTplEfc; } else if(isPreset){ tplStr=CodeTplManager.asCodeTplPst; } break ; case 2:
改成
CodeTplManager.getCodeTpl=function(codeType,isPreset,isLoad,isEfc,pageExportType){ (isEfc===void 0)&& (isEfc=false); (pageExportType===void 0)&& (pageExportType=PageExportType.INCODE); if(isLoad){ CodeTplManager.setCodeTpls("Load"); }else{ CodeTplManager.setCodeTpls("NoLoad"); }; var tplStr; codeType=Math.ceil(codeType); switch(codeType){ case 0: if (pageExportType == PageExportType.LOAD_ONE) { // 分离模式使用我们自定义的模板 tplStr=CodeTplManager.asCodeTplFenli; } else { tplStr=CodeTplManager.asCodeTpl; } if(isEfc){ tplStr=CodeTplManager.asCodeTplEfc; } else if(isPreset){ tplStr=CodeTplManager.asCodeTplPst; } break ; case 2:
再修改
CodeManager.objToUI
中调用CodeTplManager.getCodeTpl
方法的地方。将
var tplStr; tplStr=CodeTplManager.getCodeTpl(ProjectSetting.codeType,isPreset,PageExportType.isLoadType(pageExportType),isEfc); str=CodeManager.createExportCode(tplStr,classObj); return str; }
改成
var tplStr; tplStr=CodeTplManager.getCodeTpl(ProjectSetting.codeType,isPreset,PageExportType.isLoadType(pageExportType),isEfc,pageExportType); str=CodeManager.createExportCode(tplStr,classObj); return str; }
即可。
-
重启IDE(或者刷新编辑器)
-
快捷键
Alt+w
再次切换到编辑模式,然后快捷键ctrl+F12
清理并导出UI。我们可以看到我们的代码
this.createView(Laya.loader.getRes("ui/a.json"));
和this.createView(Laya.loader.getRes("ui/test/b.json"));
没有被移除掉。
我们也可以将这两行代码删除,然后再运行一次ctrl+F12
清理并导出UI。会发送可以正常生成含createView
调用的代码,即表示我们修改IDE代码成功了。至此,IDE自动生成带createView
调用的演示就结束了。