ExpansionTile其实就是一个有标题可以展开的控件
ExpansionTile({
Key key,
this.leading,//在文字前面的Widget
@required this.title,//文字
this.backgroundColor,//背景
this.onExpansionChanged,//展开或者关闭的监听
this.children = const [],//孩子
this.trailing,//右侧图标
this.initiallyExpanded = false,//默认是否展开
})
ExpansionTile的很多属性都跟ListTitle类似,它内部就是使用ListTitle实现的,感兴趣的小伙伴可以去看下源码。
下面看一下demo核心 code:
构造你展开时你想要展示的widget数据
final List lzData = [
BanchItem(
title: '待接单',
imgName: 'assets/images/待接单.png',
number: 7,
),
BanchItem(
title: '跟进中',
imgName: 'assets/images/待接单.png',
number: 0,
),
BanchItem(
title: '留资查询',
imgName: 'assets/images/待接单.png',
number: 0,
),
BanchItem(
title: '拉新邀请',
imgName: 'assets/images/待接单.png',
number: 0,
),
];
Container(
margin: EdgeInsets.fromLTRB(10, 10, 10, 0),
child: ExpansionTile(
backgroundColor: Colors.white,
title: new Text(
'留资单',
style: new TextStyle(
color: Color(0xFF333333),
fontSize: 18,
),
),
trailing: Image.asset('assets/images/收起.png'),
initiallyExpanded: true,
children: [
Wrap(
runSpacing: 10,
spacing: 10,
runAlignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start,
children: lzData,
),
Container(
height: 20,
)
],
),
),
效果如下 默认展开:
效果还不错,但是会发现右侧的箭头并没有像默认的trailing那样会随着ExpansionTile的展开和关闭来做变换。这里需要我们自己处理一下箭头的变换动画。
动画核心code:
Animation animation;
AnimationController animationController;
@override
void initState() {
// TODO: implement initState
super.initState();
animationController = new AnimationController(
vsync: this, duration: Duration(milliseconds: 200));
animation = new Tween(begin: 0.0, end: 0.5).animate(animationController);
}
_changeTrailing(bool expand) {
setState(() {
if (expand) {
animationController.reverse();
} else {
animationController.forward();
}
});
}
把trailing改为RotationTransition 并添加onExpansionChanged 展开收起的回调方法:
trailing: RotationTransition(
turns: animation,
child: Image.asset('assets/images/收起.png'),
),
onExpansionChanged: (expand) {
_changeTrailing(expand);
},
到此 一个展开收起的控件就完美实现了,但是处理ExpansionTile,还有一个和他功能类似的控件ExpansionPanelList
ExpansionPanelList({
Key key,
this.children = const [],
this.expansionCallback,//展开关闭回调
this.animationDuration = kThemeAnimationDuration,//展开进行时间
})
ExpansionPanel({
@required this.headerBuilder,//标题构造器
@required this.body,//内容区域
this.isExpanded = false//是否展开
})
基本使用也很简单,这里主要说一下注意事项:
1.headerBuilder不能自定义trailing ,或者说右侧他有一个写死的箭头 我们是没办法换成自己的图片的
2.isExpanded需要手动设置,默认不会在点击header的时候改变 ,所以expansionCallback不实现的时候 点击是没效果的 这与RotationTransition不同
下面是一段使用的核心code:
Container(
margin: EdgeInsets.fromLTRB(10, 10, 10, 0),
child: ExpansionPanelList(
expansionCallback: (index, expand) {
setState(() {
orderExpand = !orderExpand;
});
},
children: [
ExpansionPanel(
isExpanded: orderExpand,
headerBuilder: (context, expand) {
return ListTile(
title: new Text(
'订单',
style: new TextStyle(
color: Color(0xFF333333),
fontSize: 18,
),
),
//不支持自定义右侧icon
// trailing: RotationTransition(
// turns: animation,
// child: Image.asset('assets/images/收起.png'),
// ),
);
},
body: Column(
children: [
Wrap(
runSpacing: 10,
spacing: 10,
runAlignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start,
children: orderData,
),
Container(
height: 20,
)
],
))
],
))