前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Flutter Widget]ExpansionTile

[Flutter Widget]ExpansionTile

作者头像
flyou
发布2018-10-16 11:03:40
2.1K0
发布2018-10-16 11:03:40
举报
文章被收录于专栏:flutter开发者flutter开发者

前言


在前面的文章红我们学习了Chip的用法,使用Chip可以很方便的完成对想要的东西打上想要的标签。在文章的最后让大家实现如下的效果

其实实现起来非常的简单,使用随机的颜色和随机的图标来完成Wrap的布局,代码非常的简单。

代码:


代码语言:javascript
复制
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没有很大的差别了。

构造方法:

代码:


代码语言:javascript
复制
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实现的啊,感兴趣的小伙伴可以去看下源码哈。

接下来还是来看个简单的例子吧

代码语言:javascript
复制
代码:

代码语言:javascript
复制
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事件我们可以很轻松的实现我们想要的变换效果。

一起来看下:

代码语言:javascript
复制
代码:

代码语言:javascript
复制
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标识的定制

试一试


根据讲到的知识完成如下效果(注意图标颜色变化)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 flutter开发者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • ExpansionTile
  • 小结
  • 试一试
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档