坐看不如实战来的有效率,这几天都在看flutter的一些布局和特性,打算从零开始搭建一个应用,中间可能会因为一些原因断了文章,但是会慢慢补上。
学移动端的套路:
在学习移动开发的时候,一般都是按照这几个套路走,
- 布局UI,
- 路由跳转,
- 网络请求,
- 页面与数据交互。
当然,接下来的一系列也是按照这个步骤走
效果
今天先来搭建一个基础的布局,在Android的首页布局中,大部分都是Fragment+TabBottom的形式,先来看下效果图。
效果图
开始搭建
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,基本的框架起来了