利用Flutter写一个跨平台的果核APP(1)——界面篇1

前言

从这里开始,我就准备边学边做边用博客记录下自己的重构历程,会结合已有的app的样式进行重构。

原图

先看一下app的截图:


首页

左侧菜单栏

上面两个截图是app的首页和左侧菜单栏的截图,首页下方是一个可以滑动的tab+viewpager,左侧菜单栏是一个drawerlayout。

目标图像

这是实现的效果图


效果图1

效果图2

接下来将会逐一分析界面并给出代码。

解析

首先我们要做的就是划分好界面层次,这一步操作还是很简单的,我直接贴出来目前的页面层次结构



在flutter中,一切都是widget,也就是说所见的都是控件,一个空间就是一个类,一个类可以放在一个dart文件里面,也就是说可以理解为一个控件就是一个dart文件。在这里项目目录分级为如下几个部分:


TIM图片20180914132826.png

assets文件夹存放相关的资源文件
lib文件为存放dart文件的地方
common文件夹用于存放app执行所需要的文件
pages文件夹用于存放页面文件
pages/main存放的是首页的页面文件
pages/school存放的是校园部分的页面文件
app.dart是首页的页面文件
main.dart是整个app的入口文件

入口文件

入口文件很简单,直接上代码

import 'package:flutter/material.dart';
import 'package:flutter_guohe/pages/main.dart';

void main() {
  runApp(new Guohe());
}

底部tabbar的实现

从之前的层次图就可以看出,tabbar控制着3个页面,所以他应该是首页的顶级元素,在app.dart中添加如下代码,具体参考《Flutter底部导航栏的实现》

/**
 * APP的主入口文件
 */

import 'package:flutter/material.dart';

import 'package:flutter_guohe/pages/main/today.dart';
import 'package:flutter_guohe/pages/main/playground.dart';
import 'package:flutter_guohe/pages/main/kb.dart';
import 'package:flutter_guohe/pages/main/leftmenu.dart';

import 'package:flutter_guohe/common/eventBus.dart';

//果核的主界面
class Guohe extends StatefulWidget {
  @override
  GuoheState createState() => new GuoheState();
}

