Nealyang/PersonalBlog

项目框架搭建

Nealyang opened this issue · 0 comments

准备工作

笔者 Flutter 版本及环境信息:Channel beta, v0.11.9, on Mac OS X 10.14.1 18B75

版本更新向前兼容,笔者更新版本后,项目依旧运行如初。目前笔者的flutter版本信息为:

    Flutter 1.0.0 • channel beta • https://github.com/flutter/flutter.git
    Framework • revision 5391447fae (5 days ago) • 2018-11-29 19:41:26 -0800
    Engine • revision 7375a0f414
    Tools • Dart 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)

img

由于我们做App,并不会1:1模仿,而是要符合App的使用规范,所以这里,我们将不同的栏目作为bootomBar。

这里我们先起一个flutter项目,命名为flutter_juejin

建立如下目录文件:

img

后面我们的目录大致修改为:

IMAGE

定义每一个页面class

  • pages/activityPage.dart
  import 'package:flutter/material.dart';
  
  class ActivityPage extends StatefulWidget {
    _ActivityPageState createState() => _ActivityPageState();
  }
  
  class _ActivityPageState extends State<ActivityPage> {
    @override
    Widget build(BuildContext context) {
      return Container(
         child: Text('活动'),
      );
    }
  }
  • pages/bookPage.dart
  import 'package:flutter/material.dart';
  
  class BookPage extends StatefulWidget {
    _BookPageState createState() => _BookPageState();
  }
  
  class _BookPageState extends State<BookPage> {
    @override
    Widget build(BuildContext context) {
      return  new DefaultTabController(
          length: 3,
          child: new Scaffold(
            appBar: new AppBar(
              backgroundColor: Colors.orangeAccent,
              title: new TabBar(
                tabs: [
                  new Tab(
                    child:new Column(
                      children:<Widget>[
                        new Icon(Icons.directions_car),
                        new Text('Car')
                      ]
                    )
                  ),
                  new Tab(
                    child:new Column(
                      children:<Widget>[
                        new Icon(Icons.directions_transit),
                        new Text('transit')
                      ]
                    )
                  ),
                  new Tab(
                    child:new Column(
                      children:<Widget>[
                        new Icon(Icons.directions_bike),
                        new Text('bike')
                      ]
                    )
                  ),
                ],
                indicatorColor: Colors.white,
              ),
            ),
            body: new TabBarView(
              children: [
                new Icon(Icons.directions_car),
                new Icon(Icons.directions_transit),
                new Icon(Icons.directions_bike),
              ],
            ),
          ),
        )
      ;
    }
  }

由于小册页面会有一个tab,我们暂时先拟定一个tab界面,后面再修改,你也可以暂时先像activityPage那样写个text上去

  • pages/indexPage.dart
  import 'package:flutter/material.dart';
  
  
   class IndexPage extends StatefulWidget {
     _IndexPageState createState() => _IndexPageState();
   }
   
   class _IndexPageState extends State<IndexPage> {
     @override
     Widget build(BuildContext context) {
       return Container(
          child: Text('IndexPage'),
       );
     }
   }
  • pages/pinsPage.dart
  import 'package:flutter/material.dart';
  
    class PinsPage extends StatefulWidget {
      _PinsPageState createState() => _PinsPageState();
    }
    
    class _PinsPageState extends State<PinsPage> {
      @override
      Widget build(BuildContext context) {
        return Container(
           child: Text('沸点'),
        );
      }
    }
  • pages/reposPage.dart
  import 'package:flutter/material.dart';
  
  class ReposPage extends StatefulWidget {
    _ReposPageState createState() => _ReposPageState();
  }
  
  class _ReposPageState extends State<ReposPage> {
    @override
    Widget build(BuildContext context) {
      return Container(
         child: Text('开源库'),
      );
    }
  }

