笔记九 :EgretH5通用MVC框架的操作:制作折叠菜单FoldList(UI部分)
前言:由于时间比较紧,这次的博客更偏向笔记性质,而不是教程性质,必须打开源代码,接着再一步一步参考以下的笔记,不然很多细节上的东西漏掉了运行时会出现不少问题。
源代码:
整体思路:
1.首先,我们在普通的List包含Item的范例,把其中每一个item改装成包含一个更小的list的组件。
2.接着是用一个二维数组给全部item的赋值,其中的二维数组代表着:包含着10个小list数据的数组smalllistdata,组合起来成为一个大list的数组biglistdata。把10个smalllistdata数组分别赋值给10个大的item,接着10个大item分别把smalllistdata数组中的n个数据赋值给n个小list中的小item。
3.然后用事件机制监听每一个大小item的点击:整体的View.ts来监听每一个item点击后发送来的事件。
4.接着想办法让小的list可以随时收缩折叠起来,运用的方法是包住小list的,group的scrollenable=true参数,可以使得group界限外面的东西不予显示,然后改变缩小这个group的高度,就可以同时实现自适应,又可以把小list隐藏掉。
演示:
第一步:按照MVC框架搭建规则搭建好基础界面(参考源代码src/example/module/demo/list的做法,以及下面的步骤)
完成效果是点击底部菜单栏的第四个可以弹出一个空白的界面出来。
- FoldListDemoController
- FoldListDemoView
- ViewConst
- DemoTest.ts (按钮监听)
- ControllerConst
第二步:建立好必须素材,包括两个item的皮肤以及view
完成效果:编写好两个Item,供后面使用。
- FoldItemSkin.exml
- ItemDemoSkin.exml
- FoldListSmallItemView.ts
- FoldListBigItemView.ts
- FoldBigItemSkin.exml
参考基础item 的ts代码
第三步:初始化组件和预览的配置(注意FoldBigItemSkin.exml中的自适应高度问题,就去掉skin中的高度,在底部设置一个空的group,设定好top的值)
完成效果:点开之后能出现一排大的Item,以及大item展开的一排小item。
3.1FoldListDemoView.ts中添加 初始化List
添加了组件的绑定
closeBtn: eui.Button;
arrCollection: eui.ArrayCollection;
list:eui.List;
initUI():中添加:
大致的设置了一下大的list
let self = this;
let data = [];
for(let i:number = 0;i<20;i++){
data.push({name:"大Item",info:i});
}
self.arrCollection = new eui.ArrayCollection(data);
self.list.itemRenderer = FoldListBigItemView;
self.list.dataProvider = self.arrCollection;
3.2在FoldListBigItemView:中添加:初始化List
大致的设置了一下大的list中的小list
在:uiCompHandler(){}中添加:
let self = this;
let data = [];
for(let i:number = 0;i<4;i++){
data.push({name:”大Item”,info:i});
}
let arrCollection = new eui.ArrayCollection(data);
self.list.itemRenderer = FoldListSmallItemView;
self.list.dataProvider = arrCollection;
和程序中添加:
private list:eui.List;
完成效果:点开之后能出现一排大的Item,以及大item展开的一排小item。
第四步:制作出一个二维数组,用来配置n*n的list数据,达到每个子菜单都分配到数据的目的
4.1在:FoldListDemoView.ts中: 制作数组
制作15个小list的data数据smallListdata,存入一个总的数组listdata中,这是要填入的全部大小item的数据
initUI();添加
//包含15个小list的大list
let listdata = [];
//15个小list的生成
for(let i:number=0;i<15;i++){
//生成一个小list
let smallListdata = [];
for(let j:number=0;j<5;j++){
smallListdata.push({bigListId:i,smallListId:j});
}
//小list,push进,大list
this.listdata.push({listvis:false,bigListId:i,smallList:smallListdata});
}
以及代码中添加上:给大List赋值数据
self.arrCollection = new eui.ArrayCollection(listdata);
self.list.itemRenderer = FoldListBigItemView;
self.list.dataProvider = self.arrCollection;
4.2在:FoldListBigItemView.ts中: 重新初始化子list菜单,大List中的Item给小list赋值
删除掉之前uiComHandler()中的List初始化
在dataChanged()函数中添加:
大List中的Item给小list赋值
let self = this;
let data = [];
for(let i in this.data.smallList){
data.push({bigListId:this.data.smallList[i].bigListId,smallListId:this.data.smallList[i].smallListId})
}
let arrCollection = new eui.ArrayCollection(data);
self.list.itemRenderer = FoldListSmallItemView;
self.list.dataProvider = arrCollection;
以及在:FoldListSmallItemView.ts:
的dataChanged()函数中:小List中的item的相应事件
console.log("xxxxxxxxxxxxxxxxxxxxxxxxxxx",this.data.bigListId,this.data.smallListId);
第五步:根据每个item获得的坐标值配置点击事件,以及改变goup高度,实现折叠效果:
5.1写一个函数,只要触发了就会使得折叠效果进行变动
在FoldListDemoView.ts中:(其中的控件在exml一一对应)
编写一个函数,由子item,大的item中的按钮触发这个函数,效果是把折叠的参数存入listdata,分别赋值给大item,让大item进行折叠
其中ParamEvent后面会编写。
/**点击了大的item,接受通知展开子菜单 */
private updateScroller(event: ParamEvent): void {
let H = this.list.scrollV;//保存位置用来还原
//把打开的折叠回去
if (this.listdata[event.data.bigListId].listvis) {
this.listdata[event.data.bigListId].listvis = false;
} else {
//折叠其余
for (let i: number = 0; i < 15; i++) {
if (i == event.data.bigListId) {
this.listdata[i].listvis = true;
} else {
this.listdata[i].listvis = false;
}
}
}
this.arrCollection.refresh();
//刷新还原位置
this.scroller.validateNow();
this.list.scrollV = H;
}
在FoldListBigItemView.ts中:(其中的组件与exml文件相对应)
在dataChange()中添加
收到了listdata那边的折叠参数赋值,这边就会执行,并进行折叠小List设置
//根据传过来的数据设定子List的显示与否
if(this.data.listvis){
this.smallGroup.height = this.list.height;
}else{
this.smallGroup.height = 0;
}
5.2在大Item中的按钮编写触发这个函数的代码:
由于大Item数量比较多,不好直接调用FoldListDemoView.ts中的函数,所以要用到事件机制,把一个通知发送给FoldListDemoView.ts,然后FoldListDemoView.ts接到通知后执行此函数。
5.2.1编写ParamEvent.ts(一个可以传递data的事件类)
\src\example\event\ParamEvent.ts:
class ParamEvent extends egret.Event{
public data:any;
public constructor(type:string, data:any=null) {
super(type);
this.data = data;
}
}
5.2.2在EventName.ts中,注册点击事件:
添加上:
//折叠菜单模块
public static FOLDLIST_TAPBIG: string = "100";//点击折叠菜单的大item
5.2.3在FoldListDemoView.ts中:(配置监听这个点击事件)
InitUI()中:
GameDispatcher.getInstance().addEventListener(EventName.FOLDLIST_TAPBIG, this.updateScroller, this);//监听大item的点击
以及在dispose()函数中加入移除:
GameDispatcher.getInstance().removeEventListener(EventName.FOLDLIST_TAPBIG, this.updateScroller, this);//监听大item的点击
5.2.4在FoldListBigItemView.ts中:(配置这个按钮触发事件)
在uiCompHandler()函数中:
this.itembutton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.OnTouchHandler, this);
以及对应的:
private OnTouchHandler(): void {
let dataObj: Object = { bigListId: this.data.bigListId};
GameDispatcher.getInstance().dispatchEvent(new ParamEvent(EventName. FOLDLIST_TAPBIG,dataObj));
}
5.3 注意FoldBigItemSkin.exml中:去掉group之外的显示。
所有控件全部装在一个group中:
这个group的所有属性里加入scrollEnabled="true"
表示group之外的东西都不显示,可以配合实现折叠效果
<?xml version="1.0" encoding="utf-8"?>
<e:Skin class="FoldBigItemSkin" width="322" xmlns:e="http://ns.egret.com/eui" xmlns:w="http://ns.egret.com/wing">
<e:Group width="322" x="0" y="0" scrollEnabled="true">
<e:Image source="card_bg" anchorOffsetY="0" height="109" anchorOffsetX="0" width="319" scale9Grid="30,30,100,100" x="0" y="0" scaleX="1" scaleY="1"/>
<e:Group height="34" width="197.79" x="21.5" y="32.5" anchorOffsetX="0" scaleX="1" scaleY="1">
<e:Label id="titleDisplay" text="普通化肥" textColor="16777215" size="21" bold="true" horizontalCenter="-20.5" verticalCenter="3.5"/>
<e:Image source="icon_diamond" scaleX="0.5" scaleY="0.5" width="60" y="2" x="167.79"/>
<e:Image source="icon_02" x="-3" y="-5.5"/>
</e:Group>
<e:Button id="itembutton" label="B" x="228.89" y="32.5" anchorOffsetX="0" width="60" anchorOffsetY="0" height="34" scaleX="1" scaleY="1"/>
<e:Group id="smallGroup" width="322" x="0" anchorOffsetY="0" top="109" y="109" scaleX="1" scaleY="1">
<e:List id="list" width="322" x="0" y="0" blendMode="normal"/>
</e:Group>
</e:Group>
</e:Skin>
5.4添加上折叠的动画
5.4.1打开:FoldListBigItemView.ts
dataChanged():函数:(去掉之前的直接赋值this.smallGroup.height)
//根据传过来的数据设定子List的显示与否
if (this.data.listvis != this.storelistvis) {//检测this.data.listvis是否有变动
this.playFold(this.data.listvis);
}
5.4.2 FoldListBigItemView.ts中增加动画函数:
private storelistvis: boolean = false;
private isPlaying: boolean = false;
private playFold(dakai: boolean): void {
let self = this;
if (self.isPlaying == false) {
self.isPlaying = true;
if (dakai) {
egret.Tween.removeTweens(this.smallGroup);//播放前先清除之前的动画
//this.smallGroup.height = 0;
let tween = egret.Tween.get(this.smallGroup).to({ height: this.list.height }, 300).call(function () { self.isPlaying = false;self.storelistvis = true; });
} else {
egret.Tween.removeTweens(this.smallGroup);//播放前先清除之前的动画
//this.smallGroup.height = this.list.height;
let tween2 = egret.Tween.get(this.smallGroup).to({ height: 0 }, 300).call(function () { self.isPlaying = false;self.storelistvis = false; });
}
}
}
6.运行测试