class GuoheState extends State<Guohe> with SingleTickerProviderStateMixin {
  TabController controller;
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  void initState() {
    controller = new TabController(length: 3, vsync: this);
    eventBus.on<EventOpenDrawer>().listen((EventOpenDrawer data) {
      if (data.flag) _scaffoldKey.currentState.openDrawer();
    });
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        key: _scaffoldKey,
        drawer: new LeftMenu(),
        body: new TabBarView(
          controller: controller,
          children: <Widget>[
            new Today(),
            new Kb(),
            new Playground(),
          ],
        ),
        bottomNavigationBar: new Material(
          color: Colors.white,
          child: new TabBar(
            controller: controller,
            labelColor: Colors.deepPurpleAccent,
            unselectedLabelColor: Colors.black26,
            tabs: <Widget>[
              new Tab(
                text: "今日",
                icon: new Icon(Icons.brightness_5),
              ),
              new Tab(
                text: "课表",
                icon: new Icon(Icons.map),
              ),
              new Tab(
                text: "操场",
                icon: new Icon(Icons.directions_run),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

左侧菜单栏

左侧菜单栏就是一个drawer,就是一个抽屉,在Scaffold中申明就好了,在这里我为了看起来不那么乱,创建了一个leftmenu.dart文件用来展示左侧菜单界面,只要知道了row、column、padding的用法就可以很快的写出来了,参考《flutter实战1:完成一个有侧边栏的主界面》。下面贴代码

import 'package:flutter/material.dart';

//左侧菜单栏
class LeftMenu extends Drawer {
  @override
  Widget build(BuildContext context) {
    return new Drawer(
      //侧边栏按钮Drawer
      child: new ListView(
        children: <Widget>[
          //个人信息部分
          new Container(
              color: Color.fromARGB(255, 119, 136, 213),
              child: new Padding(
                padding: new EdgeInsets.all(26.0),
                child: new Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    new Row(
                      children: <Widget>[
                        //头像
                        new Container(
                          width: 80.0,
                          height: 80.0,
                          margin:
                              new EdgeInsets.only(right: 10.0, bottom: 15.0),
                          decoration: BoxDecoration(
                            image: DecorationImage(
                              image: new NetworkImage(
                                  'http://www.chedan5.com/upload/article/201803/06/1740235a9e62077e0aexbcUQh.jpg'),
                              //从Assets加载图片
                              fit: BoxFit.cover,
                            ),
                            shape: BoxShape.circle,
                          ),
                        ),
                        new Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            new Text(
                              '梁越勇',
                              style: new TextStyle(
                                  color: Colors.white, fontSize: 25.0),
                            ),
                            new Text(
                              '152210702112',
                              style: new TextStyle(
                                  color: Colors.white, fontSize: 15.0),
                            )
                          ],
                        )
                      ],
                    ),
                    new Text(
                      "计算机学院",
                      style: new TextStyle(color: Colors.white, fontSize: 18.0),
                    )
                  ],
                ),
              )),
          new ListTile(
              //第二个功能项
              title: new Text('关于我们'),
              leading: new Icon(Icons.accessibility),
              onTap: () {
                Navigator.of(context).pop();
                Scaffold.of(context).showSnackBar(new SnackBar(
                      content: new Text("关于我们"),
                    ));
              }),
          //分割线控件
          new ListTile(
              //退出按钮
              title: new Text('分享此应用'),
              leading: new Icon(Icons.share),
              onTap: () {
                Navigator.of(context).pop();
                Scaffold.of(context).showSnackBar(new SnackBar(
                      content: new Text("分享此应用"),
                    ));
              } //点击后收起侧边栏
              ),
          //分割线控件
          new ListTile(
              //退出按钮
              title: new Text('给我们反馈'),
              leading: new Icon(Icons.feedback),
              onTap: () {
                Navigator.of(context).pop();
                Scaffold.of(context).showSnackBar(new SnackBar(
                      content: new Text("给我们反馈"),
                    ));
              } //点击后收起侧边栏
              ),
          //分割线控件
          new ListTile(
              //退出按钮
              title: new Text('联系开发者'),
              leading: new Icon(Icons.flight),
              onTap: () {
                Navigator.of(context).pop();
                Scaffold.of(context).showSnackBar(new SnackBar(
                      content: new Text("联系开发者"),
                    ));
              } //点击后收起侧边栏
              ),
          //分割线控件
          new ListTile(
              //退出按钮
              title: new Text('加入交流群'),
              leading: new Icon(Icons.group_add),
              onTap: () {
                Navigator.of(context).pop();
                Scaffold.of(context).showSnackBar(new SnackBar(
                      content: new Text("加入交流群"),
                    ));
              } //点击后收起侧边栏
              ),
          new ListTile(
              //退出按钮
              title: new Text('切换账号'),
              leading: new Icon(Icons.sync),
              onTap: () {
                Navigator.of(context).pop();
                Scaffold.of(context).showSnackBar(new SnackBar(
                      content: new Text("切换账号"),
                    ));
              } //点击后收起侧边栏
              ),
          new ListTile(
              //退出按钮
              title: new Text('检测升级'),
              leading: new Icon(Icons.refresh),
              onTap: () {
                Navigator.of(context).pop();
                Scaffold.of(context).showSnackBar(new SnackBar(
                      content: new Text("检测升级"),
                    ));
              } //点击后收起侧边栏
              ),
          new ListTile(
              //退出按钮
              title: new Text('更新说明'),
              leading: new Icon(Icons.info),
              onTap: () {
                Navigator.of(context).pop();
                Scaffold.of(context).showSnackBar(new SnackBar(
                      content: new Text("更新说明"),
                    ));
              } //点击后收起侧边栏
              ),
        ],
      ),
    );
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • 经过2周的学习,看过笔记1-8的小伙伴们已经有不少开始自己写APP了,我也按耐不住这股热情,想要自己开发个APP玩...
    燃烧的鱼丸阅读 13,084评论 7 39
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,704评论 2 59
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,969评论 3 119
  • 说好不再写你了。可······ 我总是说话不算数,对吗? 昨晚是我的生日,你说你还记得,我很欣喜。其实,我昨晚喝吐...
    曹小七阅读 171评论 2 0