Flutter组件----ExpansionTile

ExpansionTile是什么?

ExpansionTile其实就是一个类似于有一个标题可以展开的控件而已,就好比我们选择一个Title他就可以展开一些属于他的东西。例如我们点击一个服务,它会在下面展开一些服务的子项目。

我们看ExpansionTile的签名函数即构造函数

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的构造函数,我们可以看出他的某些参数的用处。(其实跟ListTitle的点击事件也是有点相通的,有兴趣的可以去源码看一下)。

刚开始

点击之后

不放gif了,至于过程脑洞自补。

代码如下:

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({Key key, this.title}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title:Text("ExpansionTileDemo"),
      ),
      body: ListView(
        children: <Widget>[
          ExpansionTile(
            title: Text("服务"),
            children: <Widget>[
              ListTile(title: Text("子服务1"),),
              ListTile(title: Text("子服务2"),),
              ListTile(title: Text("子服务3"),),
              ListTile(title: Text("子服务4"),),
            ],
          ),
        ],
      ),
    );
  }
}

还有别的参数,有兴趣的可以自己去试试,不过常用的就是backgroundColor:(背景颜色) Colors.blueAccent.withOpacity(0.1),initiallyExpanded: true,(自动展开) 还有leading和trailing属性,应该很熟了,他是左边和右边可以设置Widget。

但是有点细心的朋友会发现,点开之后的按钮从朝下,变成了朝上,这样我们就要使用动画的知识去改变了(后面补)。发现是旋转,那么就会用到相关的旋转函数RotationTransition,至于图片我就不放了,因为就是右边按钮的样式换了。

代码如下:

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({Key key, this.title}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin{

  Animation animation;
  AnimationController animationController;

  @override
  void initState() {
    super.initState();
    animationController = new AnimationController(
      vsync: this,  //用这个方法必须实现接口TickerProviderStateMixin --别问为什么就是这样写....想知道的去看底层源码
      duration: Duration(milliseconds: 200)  //延迟、延时
    );
    animation = new Tween(begin: 0.0,end: 0.25).animate(animationController);  //这里最大是1  而0.25是为了  0.25*360=90,刚好旋转90°
  }

  _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: Text('服务'),
                  backgroundColor: Colors.blueAccent.withOpacity(0.5),
                  initiallyExpanded: true,
                  leading: Icon(
                    Icons.person,
                    color: Colors.redAccent,
                  ),
                  trailing: RotationTransition(
                    turns: animation,
                    child: const Icon(Icons.chevron_right),
                  ),
                  onExpansionChanged: (bool) {
                    _changeOpacity(bool);
                  },
                  children: <Widget>[

                    ListTile(title: Text('子服务1'),),
                    ListTile(title: Text('子服务2'),),
                    ListTile(title: Text('子服务3'),),
                    ListTile(title: Text('子服务4'),),

                  ]
              )
            ]
        )
    );
  }
}


这就是转变之后的了。

我写的应该是有问题的,因为最好还是要加一下释放!

@override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    animationController.dispose();
  }
  • 虽说你加不加看不出什么结果,但是如果你的项目大了,它会变得慢!

版权声明:本文为mubowen666原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。