Flutter实现滑动头部折叠切换tab

Flutter实现滑动头部折叠切换tab

主要使用到NestedScrollView和SliverAppBar
先看效果:

www.zeeklog.com  - Flutter实现滑动头部折叠切换tab

代码如下:

import 'package:flutter/material.dart';

class ActPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new ActState();
  }
}

class ActState extends State<ActPage> with SingleTickerProviderStateMixin {
  List<Choice> tabs = [];
  TabController mTabController;
  int mCurrentPosition = 0;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: NestedScrollView(headerSliverBuilder: (BuildContext context,
          bool innerBoxIsScrolled) {
        return [new SliverAppBar(
          pinned: true,
          expandedHeight: 220.0,
          bottom: PreferredSize(
              child: new Container(
                color: Colors.white,
                child: new TabBar(
                  indicatorSize: TabBarIndicatorSize.label,
                  indicatorColor: Colors.green,
                  labelColor: Colors.green,
                  unselectedLabelColor: Colors.black45,
                  tabs: tabs.map((Choice choice) {
                    return new Tab(
                      text: choice.title,
                      icon: new Icon(choice.icon,),
                    );
                  }).toList(),
                  controller: mTabController,
                ),
              ),
              preferredSize: new Size(double.infinity, 18.0)
          ),
          flexibleSpace: new Container(
            child: new Column(
              children: <Widget>[
                new Expanded(
                  child: new Container(
                    child: Image.asset(
                      "images/temp2.jpg",
                      fit: BoxFit.cover,
                    ),
                    width: double.infinity,
                  ),
                )
              ],
            ),
          ),
        )
        ];
      },
        body: new TabBarView(children: tabs.map((Choice choice) {
          return new Padding(
              padding: const EdgeInsets.all(15.0),
              child:choice.position==0?new Container(
                child: new ListView(
                    children: <Widget>[
                      new ListTile(
                        leading: new Icon(Icons.map),
                        title: new Text('Map'),
                      ),
                      new ListTile(
                        leading: new Icon(Icons.photo),
                        title: new Text('Album'),
                      ),
                      new ListTile(
                        leading: new Icon(Icons.phone),
                        title: new Text('Phone'),
                      ),
                      new ListTile(
                        leading: new Icon(Icons.map),
                        title: new Text('Map'),
                      ),
                      new ListTile(
                        leading: new Icon(Icons.photo),
                        title: new Text('Album'),
                      ),
                      new ListTile(
                        leading: new Icon(Icons.phone),
                        title: new Text('Phone'),
                      ),
                    ],
                )
              ):new Container(
                child: new Text("ahhhhhhhhhhhhh"),
              )
          );
        }).toList(),
          controller: mTabController,
        ),
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    tabs.add(Choice(title: '热门', icon: Icons.hot_tub, position: 0));
    tabs.add(Choice(title: '最新', icon: Icons.fiber_new, position: 1));
    mTabController = new TabController(vsync: this, length: tabs.length);
    //判断TabBar是否切换
    mTabController.addListener(() {
      if (mTabController.indexIsChanging) {
        setState(() {
          mCurrentPosition = mTabController.index;
        });
      }
    });
  }

  @override
  void dispose() {
    super.dispose();
    mTabController.dispose();
  }
}

class Choice {
  const Choice({ this.title, this.icon, this.position});
  final String title;
  final int position;
  final IconData icon;
}