序
在APP
开发过程中,经常遇到需要添加背景、设置边距、动态显示和隐藏某个组件。
但是在Flutter
中,能同时具有添加背景、设置边距、阴影、边框、圆角的布局只有Container
(参考我上一篇文章的介绍Flutter入门之Row、Column、Container布局),这个已经算是业务功能比较多的组件了,而要想实现组件的显示和隐藏则需要用到另外一个组件Offstage
,水平的线性布局则需要用到组件Row
,垂直的线性布局则需要用到组件Column
,而Row
和Column
这两个布局都不具备直接设置背景、边距、显示和隐藏等功能。
在开发过程中这种需求又很常见,不可能每个地方都把这些代码重复一遍,所以对这几个组件封装一下,实现了一个类似Android
中LinearLayout
布局的组件很有必要。
封装LinearLayout
封装成LinearLayout
其实很简单,就是将Row
、Column
、Offstage
、Container
四个组件合理的组合在一起就可以了。
- 首先要暴露一个参数确定是水平的线性布局还是垂直的线性布局
- 将
Container
经常用到的背景、边距参数暴露出来 - 将
Row
、Column
中用到的主轴、交叉轴的对齐方式暴露出来 - 将
Row
、Column
中主轴size的适配方式暴露出来 - 暴露出一个方法用来动态改变组件的显示和隐藏
代码如下: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
103
104
105
106
107
108
109
110
111
112
113
114import 'package:flutter/material.dart';
import 'package:flutter_library/common/util.dart';
enum LayoutOrientation { horizontal, vertical }
class LinearLayout extends StatefulWidget {
final LayoutOrientation orientation;
final bool isVisible;
final Decoration background;
final EdgeInsetsGeometry padding;
final EdgeInsetsGeometry margin;
final List<Widget> children;
final MainAxisAlignment mainAxisAlignment;
final MainAxisSize mainAxisSize;
final CrossAxisAlignment crossAxisAlignment;
LinearLayout({
Key key,
this.orientation,
this.isVisible = true,
this.background,
this.padding,
this.margin,
this.children = const <Widget>[],
this.mainAxisAlignment = MainAxisAlignment.start,
this.mainAxisSize = MainAxisSize.min,
this.crossAxisAlignment = CrossAxisAlignment.center,
}) : super(key: key);
@override
LinearLayoutState createState() {
return LinearLayoutState();
}
}
class LinearLayoutState extends State<LinearLayout> {
bool _isVisible = true;
@override
void initState() {
_isVisible = widget.isVisible;
super.initState();
}
@override
Widget build(BuildContext context) {
return isNotNull(_isVisible)
? Offstage(
offstage: !_isVisible,
child: _buildLayoutWidget(),
)
: _buildLayoutWidget();
}
Widget _buildLayoutWidget() {
if (_isNeedContainerWidget()) {
return _buildContainerWidget();
} else {
return _buildOrientationWidget();
}
}
bool _isNeedContainerWidget() {
return isNotNull(widget.background) ||
isNotNull(widget.padding) ||
isNotNull(widget.margin);
}
Widget _buildContainerWidget() {
return Container(
decoration: widget.background,
padding: widget.padding,
margin: widget.margin,
child: _buildOrientationWidget(),
);
}
Widget _buildOrientationWidget() {
if (widget.orientation == LayoutOrientation.horizontal) {
return _buildHorizontalWidget();
} else {
return _buildVerticalWidget();
}
}
Widget _buildVerticalWidget() {
return Column(
mainAxisSize: widget.mainAxisSize,
mainAxisAlignment: widget.mainAxisAlignment,
crossAxisAlignment: widget.crossAxisAlignment,
children: widget.children,
);
}
Widget _buildHorizontalWidget() {
return Row(
mainAxisSize: widget.mainAxisSize,
mainAxisAlignment: widget.mainAxisAlignment,
crossAxisAlignment: widget.crossAxisAlignment,
children: widget.children,
);
}
bool isVisible() {
return _isVisible;
}
void setVisible(bool isVisible) {
setState(() {
_isVisible = isVisible;
});
}
}
package:flutter_library/common/util.dart文件代码如下:1
2
3
4
5
6
7bool isNull(dynamic obj) {
return obj == null;
}
bool isNotNull(dynamic obj) {
return obj != null;
}
LinearLayout使用
1 | class LinearLayoutSampleWidget extends StatefulWidget { |
这里重点说一下Demo中的GlobalKey<LinearLayoutState> _key = GlobalKey<LinearLayoutState>()
这段代码,这个就是用来给LinearLayout
设定一个唯一标识符,这样才能在后面点击按钮的时候调用setVisible
方法来显示和隐藏。而泛型LinearLayoutState
则是我封装的代码中的一个类,因为我的setVisible
方法暴露在此State中。
原创文章,转载请出处注明。
下面是我的个人公众号,欢迎关注交流