03*:Flutter 初探:(StatelessWidget、StatefulWidget)(【runApp()-->>MaterialApp()-->> Scaffold()】启动-风格-容器)

问题

 

目录

1:runApp()函数启动项目 

2:MaterialApp()  [məˈtɪəriəl] 材料,素材

3:Scaffold()[ˈskæfəʊld]  

预备

 

正文

由上面的架构图可以看出来,flutter最上层是google 的纸墨设计Material Design(MaterialApp)组件,关于Material Design设计理念大家可以去官网安利一下啊material.io

在MaterialApp下面是所有组件的基类Widget,而在Widget的上层是statelessWdiget(无状态组件)、statefulWidget(有状态组件)和InheritedWidget(可以向子类View树种传递信息),包括我们在上篇文章中用到的Scaffold、Center、Text都是statelessWdiget、statefulWidget的子类。

1:runApp()函数启动项目

import 'package:flutter/material.dart';

void main() {
  runApp(
    new Center(
      child: new Text(
        'Hello, world!',
        textDirection: TextDirection.ltr,
      ),
    ),
  );
}

该runApp函数接受给定的widget并使其成为widget树的根。

在编写应用程序时,通常会创建新的widget,这些widget是无状态的StatelessWidget或者是有状态的StatefulWidget, 具体的选择取决于您的widget是否需要管理一些状态。

2:MaterialApp()  [məˈtɪəriəl] 材料,素材

MaterialApp 代表使用纸墨设计(Material Design)设计风格(google的安卓设计风格)的应用。里面包含了纸墨设计风格应用所需要的基本控件。

MaterialApp 主要属性如下:

  • title : 在任务管理窗口中所显示的应用名字
  • theme : 应用各种 UI 所使用的主题颜色
  • color : 应用的主要颜色值(primary color),也就是安卓任务管理窗口中所显示的应用颜色
  • home : 应用默认所显示的界面 Widget
  • routes : 应用的顶级导航表格,这个是多页面应用用来控制页面跳转的,类似于网页的网址
  • initialRoute :第一个显示的路由名字,默认值为 Navigator.defaultRouteName
  • onGenerateRoute : 生成路由的回调函数,当导航的命名路由的时候,会使用这个来生成界面
  • onLocaleChanged : 当系统修改语言的时候,会触发这个回调
  • navigatorObservers : 应用 Navigator 的监听器
  • debugShowMaterialGrid : 是否显示 纸墨设计 基础布局网格,用来调试 UI 的工具
  • showPerformanceOverlay : 显示性能标签
  • debugShowCheckedModeBanner :是否显示右上角DEBUG标签 (调试开关)
  • checkerboardRasterCacheImages :检查缓存的图像开关,检测在界面重绘时频繁闪烁的图像(调试开关)
  • showSemanticsDebugger :是否打开Widget边框,类似Android开发者模式中显示布局边界(调试开关)

下面将介绍重要的几个属性。

title

这个和启动图标名字是不一样的,和当前 Activity 的名字也是不一样的。 这个 Title 是用来定义任务管理窗口界面所看到应用名字的。在原生 Android 系统中点击圆圈 Home 按钮右边的方块按钮就会打开多任务切换窗口。

theme

定义应用所使用的主题颜色,在纸墨设计中定义了 primaryColor、accentColor、hintColor 等颜色值。可以通过这个来指定一个 ThemeData 定义应用中每个控件的颜色。

home

这个是一个 Widget 对象,用来定义当前应用打开的时候,所显示的界面。

color

定义系统中该应用的主要颜色

routes

定义应用中页面跳转规则。 该对象是一个 Map<String, WidgetBuilder>。

当使用 Navigator.pushNamed 来路由的时候,会在 routes 查找路由名字,然后使用 对应的 WidgetBuilder 来构造一个带有页面切换动画的 MaterialPageRoute。如果应用只有一个界面,则不用设置这个属性,使用 home 设置这个界面即可。

'/' 和 home 属性
路由表(也就是我们下面代码里面定义的routes变量)里面的 '/' 和 home 属性,二者不能同时存在,但是必须有一个存在:修改了 title、home 被注释了使用 routes 来替代。

如果所查找的路由在 routes 中不存在,则会通过 onGenerateRoute 来查找。

initialRoute

是启动APP的初始页面,也就是用户看到的第一个页面。如果这个属性没有给值,那么会去寻找路由表里面的 '/' ,或者 home 属性。

当initialRoute没有设置
initialRoute 或者 home 属性都是定义了主页面,当 initialRoute 没有定义的时候,用户看到的就是 '/' 或者 home 对应的页面。

当initialRoute设置了
当initialRoute 和 '/' 或者 home 属性同时存在的时候,initialRoute 的优先级高于二者。意思就是如果 initialRoute 定义的页面和 '/' 或者 home 设置的页面不同时,用户看到的是 initialRoute 定义的页面。

onGenerateRoute

