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
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), ), ]) ])); } }
效果如下:
当然,我在这里仅仅是为了演示,界面就这样子哈,大家可以根据自己的需要来定制自己的界面。
小结
- 使用ExpansionTile可以很轻松的实现界面View展开效果
- 使用动画可以完成自己对trailing标识的定制
试一试
根据讲到的知识完成如下效果(注意图标颜色变化)