Flutter 一切谐为组件!
本篇主要介绍以下几个组件:
- Card - 卡片组件
- CheckBox - 组件
- Chip - 标签组件
- Dialog - 对话框组件
- Grid - 网格组件
- Icon - 图标组件
- Image - 图片组件
- Input - TextField 组件
- Layout - 布局组件
- List - 列表组件
一、Card - 卡片组件
卡片可以做联系人,地址信息等,带有介绍性质的组件。
class DemoPageState extends State<DemoPage> {
@override
Widget build(BuildContext context) {
return Center(
child: Card(
//背景色
color: Colors.green,
//卡片的z坐标 阴影的大小
elevation: 10.0,
//外边距
margin: EdgeInsets.all(20.0),
//卡片边框样式
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
//卡片的具体内容
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: Icon(Icons.shopping_cart),
title: Text(
'苹果电脑MacBookPro',
style: TextStyle(
color: Colors.white,
fontSize: 32.0,
),
),
subtitle: Text(
'配置为16核 8G内存',
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
contentPadding: EdgeInsets.all(20.0),
),
//添加两个按钮
ButtonTheme.bar(
child: ButtonBar(
children: <Widget>[
FlatButton(
child: Text('购买',style: TextStyle(color: Colors.black,fontSize: 18.0),),
onPressed: (){},
),
FlatButton(
child: Text('取消',style: TextStyle(color: Colors.black,fontSize: 18.0),),
onPressed: (){},
),
],
),
),
],
),
),
);
}
}
二、CheckBox - 组件
复选框,允许用户从一组中选择多个选项。
2.1 CheckboxListTile
child: CheckboxListTile(
value: _value,
//默认文字是否高亮
selected: true,
onChanged: _valueChanged,
dense: false,
//文字是否对齐 图标高度
isThreeLine: false,
//文字是否三行显示
title: Text('整个内容'),
// 将控件放在何处相对于文本,leading 按钮显示在文字前面,platform,trailing 按钮显示在文字后面
controlAffinity: ListTileControlAffinity.platform,
subtitle: Text('勾选下列选项'),
secondary: Icon(Icons.archive),//左侧小图标
activeColor: Colors.red,
),
2.2 CheckBox
复选框
Checkbox(
//激活时的颜色
activeColor: Colors.red,
//是否被选中
value: 0 == currentIndex,
//如果tristate的值为true 那个value的值可能为true false null
tristate: false,
//值发生变化
onChanged: (bool check){
setState(() {
if(check){
currentIndex = 0;
}
});
},
),
三、Chip - 标签组件
标签,一个 Material widget,它可以将一个复杂内容实体展现在一个小块中,如联系人。
- Chip
- ActionChip
- FilterChip
- ChoiceChip
Chip(
label: Text('Flutter'),
//背景色
backgroundColor: Colors.orange,
),
Chip(
label: Text('Flutter'),
//头部
avatar: CircleAvatar(
backgroundColor: Colors.green,
child: Text('Flutter'),
),
),
四、Dialog - 对话框组件
Dialog 的主要作用:提示类、做交互
- AlertDialog //一个会中断用户操作的对话款,需要用户确认
- SimpleDialog //简单对话框可以显示附加的提示或操作
//打开AboutDialog,介绍之类的
void showAboutDialog(BuildContext context) {
//调用方法
showDialog(
context: context,
//构造器
builder: (_) => new AboutDialog(
applicationName: 'AndroidStudio',
applicationIcon: Icon(Icons.apps),
applicationVersion: 'V3.1.2',
children: <Widget>[Text('这是AndroidStudio')],
));
}
//打开showSimpleDialog
void showSimpleDialog(BuildContext context) {
//调用方法
showDialog<Null>(
context: context,
//构造器
builder: (BuildContext context) => new SimpleDialog(
title: Text('选择'),
children: <Widget>[
//SimpleDialog选项
SimpleDialogOption(
child: Text('选项1'),
onPressed: (){
Navigator.of(context).pop();
},
),
SimpleDialogOption(
child: Text('选项2'),
onPressed: (){
Navigator.of(context).pop();
},
),
],
));
}
//AlertDialog
void showAlertDialog(BuildContext context) {
//调用方法
showDialog<void>(
context: context,
//构造器
builder: (BuildContext context) => new AlertDialog(
title: Text('标题'),
//内容
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
Text('较长的list...'),
],
),
),
//操作按钮
actions: <Widget>[
FlatButton(
child: Text('确定'),
onPressed: (){
Navigator.of(context).pop();
},
),
FlatButton(
child: Text('取消'),
onPressed: (){
Navigator.of(context).pop();
},
),
],
));
}
五、Grid - 网格组件
5.1 GridTitle
网格标题,网格里展示图片、文字、标题之类的组件。GridView
- GridTile
- GridTileBar
- GridPaper
//风格标题基本用法
GridTile(
header: Text('grid title'),
child: Image.asset('assets/cat.jpeg'),
footer: Text('grid footer'),
),
Image.asset('assets/cat.jpeg'),
GridTile(
//GridTile按钮
header: GridTileBar(
//标题
title: Text('header',style: TextStyle(color: Colors.red),),
//subtitle: Text('header',style: TextStyle(color: Colors.red),),
//前置图标
leading: Icon(Icons.print,color: Colors.green,),
),
child: Image.asset('assets/cat.jpeg',fit: BoxFit.cover,),
footer: GridTileBar(
//标题
title: Text('header',style: TextStyle(color: Colors.red),),
//subtitle: Text('header',style: TextStyle(color: Colors.red),),
//前置图标
leading: Icon(Icons.favorite,color: Colors.green,),
),
5.2 GridView
网格组件,是一个重要组件
几种创建方式:
_buildGridExtent //可以扩展的
_buildGridCount //指定列数
_buildGridSliver
_buildGridCustom
Widget _buildGridExtent() {
return GridView.extent(
//横轴的最大长度
maxCrossAxisExtent: 180.0,
//内边距
padding: EdgeInsets.all(4.0),
//垂直方向的间距
mainAxisSpacing: 4.0,
//水平方向的间距
crossAxisSpacing: 4.0,
children: _buildGridTitleList(30),
);
}
//创建指定列数的Grid
Widget _buildGridCount() {
return GridView.count(
//指定多少列
crossAxisCount: 4,
//内边距
padding: EdgeInsets.all(4.0),
//垂直方向的间距
mainAxisSpacing: 4.0,
//水平方向的间距
crossAxisSpacing: 4.0,
children: _buildGridTitleList(30),
);
}
//可懒加载的Grid 只有可见的部分加载
Widget _buildGridSliver() {
return CustomScrollView(
primary: false,
slivers: <Widget>[
SliverPadding(
padding: EdgeInsets.all(20.0),
sliver: SliverGrid.count(
crossAxisCount: 2,
crossAxisSpacing: 10.0,
children: _buildGridTitleList(30),
),
),
],
);
}
//SliverGridDelegateWithFixedCrossAxisCount可以指定列的个数的Grid
//SliverGridDelegateWithMaxCrossAxisExtent根据每个宽度自动计算的Grid
Widget _buildGridCustom() {
return GridView.custom(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 5,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
),
childrenDelegate: SliverChildBuilderDelegate(
(context, index) {
return Image.asset('assets/cat.jpeg');
},
childCount: 30,
),
);
}
List<Container> _buildGridTitleList(int count) {
return List.generate(
count,
(int index) => Container(
child: Image.asset('assets/cat.jpeg'),
));
}
六、Icon - 图标组件
6.1 Icon - 图标组件
//自带图标
Icon(
//图标
Icons.favorite,
//颜色
color: Colors.redAccent,
//大小
size: 48.0,
),
//图片Icon
ImageIcon(
AssetImage('assets/phone.png'),
color: Colors.green,
size: 48.0,
),
//可交互的Icon
IconButton(
icon: Icon(Icons.print),
onPressed: (){},
),
6.2 IconData - 字体图标
child: Column(children: <Widget>[
Icon(
IconData(
//code
0xe8ad,
//字体
fontFamily: 'MaterialIcons'),
color: Colors.redAccent,
),
Icon(
IconData(
//code
61447,
//字体
fontFamily: 'FontAwesome'),
color: Colors.green,
size: 68.0,
),
Icon(
IconData(
//code
61454,
//字体
fontFamily: 'FontAwesome'),
color: Colors.green,
size: 68.0,
),
]),
6.3 IconTheme - 图标主题
return Center(
//图标主题
child: IconTheme(
//图标主题数据
data: IconThemeData(
color: Colors.green,
//透明度
opacity: 0.5,
),
child: Row(
children: <Widget>[
Icon(
Icons.favorite_border,
size: 48.0,
),
Padding(
padding: EdgeInsets.all(20.0),
child: Text(
'喜欢',
style: TextStyle(fontSize: 44.0),
),
),
],
),
),
);
七、Image - 图片组件
一个显示图片的 widget。
7.1 AssetImage
资源图片
在资源配置文件中添加资源 pubspec.yaml
assets:
- assets/cat.jpeg
- assets/view.jpeg
- assets/flower.jpeg
- assets/flutter.png
child: CircleAvatar(
backgroundImage: AssetImage('assets/cat.jpeg'),
),
child: Image(
width: 300.0,
height: 300.0,
image: AssetImage('assets/view.jpeg'),
),
Image(
//可缩放的图片组件 scale值越大 图片越小
image: ExactAssetImage('assets/flutter.png',scale: 1.5,),
),
7.2 BoxDecoration - 装饰图片
//装饰器
decoration: BoxDecoration(
color: Colors.greenAccent,
//装饰图片
image: DecorationImage(
//使用资源图片
image: AssetImage(
'assets/flower.jpeg',
),
fit: BoxFit.contain,
//对齐方式
alignment: Alignment.center,
),
),
7.3 FileImage - 文件图片
class DemoPageState extends State<DemoPage> {
//图片文件
File _image;
//异步获取本地文件
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
});
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>[
Center(
child: _image == null
? Text('你还未选择任何图片')
//文件图片设置
: Image.file(
_image,
//缩放
scale: 0.5,
//填充模式
fit: BoxFit.cover,
)),
//选择图片动作
RaisedButton(
onPressed: getImage,
child: Text(
'点击选择图片',
style: TextStyle(color: Colors.white),
),
),
],
),
);
}
}
7.4 Image-图片组件
children: <Widget>[
//资源图片 可添加缩放值
Image.asset('assets/flower.jpeg',scale: 2.5,),
//网络图片 可添加缩放值
Image.network(
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2756575517,833879878&fm=200&gp=0.jpg',
scale: 2.5,
),
//本地图片
//Image.file(file),
//控制图片大小
SizedBox(
width: 200.0,
height: 200.0,
child: Image.asset('assets/flower.jpeg',fit: BoxFit.cover,),
),
],
八、Input - TextField 组件
TextField 是最常用的文本输入 widget。默认情况下,TextField 有一个下划线装饰(decoration)。可以通过提供给 decoration 属性设置一个 InputDecoration 来添加一个标签、一个图标、提示文字和错误文本。 要完全删除装饰(包括下划线和为标签保留的空间),将 decoration 明确设置为空即可。
TextFormField 包裹一个 TextField 并将其集成在 Form 中。你要提供一个验证函数来检查用户的输入是否满足一定的约束(例如,一个电话号码)或当你想将 TextField 与其他 FormField 集成时,使用 TextFormField。
有两种获取用户输入的主要方法:
- 处理 onChanged回调
- 提供一个TextEditingController.
class LoginPageState extends State<LoginPage>{
//文本编辑控制器
TextEditingController usernameController = TextEditingController();
TextEditingController passwordController = TextEditingController();
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
TextField(
controller: usernameController,
//TextCapitalization.words 将每个单词的首字母大写
//TextCapitalization.sentences 将首字母大写
//TextCapitalization.characters 将所有字母大写
textCapitalization: TextCapitalization.characters,
//键盘类型
keyboardType: TextInputType.number,
decoration: InputDecoration(
//内容的内边距
contentPadding: EdgeInsets.all(10.0),
icon: Icon(Icons.person),
//提示文本
labelText: '请输入你的用户名',
helperText: '请输入注册的用户名',
),
//键盘插件按钮样式
textInputAction: TextInputAction.go,
//设置光标样式
// cursorColor: Colors.green,
// cursorRadius: Radius.circular(16.0),
// cursorWidth: 16.0,
),
TextField(
controller: passwordController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(10.0),
icon: Icon(Icons.lock),
labelText: '请输入密码',
),
obscureText: true,
),
RaisedButton(
onPressed: (){
loginCheck();
},
child: Text('登录'),
),
//decoration示例
// TextField(
// //带外边框的样式
// decoration: InputDecoration(
// border: OutlineInputBorder(),
// hintText: '请输入你的用户名',
// labelText: '用户名',
// prefixIcon: Icon(Icons.person),
// suffixIcon: Icon(Icons.print),
// ),
// ),
],
);
}
loginCheck(){
if(usernameController.text.length != 11){
print('请输入正确的手机号');
}
if(passwordController.text.length != 6){
print('请输入6位以上的密码');
}
}
}
九、Layout - 布局组件
9.1 Center-居中布局
相对居中布局,将其子 widget 居中显示在自身内部的 widget。
body:Center(
child: Container(
color: Colors.red,
width: 200.0,
height: 100.0,
child: Center(
child: Text(
'居中布局',
style: TextStyle(
fontSize: 36.0,
color: Colors.white,
),
),
),
),
),
9.2 Column - 垂直布局
在垂直方向上排列子widget的列表。
child: Column(
//mainAxisAlignment属性
//MainAxisAlignment.spaceEvenly/spaceAround/spaceBetween,
//spaceEvenly:将主轴方向空白区域均分,使得children之间空间相等,包括首尾children
//spaceAround:将主轴方向空白区域均分,使得children之间空间相等,但是首尾children的空白部分为一半
//spaceBetween:将主轴方向空白区域均分,使得children之间空间相等,但是首尾children靠近收尾,没有空细逢
//MainAxisAlignment.start/end/center,
//start:将children放置在主轴起点方向
//end:将children放置在主轴末尾方向
//center:将children放置在主轴中间方向
mainAxisAlignment: MainAxisAlignment.spaceBetween,
//CrossAxisAlignment 属性
//crossAxisAlignment: CrossAxisAlignment.center/end/start,即,根据设定的位置交叉对齐
//center/end/start: children在交叉轴上居中/末端/起点 对齐展示
//stretch:让children填满交叉轴方向
//baseline:在交叉轴方向,使得于这个baseline对齐,如果主轴是垂直的,那么这个值是当作开始
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
//色块
Container(
color: Colors.greenAccent,
width: 100.0,
height: 60.0,
),
//色块
Container(
color: Colors.greenAccent,
width: 100.0,
height: 60.0,
),
//色块
Container(
color: Colors.greenAccent,
width: 100.0,
height: 60.0,
),
//色块
Container(
color: Colors.greenAccent,
width: 100.0,
height: 60.0,
),
],
),
9.3 Row - 水平布局
在水平方向上排列子widget的列表。
child: Row(
//mainAxisAlignment属性
//MainAxisAlignment.spaceEvenly/spaceAround/spaceBetween,
//spaceEvenly:将主轴方向空白区域均分,使得children之间空间相等,包括首尾children
//spaceAround:将主轴方向空白区域均分,使得children之间空间相等,但是首尾children的空白部分为一半
//spaceBetween:将主轴方向空白区域均分,使得children之间空间相等,但是首尾children靠近收尾,没有空细逢
//MainAxisAlignment.start/end/center,
//start:将children放置在主轴起点方向
//end:将children放置在主轴末尾方向
//center:将children放置在主轴中间方向
mainAxisAlignment: MainAxisAlignment.spaceBetween,
//CrossAxisAlignment 属性
//crossAxisAlignment: CrossAxisAlignment.center/end/start,即,根据设定的位置交叉对齐
//center/end/start: children在交叉轴上居中/末端/起点 对齐展示
//stretch:让children填满交叉轴方向
//baseline:在交叉轴方向,使得于这个baseline对齐,如果主轴是垂直的,那么这个值是当作开始
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
//色块
Container(
color: Colors.orange,
width: 100.0,
height: 50.0,
),
//色块
Container(
color: Colors.orange,
width: 100.0,
height: 50.0,
),
//色块
Container(
color: Colors.orange,
width: 100.0,
height: 50.0,
),
],
),
十、List - 列表组件
10.1 ListBody - 列表组件
一个 widget,它沿着一个给定的轴,顺序排列它的子元素。 ListBody
class DemoPageState extends State<DemoPage> {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
//ListBody不常用,但可以和Cloumn Row及ListView结合使用即可
ListBody(
//对齐方式
mainAxis: Axis.vertical,
//内容是否反向
reverse: false,
children: <Widget>[
Container(
color: Colors.red,
width: 50.0,
height: 50.0,
child: Text('A',style: TextStyle(color: Colors.white),),
),
Container(
color: Colors.orange,
width: 50.0,
height: 100.0,
child: Text('B',style: TextStyle(color: Colors.white),),
),
Container(
color: Colors.blue,
width: 50.0,
height: 150.0,
child: Text('C',style: TextStyle(color: Colors.white),),
),
],
),
],
);
}
}
10.2 ListView - 滚动列表
ListView 在任何语言中,都是占居非常重要的位置,出现的频率也相当高。可滚动的列表控件,ListView 是最常用的滚动 widget,它在滚动方向上一个接一个地显示它的孩子。在纵轴上,孩子们被要求填充 ListView。
class DemoPageState extends State<DemoPage> {
@override
Widget build(BuildContext context) {
// //ListView基本用法
// return ListView(
// children: <Widget>[
// //列表项
// ListTile(
// leading: Icon(Icons.person),
// title: Text('A'),
// ),
// //列表分割线
// Divider(height: 10.0,color: Colors.grey,),
// ListTile(
// leading: Icon(Icons.print),
// title: Text('B'),
// ),
// Divider(height: 10.0,color: Colors.grey,),
// ListTile(
// leading: Icon(Icons.favorite_border),
// title: Text('C'),
// ),
// Divider(height: 10.0,color: Colors.grey,),
// ListTile(
// leading: Icon(Icons.lock),
// title: Text('C'),
// ),
// Divider(height: 10.0,color: Colors.grey,),
//
// ],
// );
// return SizedBox(
// height: 300.0,
// child: ListView.builder(
// //排列方向 垂直和水平
// scrollDirection: Axis.vertical,
// //列表项个数
// itemCount: 10,
// //确定每一个item的高度 会让item加载更加高效
// itemExtent: 50.0,
// //physics 滑动类型设置
// //这个属性几个滑动的选择
// // AlwaysScrollableScrollPhysics() 总是可以滑动
// // NeverScrollableScrollPhysics禁止滚动
// // BouncingScrollPhysics 内容超过一屏 上拉有回弹效果
// // ClampingScrollPhysics 包裹内容 不会有回弹
// //physics: AlwaysScrollableScrollPhysics(),
// // 这个属性的意思就是预加载的区域
// // 设置预加载的区域 cacheExtent 强制设置为了 0.0,从而关闭了“预加载”
// // controller:滑动监听,我们多用于上拉加载更多,通过监听滑动的距离来执行操作
// //在构造中默认是false primary为true时,controller滑动监听就不能使用了
// //primary:false ,
// // shrinkWrap child 高度会适配 item填充的内容的高度,我们非常的不希望child的高度固定,因为这样的话,
// // 如果里面的内容超出就会造成布局的溢出。
// //shrinkWrap: false,
// itemBuilder: (BuildContext context, int index) {
// return ListTile(
// title: Text("title $index"),
// //标题
// leading: Icon(Icons.favorite_border),
// //前置图标
// subtitle: Text("sub title $index"),
// //子标题
// trailing: Icon(Icons.arrow_forward),
// //后置图标
// isThreeLine: false,
// //是否显示三行
// contentPadding: EdgeInsets.all(10.0),
// //内边距
// enabled: true,
// //是否禁用
// onTap: () {
// print('点击了:$index');
// },
// onLongPress: () {
// print('长按了:$index');
// },
// selected: false,
// );
// }),
// );
// return SizedBox(
// height: 300.0,
//
// //带分割线的ListView
// child: ListView.separated(
// //排列方向 垂直和水平
// scrollDirection: Axis.vertical,
// //分割线构建器
// separatorBuilder: (BuildContext context, int index) => Divider(height: 1.0,color: Colors.grey,),
// //列表项个数
// itemCount: 100,
// itemBuilder: (BuildContext context, int index) {
// return ListTile(
// title: Text("title $index"),
// //标题
// leading: Icon(Icons.favorite_border),
// //前置图标
// subtitle: Text("sub title $index"),
// //子标题
// trailing: Icon(Icons.arrow_forward),
// //后置图标
// isThreeLine: false,
// //是否显示三行
// contentPadding: EdgeInsets.all(10.0),
// //内边距
// enabled: true,
// //是否禁用
// onTap: () {
// print('点击了:$index');
// },
// onLongPress: () {
// print('长按了:$index');
// },
// selected: false,
// );
// }),
// );
return SizedBox(
height: 300.0,
//自定义列表
child: ListView.custom(
scrollDirection: Axis.vertical,
//生成子项
childrenDelegate:
SliverChildBuilderDelegate((BuildContext context, int index) {
//自定义容器
return Container(
height: 50.0,
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: Text('item $index'),
);
}, childCount: 10),
),
);
}
}