路由回调函数,在打开命名路由的时候可能会被调用,之所以说可能,是因为当调用Navigator.pushNamed(...)打开命名路由时,如果指定的路有名在路由表中已注册,则回调用路由表中的builder函数来生成路由组建;如果路由表中没有注册,则会调用onGenerateRoute来生成路由。
假设我们需要开发一个电商APP,当用户没有登录的时候可以查看碘伏、商品等信息,但是交易记录、购物车、用户个人信息等页面需要登录后才能查看。就可以在onGenerateRoute回调中进行统一的权限控制:

import 'package:flutter/material.dart';

void main() => runApp(MaterialAppDemo());


// 第二个类
class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("Second Bar")),
        body: Center(child: Text("Second Body"))
    );
  }
}

// 最后一个类
class MaterialAppDemo extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '应用名称',
      color: Colors.green,
      home: SecondScreen(),
      theme: ThemeData(
          primaryColor: Colors.redAccent
      )
    );
  }
}

3:Scaffold()[ˈskæfəʊld]  给…搭脚手架;用支架支撑  相当于一个容器,相当于VC, 有导航、主体、tabbar

Scaffold 实现了基本的 Material 布局。只要是在 Material 中定义了的单个界面显示的布局控件元素,都可以使用 Scaffold 来绘制。

提供展示抽屉(drawers,比如:左边栏)、通知(snack bars) 以及 底部按钮(bottom sheets)。

我们可以将 Scaffold 理解为一个布局的容器。可以在这个容器中绘制我们的用户界面。

主要的属性说明

  • appBar:显示在界面顶部的一个 AppBar
  • body:当前界面所显示的主要内容
  • floatingActionButton: 在 Material 中定义的一个功能按钮。
  • persistentFooterButtons:固定在下方显示的按钮。
  • drawer:侧边栏控件
  • bottomNavigationBar:显示在底部的导航栏按钮栏。可以查看文档:Flutter学习之制作底部菜单导航
  • backgroundColor:背景颜色
  • resizeToAvoidBottomPadding: 控制界面内容 body,是否重新布局来避免底部被覆盖了,比如当键盘显示的时候,重新布局避免被键盘盖住内容。默认值为 true。
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Scaffold组件',
      home: DemoPage(),
    );
  }
}

class DemoPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //应用栏
      appBar: AppBar(
        backgroundColor: Colors.red,
        title: Text('标题',style: TextStyle(color: Colors.white),),
        centerTitle: true,
        elevation: 10.0,
        leading: Icon(Icons.home),
        actions: <Widget>[
          Icon(Icons.add),
        ],
        bottom: PreferredSize(
          child: Container(
            height: 50.0,
            child: Center(
              child: Text('显示在标题下面的内容'),
            ),
            decoration: BoxDecoration(
              color: Colors.redAccent,
            ),
          ),
          preferredSize: Size.fromHeight(50.0),
        ),
      ),

      //内容区域
      body: Center(
        child: Text('中间内容部分',style: TextStyle(color: Colors.red,fontSize: 36.0),),
      ),

      //侧边栏 抽屉组件
      drawer: Drawer(
          child: Center(
            child: Container(
              width: 150.0,
              color: Colors.orange,
              child: Text('侧边栏',style: TextStyle(color: Colors.white,fontSize: 24.0),),
            ),
          )
      ),

      //底部 持久化按钮
      persistentFooterButtons: <Widget>[
        Icon(Icons.person),
        Icon(Icons.add),
        Icon(Icons.print),
        Icon(Icons.apps),
        Icon(Icons.chat),
      ],

      //底部 导航按钮
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 1,
        fixedColor: Colors.redAccent,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('主页'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.chat),
            title: Text('聊天'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            title: Text('我的'),
          ),
        ],
      ),

      //底部 FAB按钮
      floatingActionButton: Builder(
          builder: (BuildContext context){
            return FloatingActionButton(
              backgroundColor: Colors.red,
              child: Icon(Icons.add),
              onPressed: (){

                var snackbar = new SnackBar(
                  content: Text('显示SnackBar'),
                  backgroundColor: Colors.red,
                  duration: Duration(
                    milliseconds : 1500,
                  ),
                  action: SnackBarAction(
                      label: '撤销',
                      onPressed: (){}
                  ),
                );
                Scaffold.of(context).showSnackBar(snackbar);
              },
            );
          }
      )

    );
  }
}

 运行后的第一个页面,每个部位含义在代码均有解释

 

从屏幕左侧往右滑,出现侧边栏 

 

点击右下角红圈白色的 + 按钮(即FAB 按钮),将显示 SnackBar、撤销 字样

 

 

 

注意

 

引用

 1:Flutter 初探

2:经验总结!Material Design和iOS 产品设计的差异化思考

3:MaterialApp 详解

4:Scaffold 详解

5:MaterialApp 详解

posted on 2020-12-04 20:36  风zk  阅读(202)  评论(0编辑  收藏  举报

导航