在前面的文章红我们学习了Chip的用法,使用Chip可以很方便的完成对想要的东西打上想要的标签。在文章的最后让大家实现如下的效果
其实实现起来非常的简单,使用随机的颜色和随机的图标来完成Wrap的布局,代码非常的简单。
代码:
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final List<MyChip> listData = [];
final List<Icon> icons = [];
Color _randomColor() {
var red = Random.secure().nextInt(255);
var greed = Random.secure().nextInt(255);
var blue = Random.secure().nextInt(255);
return Color.fromARGB(255, red, greed, blue);
}
@override
void initState() {
super.initState();
icons.add(Icon(Icons.delete_forever, color: _randomColor()));
icons.add(Icon(Icons.message, color: _randomColor()));
icons.add(Icon(Icons.print, color: _randomColor()));
icons.add(Icon(Icons.add, color: _randomColor()));
icons.add(Icon(Icons.security, color: _randomColor()));
icons.add(Icon(Icons.cake, color: _randomColor()));
icons.add(Icon(Icons.http, color: _randomColor()));
icons.add(Icon(Icons.location_city, color: _randomColor()));
icons.add(Icon(Icons.apps, color: _randomColor()));
for (int i = 0; i < 20; i++) {
listData.add(new MyChip("add$i", _randomColor(),
icons[Random.secure().nextInt(icons.length)], _removeChip));
}
}
void _removeChip(MyChip chip) {
setState(() {
listData.remove(chip);
});
}
void _addChip(MyChip chip) {
setState(() {
listData.add(chip);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Chip"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.add),
onPressed: () {
_addChip(MyChip("add", _randomColor(),
icons[Random.secure().nextInt(icons.length)], _removeChip));
})
],
),
body: Wrap(
spacing: 5.0,
runSpacing: 5.0,
children: listData,
),
);
}
}
class MyChip extends StatelessWidget {
final tipText;
final color;
final avatar;
var callback;
MyChip(this.tipText, this.color, this.avatar, this.callback);
@override
Widget build(BuildContext context) {
return Chip(
label: Text(tipText),
onDeleted: () {
callback(this);
},
avatar: avatar,
labelStyle: TextStyle(
color: color,
),
deleteIconColor: color,
deleteButtonTooltipMessage: "删除该条",
);
}
}
在今天的文章中我们来看下ExpansionTile的使用。
ExpansionTile是什么东西?其实就是一个有标题可以展开的控件而已,其他就跟其他的layout没有很大的差别了。
构造方法:
代码:
ExpansionTile({
Key key,
this.leading,//和ListTitle类似,在文字前面的Widget
@required this.title,//和ListTitle类似,文字
this.backgroundColor,//背景
this.onExpansionChanged,//展开或者关闭的监听
this.children = const <Widget>[],//内部孩子
this.trailing,//和ListTitle类似,右侧图标
this.initiallyExpanded = false,//默认是否展开
})
ExpansionTile的构造方法可以说也是足够的简单,哈。
为什么说ExpansionTile的很多属性都跟ListTitle类似啊?那是因为它内部就是使用ListTitle实现的啊,感兴趣的小伙伴可以去看下源码哈。
接下来还是来看个简单的例子吧
代码:
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ExpansionTile')),
body: ListView(children: <Widget>[
ExpansionTile(title: const Text('更多精彩'), children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3.0),
color: Colors.blueAccent,
),
height: 100.0,
margin: EdgeInsets.all(5.0),
),
])
]));
}
}
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
在上面的代码中,我们仅仅定义ExpansionTile的title和children两个属性,children我们仅仅放了一个高度为100的Container。
看下效果:
当然,我们可以给ExpansionTil设置背景颜色,并设置默认展开
backgroundColor: Colors.blueAccent.withOpacity(0.1), initiallyExpanded: true,
当然,我们也可以给ExpansionTile设置一个leading或者修改右侧展开关闭图标
leading: Icon(Icons.whatshot,color: Colors.redAccent,), trailing: Icon(Icons.chevron_right),
可以看到我们在文字的左侧放置了一个“火”的图标,把文字的右侧的图标改成了一个向右的小箭头,效果还不错,但是细心的小伙伴会发现右侧的箭头并没有像默认的trailing那样会随着ExpansionTile的展开和关闭来做变换。
所以这里我们就需要借助于我们前面讲到的动画的知识了,借助于RotationTransition和ExpansionTile的onExpansionChanged事件我们可以很轻松的实现我们想要的变换效果。
一起来看下:
代码:
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
Animation animation;
AnimationController animationController;
@override
void initState() {
super.initState();
animationController = new AnimationController(
vsync: this, duration: Duration(milliseconds: 200));
animation = new Tween(begin: 0.0, end: 0.5).animate(animationController);
}
_changeOpacity(bool expand) {
setState(() {
if (expand) {
animationController.forward();
} else {
animationController.reverse();
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ExpansionTile')),
body: ListView(children: <Widget>[
ExpansionTile(
title: const Text('更多精彩'),
backgroundColor: Colors.blueAccent.withOpacity(0.1),
initiallyExpanded: true,
leading: Icon(
Icons.whatshot,
color: Colors.redAccent,
),
trailing: RotationTransition(
turns: animation,
child: const Icon(Icons.chevron_right),
),
onExpansionChanged: (bool){
_changeOpacity(bool);
},
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3.0),
color: Colors.blueAccent),
height: 100.0,
margin: EdgeInsets.all(5.0),
),
])
]));
}
}
效果如下:
当然,我在这里仅仅是为了演示,界面就这样子哈,大家可以根据自己的需要来定制自己的界面。
根据讲到的知识完成如下效果(注意图标颜色变化)