然后我们在pages/myApp.dart中定义一个class,引入到main.dart中

  • pages/mian.dart
  import 'package:flutter/material.dart';
  import './pages/myApp.dart';
  
  void main() => runApp(MyApp());

编写入口文件 myApp.dart

  • pages/myApp.dart

为了方面后面扩展,我们这里使用StatefulWidget

  class MyApp extends StatefulWidget {
    _MyAppState createState() => _MyAppState();
  }
  class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
    
  }

在 State中,我们定义如下:

    final TextStyle tabTextStyleNormal =
        TextStyle(color: const Color(0xffdddddd));
    final TextStyle tabTextStyleSelected =
        TextStyle(color: const Color(0xff4d91fd));
    // 底部bar
    final List<Tab> _bottomTabs = <Tab>[
      Tab(
        text: '首页',
        icon: Icon(Icons.home),
      ),
      Tab(
        text: '沸点',
        icon: Icon(Icons.chat),
      ),
      Tab(
        text: '小册',
        icon: Icon(Icons.book),
      ),
      Tab(
        text: '开源库',
        icon: Icon(Icons.bubble_chart),
      ),
      Tab(
        text: '活动',
        icon: Icon(Icons.local_activity),
      ),
    ];
    var _body;
    List _appBarTitles = ['首页', '沸点', '小册', '开源库', '活动'];

上面定义了一些我们页面会使用到的一个变量,当然,页面顶部需要引入我们之前写好的一些页面

  import 'package:flutter/material.dart';
  
  import './indexPage.dart';
  import './pinsPage.dart';
  import './bookPage.dart';
  import './reposPage.dart';
  import './activityPage.dart';

bottomNavigationBar中我们需要使用TabBar,所以在定义变量的时候,别忘记了加一个Controller

这里说一下一个VSCode的小技巧,当鼠标悬停到Widget的时候,我们可以看到这个Widget都有哪些属性,
img

Controller其实也可以说不需要,因为他的作用就是定义底部bar的长度,加上它后,我们可以通过setState来改变底部的菜单按钮,更多的使用介绍,大家可以查看Flutter的api。

顺便说下对于必须的属性,编译器会给我们对应的提示的。后面我们会遇到。

这里我们添加Controller (万一后面我们会改变底部bar的长度呢,当然,能用StatelessWidget的最好用StatelessWidget,性能,你懂得)

  TabController _tabController;
  
  @override
    void initState() {
      // TODO: implement initState
      super.initState();
      _tabController =
          new TabController(vsync: this, length: _bottomTabs.length);
    }
  
    @override
    void dispose() {
      _tabController.dispose();
      super.dispose();
    }

基本准备工作都有了,然后我们来写我们的build方法吧

  @override
    Widget build(BuildContext context) {
      return Container(
        child: MaterialApp(
          theme: ThemeData(primaryColor: const Color.fromRGBO(77, 145, 253, 1.0)),
          home: Scaffold(
            appBar: AppBar(
              title: Text('Title'),
            ),
            body: TabBarView(
              controller: _tabController,
              children: <Widget>[
                IndexPage(),
                PinsPage(),
                BookPage(),
                ReposPage(),
                ActivityPage()
              ],
            ),
            bottomNavigationBar: new Material(
              color: Theme.of(context).primaryColor,
              child: TabBar(
                tabs: _bottomTabs,
                controller: _tabController,
                indicatorColor: Colors.white,
              ),
            ),
          ),
        ),
      );
    }

Scaffold 是Material提供的一个类似HTML的架构,其中包括header、body差不多

这次,我们app的基础结构就都已经搭建起来了。后面需要调整的时候我们再做相应调整,包括项目的目录结构后面肯定会调整的。

img

后面会介绍目录部分的跳转和添加

总结

这一节中,你应该学会如何

  • 定义新页面
  • 顶部tab
  • bottomNavigationBar
  • VSCode的一些使用技巧

这一节中,鼓励大家自己敲代码,代码地址将在下一节中给出。