flutter之从零开始搭建(一)之 BottomNavigationBar

坐看不如实战来的有效率,这几天都在看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,基本的框架起来了

猜你喜欢

转载自juejin.im/post/5b3ee0b66fb9a04f8a21678c