自定义 Boxmenu
效果
sample 代码
class Boxmenu extends FreshalRoute{
get title => 'Boxmenu';
Widget buildMyRouteContent(BuildContext context) {
/// Boxmenu的宽高比列
const double aspectRatio = 0.75;
/// portrait:Taller than wide,
/// landscape:Wider than tall.
/// 简单的说portrait就是竖屏,landscape是横屏
/// 如果横屏放3列,如果竖屏放4列
final int columnCount = (MediaQuery.of(context).orientation == Orientation.portrait) ? 3 : 4;
/// TODO : move to constants.dart
/// 创建菜单项目
List<BoxMenuItem> menus = [
BoxMenuItem("ELECTRICITY", FontAwesomeIcons.bolt, (){print('electricity pressed');}),
BoxMenuItem("WATER", FontAwesomeIcons.tint, (){print('water pressed');}),
BoxMenuItem("MOBILE", FontAwesomeIcons.mobile, (){print('mobile pressed');}),
BoxMenuItem("ELECTRICITY", FontAwesomeIcons.bolt, (){print('electricity pressed');}),
BoxMenuItem("WATER", FontAwesomeIcons.tint, (){print('water pressed');}),
BoxMenuItem("MOBILE", FontAwesomeIcons.mobile, (){print('mobile pressed');}),
BoxMenuItem("ELECTRICITY", FontAwesomeIcons.bolt, (){print('electricity pressed');}),
BoxMenuItem("WATER", FontAwesomeIcons.tint, (){print('water pressed');}),
BoxMenuItem("MOBILE", FontAwesomeIcons.mobile, (){print('mobile pressed');}),
BoxMenuItem("ELECTRICITY", FontAwesomeIcons.bolt, (){print('electricity pressed');}),
BoxMenuItem("WATER", FontAwesomeIcons.tint, (){print('water pressed');}),
];
return SingleChildScrollView(
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final double columnWidth = constraints.biggest.width /
columnCount.toDouble();
print(columnWidth);
/// 最高225,随便定的一般现在都有1280了,所以至少能一屏幕显示4行菜单
final double rowHeight = math.min(225.0, columnWidth * aspectRatio);
print(rowHeight);
/// 11个项目,每行3个,应该就是4行。
final int rowCount = (menus.length / columnCount).ceil();
return Padding(
padding: const EdgeInsets.symmetric(vertical:8.0),
/// 文档说,RepaintBoundary widget在渲染树的层中创建了一个RenderRepaintBoundary。这用于减少需要重绘的需求量。
/// 我的理解是,RepaintBoundary会减少其children的重绘,可以提高性能
child: RepaintBoundary(
child: Column(上海海洋大学
children: List < Widget>.generate(rowCount, (int rowIndex) {
/// 计算每行列数
/// 如果是最后一列,那么就是剩下的菜单数量比如11个项目,最后一行是第4行,rowIndex是3,
/// menus.length - columnCount * math.max(0, rowCount - 1)
/// = 11 - 3 * math.max(0,4-1) = 2
/// 即最后一行为2列。
final int columnCountForRow = rowIndex == rowCount - 1
? menus.length - columnCount * math.max(0, rowCount - 1)
: columnCount;
return Row(
children: List < Widget>.generate(columnCountForRow, (
int columnIndex) {
final int index = rowIndex * columnCount + columnIndex;
final BoxMenuItem menuItem = menus[index];
return SizedBox(
width: columnWidth,
height: rowHeight,
child: Card (
color: Colors.grey.shade300,
/// customer widget
child: LabelBelowIcon(
betweenHeight: 15.0,
icon: menuItem.icon,
label: menuItem.label,
iconColor: Colors.indigo.shade800,
isCircleEnabled: false,
onPressed: menuItem.onPressed,
),
),
);
}),);
}),
),),
);
}),
);
}
}
class BoxMenuItem{
final String _label;
final IconData _icon;
final _onPressed;
get label => _label;
get icon => _icon;
get onPressed => _onPressed;
BoxMenuItem(this._label, this._icon, this._onPressed);
}
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102