EUI容器布局
白鹭引擎中的EUI容器布局分三种 : 水平,垂直,格子。
以上三种基本布局就能满足大部分的需求,然而亲(gao)爱(shi)的产品经理总会有奇奇怪怪的设计。
弧形
因为环形布局,依赖容器尺寸来定义半径,所以需要容器显式的设置width和height,在这种情况下measure方法将失去作用,如果需要根据内部子项计算尺寸,就要重写显示列表的更新函数updateDisplayList()
。在这个函数中,将根据起始角度,重定位所有子元件。
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 /**
* 自定义布局,支持椭圆(圆形),弧形布局
**/
export class MXCircleLayout extends eui.LayoutBase{
private _data : number;//弧度
public constructor(data ?: any){//
super();
this._data = data;
}
public measure():void{
super.measure();
}
/**重写显示列表更新*/
public updateDisplayList(unscaledWidth : number, unscaledHeight : number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(this.target == null){
return;
}
let cd : any = this._data || {}
let maxX : number = 0;
let maxY : number = 0;
//重定位所有子元件
for (let i = 0, count = this.target.numElements; i < count; i++){
let c_c : eui.UIComponent = <eui.UIComponent> (this.target.getVirtualElementAt(i));
if (!egret.is(c_c, "eui.UIComponent") || !c_c.includeInLayout){
continue;
}
let childX = 0;
let childY = 0;
switch(cd.type){
case "desc"://等差
childX = i % 2 == 0 ? ((i / 2) * (cd.desc + cd.width)) : (1 * (cd.width - 20) + (i / 2 - 0.5) * (cd.width+ 46));
childY = i % 2 == 0 ? 0 : 61;
break;
case "spe"://非相等间距
childX = (i == count - 1 ? (i * (cd.width + cd.desc) - cd.desc) : (i * (cd.width + cd.desc))) + 30;
childY = i == count - 1 ? -5 : 0;
break;
case "hor"://水平
childX = i * (cd.gap + cd.width);
childY = 0;
maxX = cd.width;
maxY = cd.height;
break;
case 'other'://非规则其他类型,按预先位置直接赋值即可
break;
case 'circle'://环形
//中心坐标
let centerX = unscaledWidth / 2;
let centerY = unscaledHeight / 2;
let a = centerX - (cd.ww || 0);//X轴
let b = centerY - (cd.hh || 0);//X轴
let sa = cd.sa || 0;//起始角度。
let rad = cd.rad || 2 * Math.PI;
if(rad < Math.PI){//弧形布局
let r = centerX / Math.sin(rad / 2);
a = b = r - (cd.ww || 0);
sa = sa - rad / 2;
centerY = r;
}
//获得角度的大小
let maxa : number = rad < Math.PI ? count - 1 : count;
let angle : number = sa + rad * i / maxa;
//获得圆周点的X坐标
childX : number = centerX + a * Math.sin(angle) - (cd.ww || 0);
childY : number = centerY - b * Math.cos(angle) - (cd.hh || 0);
break;
}
c_c.setLayoutBoundsPosition(childX, childY);
maxX = Math.max(maxX, childX + (cd.ww || 0));
maxY = Math.max(maxY, childY + (cd.hh || 0));
}
this.target.setContentSize(maxX, maxY);
}
}
抽离出来成类,调用时直接new MXCircleLayout()即可,传入预先设定好的参数1
2
3
4
5
6let layout = new MXCircleLayout({
"ww": 40 * 1.5,//按实际情况自行设定
"hh": 50 * 1.5,//按实际情况自行设定
"sa": -30 / 180 * Math.PI,//起始位置,默认为12点方向
});
list.layout = layout;