Flutter基礎(五)Material元件之MaterialApp、Scaffold、AppBar

劉望舒發表於2019-07-09

本文首發於公眾號「劉望舒」

關聯絡列 ReactNative入門系列 React Native元件 Flutter基礎系列

前言

在上一篇文章Flutter基礎(四)開發Flutter應用前需要掌握的Basics Widget,我們學習了Basics Widget,除了Basics Widget,我們還需要了解Material Components,也就是Material元件。它提供了實現Material Design準則的視覺、行為和動作的Widget。 官方將Material元件分為為幾個型別:

  • 應用程式結構和導航
  • Button
  • 輸入和選擇
  • 對話方塊,警告彈框和皮膚
  • 資訊顯示
  • 佈局

主要介紹應用程式結構和導航,會分為兩篇文章進行介紹,這一篇介紹應用程式結構和導航分類中的MaterialApp、Scaffold、AppBar。

1.MaterialApp

說到Material元件,不得不提到MaterialApp,它包含了許多Widget,這些Widget通常是實現Material Design的應用程式所必需的。 MaterialApp在此前的文章都用過,簡單的使用這裡就不介紹了,這裡簡單介紹下路由。 在Android開發中我們使用Intent來進行介面跳轉,也稱之為原生路由,後來出現了一些路由框架,比如ARouter。 在Flutter中進行介面跳轉的就是路由,路由用Route類來進行表示,Navigator是對Route進行管理的Widget。Navigator不僅管理了一堆route,還提供管理堆疊的方法 Navigator.push 和 Navigator.pop,通過路由物件的進出棧來控制頁面的跳轉。

flutter路由的使用方式主要有兩種,一種是新建路由,一種是註冊路由。我們分別用這兩種方式寫例子: 首屏是第一個介面,通過第一個介面的按鈕跳轉到第二頁,點選第二頁的按鈕回到第一頁。

1.1 新建路由

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material Components',
      home: FirstPage(),
    );
  }
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('第一頁'),
      ),
      body: Padding(
        padding: EdgeInsets.all(30.0),
        child: RaisedButton(
          child:  Text('跳轉到第二頁'),
          onPressed: () {
            Navigator.push(//1
              context,
              MaterialPageRoute(builder: (context) => SecondPage()),
            );
          },
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('第二頁'),
      ),
      body: Padding(
        padding: EdgeInsets.all(30.0),
        child: RaisedButton(
            child: Text('回到上一頁'),
            onPressed: () {
              Navigator.pop(context);//2
            }),
      ),
    );
  }
}
複製程式碼

註釋1處呼叫了Navigator.push,將新建的路由新增到Navigator管理的route堆疊的棧頂,這個路由我們可以自定義,但是建議使用MaterialPageRoute,它是一個模態路由,可以自適應各個平臺進行頁面替換,並提供了相應的頁面切換動畫。在Android平臺時,頁面進入動畫是向上滑動並淡出,退出是相反的動畫,如果是在iOS平臺 ,頁面進入動畫是從右側滑入,退出是相反的動畫。 點選'跳轉到第二頁'按鈕時會跳轉到SecondPage。註釋2處的Navigator.pop用於彈出route堆疊最頂層的Route。效果如下兩個圖所示。

Flutter基礎(五)Material元件之MaterialApp、Scaffold、AppBar

Flutter基礎(五)Material元件之MaterialApp、Scaffold、AppBar

1.2 註冊路由

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material Components',
      home: FirstPage(),
      routes:  <String, WidgetBuilder>{//1
        '/first': (BuildContext context) => FirstPage(),
        '/second': (BuildContext context) => SecondPage(),
      },
      initialRoute: '/first' ,
    );
  }
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('第一頁'),
      ),
      body: Padding(
        padding: EdgeInsets.all(30.0),
        child: RaisedButton(
          child: Text('跳轉到第二頁'),
          onPressed: () {
            Navigator.pushNamed(context, '/second');//2
          },
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('第二頁'),
      ),
      body: Padding(
        padding: EdgeInsets.all(30.0),
        child: RaisedButton(
            child: Text('回到上一頁'),
            onPressed: () {
              Navigator.of(context).pop();
            }),
      ),
    );
  }
}
複製程式碼

通過註釋1處的routes用於初始化一個路由列表,當推送路由時,將在routes中查詢路徑名稱,如果名稱存在,則關聯的WidgetBuilder用於構造MaterialPageRoute。註釋2處的Navigator.pushNamed和Navigator.push作用類似,只不過pushNamed的引數為路由的名稱。

2. Scaffold

Scaffold同樣屬於Material元件,它實現了Material Design的基本佈局結構,因此它經常會作為MaterialApp的子Widget, Scaffold會自動填充可用的空間,這通常意味著它將佔據整個視窗或螢幕,並且Scaffold會自動適配螢幕。我們的佈局就是在Scaffold中進行編寫的。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Scaffold示例'),
        ),
        body: Padding(
          padding: EdgeInsets.all(30.0),
          child: Text('Scaffold'),
        ),
        bottomNavigationBar: BottomAppBar(
          child: Container(height: 50),
        ),
        drawer: Drawer(
          child: Center(
            child: Text('抽屜'),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}
複製程式碼

Scaffold的屬性有很多,例子中用了幾個屬性:

  • appBar:用於設定頂部的標題欄。
  • body:顯示Scaffold的主要內容。
  • bottomNavigationBar:用於設定Scaffold的底部導航欄,
  • drawer:用於設定抽屜效果。
  • floatingActionButton:用於設定位於右下角的按鈕。

效果如下所示:

Flutter基礎(五)Material元件之MaterialApp、Scaffold、AppBar

可以看到在AppBar上有個抽屜的按鈕,點選按鈕就會滑出抽屜。

3. AppBar

AppBar由toolbar和其他的可選Widget組成,比如TabBar和FlexibleSpaceBar。 AppBar會在頂部顯示leading、title、actions等內容,底部bottom通常顯示TabBar,下圖展示了這些內容的位置分佈。

Flutter基礎(五)Material元件之MaterialApp、Scaffold、AppBar

import 'package:flutter/material.dart';

void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyScaffld(),
    );
  }
}

class MyScaffld extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AppBar示例'),
        leading: FlutterLogo(colors: Colors.lightGreen),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.share),
            onPressed: () {
              print('新增按鈕');
            },
          ),
        ],
      ),
    );
  }
}
複製程式碼

這次沒有把所有程式碼寫在MyApp類中,而是將Scaffld的定義放在了MyScaffld類中。

Flutter基礎(五)Material元件之MaterialApp、Scaffold、AppBar

上面程式碼的Widget樹如下所示,遵守Material Design準則的flutter應用的Widget樹大致也是如此。

Flutter基礎(五)Material元件之MaterialApp、Scaffold、AppBar

總結

本文總結了Material元件中的三種Widget,可以說它們是使用Material元件時最常使用的Widget,常用到我們可能會忽略它們。由於篇幅原因,會在下一篇介紹Material元件的其他Widget。


這裡不僅分享大前端、Android、Java等技術,還有程式設計師成長類文章。
Flutter基礎(五)Material元件之MaterialApp、Scaffold、AppBar

相關文章