flutter之從零開始搭建(一)之 BottomNavigationBar

codelang發表於2018-07-06

坐看不如實戰來的有效率,這幾天都在看flutter的一些佈局和特性,打算從零開始搭建一個應用,中間可能會因為一些原因斷了文章,但是會慢慢補上。

學移動端的套路:

在學習移動開發的時候,一般都是按照這幾個套路走,

  • 佈局UI,
  • 路由跳轉,
  • 網路請求,
  • 頁面與資料互動。

當然,接下來的一系列也是按照這個步驟走

效果

今天先來搭建一個基礎的佈局,在Android的首頁佈局中,大部分都是Fragment+TabBottom的形式,先來看下效果圖。

效果圖

image

開始搭建

main.dart 啟動的main.dart是啟動的介面,返回的主佈局是MainPage,然後去

import 'package:flutter/material.dart';
import 'package:codelang/MainPage.dart';
void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MainPage(),
    );
  }
}
複製程式碼

MainPage

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

import 'package:codelang/page/MsgPage.dart';
import 'package:codelang/page/HomePage.dart';
import 'package:codelang/page/ShopPage.dart';
import 'package:codelang/page/MyPage.dart';
import 'package:codelang/widget/Demo1.dart';


class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        debugShowCheckedModeBanner: false,
        routes: <String, WidgetBuilder>{
          "/Demo1": (BuildContext context) => new Demo1(),
        },
        home: new MainPageWidget());
  }
}

class MainPageWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new MainPageState();
  }
}
class MainPageState extends State<MainPageWidget> {
  int _tabIndex = 0;
  var tabImages;
  var appBarTitles = ['首頁', '商鋪', '訊息', '我的'];

  /*
   * 根據image路徑獲取圖片
   * 這個圖片的路徑需要在 pubspec.yaml 中去定義
   */
  Image getTabImage(path) {
    return new Image.asset(path, width: 20.0, height: 20.0);
  }

  /*
   * 根據索引獲得對應的normal或是press的icon
   */
  Image getTabIcon(int curIndex) {
    if (curIndex == _tabIndex) {
      return tabImages[curIndex][1];
    }
    return tabImages[curIndex][0];
  }
  /*
   * 獲取bottomTab的顏色和文字
   */
  Text getTabTitle(int curIndex) {
    if (curIndex == _tabIndex) {
      return new Text(appBarTitles[curIndex],
          style: new TextStyle(color: const Color(0xff63ca6c)));
    } else {
      return new Text(appBarTitles[curIndex],
          style: new TextStyle(color: const Color(0xff888888)));
    }
  }
  /*
   * 儲存的四個頁面,和Fragment一樣
   */
  var _bodys;

  void initData() {
    /*
      bottom的按壓圖片
     */
    tabImages = [
      [
        getTabImage('images/ic_home_normal.png'),
        getTabImage('images/ic_home_press.png')
      ],
      [
        getTabImage('images/ic_shop_normal.png'),
        getTabImage('images/ic_shop_press.png')
      ],
      [
        getTabImage('images/ic_msg_normal.png'),
        getTabImage('images/ic_msg_press.png')
      ],
      [
        getTabImage('images/ic_my_normal.png'),
        getTabImage('images/ic_my_press.png')
      ]
    ];

    _bodys = [
      new HomePage(),
      new ShopPage(),
      new MsgPage(),
      new MyPage()
    ];
  }

  @override
  Widget build(BuildContext context) {
    initData();
    // TODO: implement build
    return Scaffold(
      appBar: new AppBar(
        title: new Text("主頁"),
      ),
      body: _bodys[_tabIndex],
      bottomNavigationBar: new BottomNavigationBar(
        items: <BottomNavigationBarItem>[
          new BottomNavigationBarItem(
              icon: getTabIcon(0), title: getTabTitle(0)),
          new BottomNavigationBarItem(
              icon: getTabIcon(1), title: getTabTitle(1)),
          new BottomNavigationBarItem(
              icon: getTabIcon(2), title: getTabTitle(2)),
          new BottomNavigationBarItem(
              icon: getTabIcon(3), title: getTabTitle(3)),
        ],
        //設定顯示的模式
        type: BottomNavigationBarType.fixed,
        //設定當前的索引
        currentIndex: _tabIndex,
        //tabBottom的點選監聽
        onTap: (index) {
          setState(() {
            _tabIndex = index;
          });
        },
      ),
    );
  }
}
複製程式碼

主介面主要通過bottomNavigationBar定義頁面底部的四個tab,body部分主要是通過_tabIndex索引在_bodys中切換頁面,這裡我定義了四個Page,HomePage、ShopPage、MsgPage、MyPage, 這四個Page都是一樣的,就發一個出來看看,其他的雷同

import 'package:flutter/material.dart';
class MsgPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: new Scaffold(
        body: new Center(child:new Text("訊息")),
      ),
    );
  }
}
複製程式碼

按照開發Android的思路來看這個佈局的話,還是很容易理解的,這裡面還要注意的幾個點,獲取本地資源的圖片,是需要在pubspec.yaml中去定義的,定義如下,在assets背後放置圖片的路徑,那麼,這個路徑就可以被Image識別並使用

flutter:
  assets:
    - images/ic_home_normal.png
    - images/ic_home_press.png
    - images/ic_shop_normal.png
    - images/ic_shop_press.png
    - images/ic_msg_normal.png
    - images/ic_msg_press.png
    - images/ic_my_normal.png
    - images/ic_my_press.png
複製程式碼

ok,基本的框架起來了

相關文章