美文网首页
flutter底部bottomNavigationBar+Pag

flutter底部bottomNavigationBar+Pag

作者: eliteTyc | 来源:发表于2019-07-24 16:23 被阅读0次

    上图

    AEB9E959-B62A-405E-BA60-DD9759B0A1A9.png

    需要实现的功能:

    • 底部tab(可自定义样式)点击切换中间内容
    • 不要一般的tab切换时相隔几个页面会缓慢过渡的问题(一般bottomNavigationBar+TabBarView实现会存在的问题)
    • 中间内容不可滑动
    • 切换页面时页面不重建

    实现过程

    1. 一个Scaffold+bottomNavigationBar+pageView
              Tab(child: _nowIndex==0?Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Image.asset("images/nav_home_h.png",width: 25,height: 25,fit: BoxFit.fill,),
                    Text("首页",style: TextStyle(decoration: TextDecoration.none,color: Colors.blue,fontSize: 14),)
                  ],
                ):Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Image.asset("images/nav_home.png",width: 25,height: 25,fit: BoxFit.fill,),
                    Text("首页",style: TextStyle(decoration: TextDecoration.none,color: Colors.grey,fontSize: 14),)
                  ],
                ),)
    

    可自定义tabbar样式就需要使用tab的child属性,使用_nowIndex记录当前页面切换到那一个页面了,然后使用三目运算符针对不同的页面赋值不同的child,flutter中都是一个个widget,所以tab的样式可以随心所欲,这里我只是实现了与使用tab的text和icon属性一样的效果
    2.一般使用bottomNavigationBar+TabBarView假设我们有4个页面,当前我们再第4个页面,然后我们点击tab切换到第一个页面,会出现一个效果就是一次从3切换到2再切换到1,虽然这个过程是很快的,但是也丢失了android原生的fragment切换效果,所以我们这里采用pageView来实现中间页面的展示。

    body: PageView(
            controller: _pageController,
            children: <Widget>[
              HomePageTab(),
              ThingsPageTab(),
              MePageTab()
            ],
    // 这里很重要就是需要实现的第三个要求
            physics: NeverScrollableScrollPhysics(),
          ),
    

    然后就是tabbar和pageview的控制器了,这一步就是将点击底部,同时也切换page连接起来。

    TabController _tabController;
      PageController _pageController;
      var _nowIndex =0;
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
    //创建页面的控制器
        _pageController = PageController();
    //创建底部tab的控制器,并且设置tab改变的监听
        _tabController = TabController(length: 3, vsync: this)..addListener((){
    // 当tab改变时,使用页面的controller跳转到指定的页面,这样就不会有依次切换的效果
          _pageController.jumpToPage(_tabController.index);
    // 使用setstate 设置数据记录当前切换到哪一个页面,自动重绘底部tab(响应式)
          setState(() {
            _nowIndex = _tabController.index;
          });
    
        });
      }
    

    3.这时候pageview还是能滑动切换的,如果需要在滑动切换后同时切换底部tab可以使用pageView的onChange属性,在onChange时同时响应式设置 _nowIndex的值,就可以达到同步,但是这里我选择直接禁用pageView的滑动,就是使用pageview的''physics: NeverScrollableScrollPhysics(),''这个属性就可以设置不可以滑动切换,请看第2点的第一段代码
    4.接下来就是点击底部tab切换时,每一次页面都会新建和销毁,就好像android原生的fragment的replace方法,在android原生中我们使用hide和show的方式来防止重建,那么我们再flutter中如何实现呢,就是在每一个子页面的state类后面混合AutomaticKeepAliveClientMixin

    class ThingsPageTab extends StatefulWidget {
      @override
      _ThingsPageTabState createState() => _ThingsPageTabState();
    }
    // 1.防止重建加with AutomaticKeepAliveClientMixin
    class _ThingsPageTabState extends State<ThingsPageTab> with AutomaticKeepAliveClientMixin{
      @override
      Widget build(BuildContext context) {
        return Text("things",style: TextStyle(fontSize: 50),);
      }
    
    // 2.防止重建必须要的实现 返回true
      @override
      // TODO: implement wantKeepAlive
      bool get wantKeepAlive => true;
    }
    
    

    完结

    • 这样整个功能就实现了,贴主页完整的代码
    import 'package:flutter/material.dart';
    import 'package:jygonline/ui/fragment/home_page.dart';
    import 'package:jygonline/ui/fragment/things_page.dart';
    import 'package:jygonline/ui/fragment/me_page.dart';
    
    
    class MainPage extends StatefulWidget {
      @override
      _MainPageState createState() => _MainPageState();
    }
    
    class _MainPageState extends State<MainPage> with SingleTickerProviderStateMixin{
      TabController _tabController;
      PageController _pageController;
      var _nowIndex =0;
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        _pageController = PageController();
        _tabController = TabController(length: 3, vsync: this)..addListener((){
          _pageController.jumpToPage(_tabController.index);
          setState(() {
            _nowIndex = _tabController.index;
          });
    
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            bottomNavigationBar: Container(
              height: 60,
              color: Colors.white,
              child: TabBar(tabs: [
    
                Tab(child: _nowIndex==0?Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Image.asset("images/nav_home_h.png",width: 25,height: 25,fit: BoxFit.fill,),
                    Text("首页",style: TextStyle(decoration: TextDecoration.none,color: Colors.blue,fontSize: 14),)
                  ],
                ):Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Image.asset("images/nav_home.png",width: 25,height: 25,fit: BoxFit.fill,),
                    Text("首页",style: TextStyle(decoration: TextDecoration.none,color: Colors.grey,fontSize: 14),)
                  ],
                ),),
                Tab(child: _nowIndex==1?Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Image.asset("images/nav_bs_h.png",width: 25,height: 25,fit: BoxFit.fill,),
                    Text("办事",style: TextStyle(decoration: TextDecoration.none,color: Colors.blue,fontSize: 14),)
                  ],
                ):Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Image.asset("images/nav_bs.png",width: 25,height: 25,fit: BoxFit.fill,),
                    Text("办事",style: TextStyle(decoration: TextDecoration.none,color: Colors.grey,fontSize: 14),)
                  ],
                ),),
                Tab(child: _nowIndex==2?Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Image.asset("images/nav_my_h.png",width: 25,height: 25,fit: BoxFit.fill,),
                    Text("个人中心",style: TextStyle(decoration: TextDecoration.none,color: Colors.blue,fontSize: 14),)
                  ],
                ):Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Image.asset("images/nav_my.png",width: 25,height: 25,fit: BoxFit.fill,),
                    Text("个人中心",style: TextStyle(decoration: TextDecoration.none,color: Colors.grey,fontSize: 14),)
                  ],
                ),),
    
              ],
                controller: _tabController,
                indicatorColor: Colors.white,
                isScrollable: false,
                indicatorWeight: 0.01,
              ),
            ),
          body: PageView(
            controller: _pageController,
            children: <Widget>[
              HomePageTab(),
              ThingsPageTab(),
              MePageTab()
            ],
            physics: NeverScrollableScrollPhysics(),
          ),
        );
      }
    }
    
    

    相关文章

      网友评论

          本文标题:flutter底部bottomNavigationBar+Pag

          本文链接:https://www.haomeiwen.com/subject/ivnxrctx.html