每日一言:與其擔(dān)心未來,不如現(xiàn)在好好努力。這條路上,只由奮斗才能給你安全感。不要輕易把夢想寄托在某個人身上,也不要太在乎身旁的耳語,因?yàn)槲磥硎悄阕约旱模挥心阕约翰拍芙o你自己最大的安全感。
原文鏈接:http://liuwangshu.cn/flutter/primer/5-material-components.html
關(guān)聯(lián)系列:Flutter基礎(chǔ)(一)移動開發(fā)跨平臺技術(shù)的百家爭鳴
Flutter基礎(chǔ)(二)Flutter開發(fā)環(huán)境搭建和Hello World
Flutter基礎(chǔ)(三)Dart快速入門
Flutter基礎(chǔ)(四)開發(fā)Flutter應(yīng)用前需要掌握的Basics Widget
前言
在上一篇文章Flutter基礎(chǔ)(四)開發(fā)Flutter應(yīng)用前需要掌握的Basics Widget,我們學(xué)習(xí)了Basics Widget,除了Basics Widget,我們還需要了解Material Components,也就是Material組件。它提供了實(shí)現(xiàn)Material Design準(zhǔn)則的視覺、行為和動作的Widget。由于Material組件比較多,而這些組件又十分重要,因此分為多篇進(jìn)行介紹。
1.MaterialApp
說到Material組件,不得不提到MaterialApp,它包含了許多Widget,這些Widget通常是實(shí)現(xiàn)Material Design的應(yīng)用程序所必需的。
MaterialApp在此前的文章都用過,簡單的使用這里就不介紹了,這里主要介紹下路由。
移動App中通常通過全屏元素“屏幕”或“頁面”來顯示內(nèi)容。在Flutter中,這些元素被稱為route(路由),它們由Navigator管理。Navigator不僅管理了一堆route,還提供管理堆棧的方法 Navigator.push 和 Navigator.pop,通過路由對象的進(jìn)出棧來控制頁面的跳轉(zhuǎn)。
flutter路由的使用方式主要有兩種,一種是新建路由,一種是注冊路由。我們分別用這兩種方式寫例子:
首屏是第一個界面,通過第一個界面的按鈕跳轉(zhuǎn)到第二頁,點(diǎn)擊第二頁的按鈕回到第一頁。
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('跳轉(zhuǎn)到第二頁'),
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處調(diào)用了Navigator.push,將新建的路由添加到Navigator管理的route堆棧的棧頂,這個路由我們可以自定義,但是建議使用MaterialPageRoute,它是一個模態(tài)路由,可以自適應(yīng)各個平臺進(jìn)行頁面替換,并提供了相應(yīng)的頁面切換動畫。在Android平臺時,頁面進(jìn)入動畫是向上滑動并淡出,退出是相反的動畫,如果是在iOS平臺 ,頁面進(jìn)入動畫是從右側(cè)滑入,退出是相反的動畫。
點(diǎn)擊’跳轉(zhuǎn)到第二頁’按鈕時會跳轉(zhuǎn)到SecondPage。注釋2處的Navigator.pop用于彈出route堆棧最頂層的Route。效果如下兩個圖所示。
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('跳轉(zhuǎn)到第二頁'),
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用于初始化一個路由列表,當(dāng)推送路由時,將在routes中查找路徑名稱,如果名稱存在,則關(guān)聯(lián)的WidgetBuilder用于構(gòu)造MaterialPageRoute。注釋2處的Navigator.pushNamed和Navigator.push作用類似,只不過pushNamed的參數(shù)為路由的名稱。
2. Scaffold
Scaffold同樣屬于Material組件,它實(shí)現(xiàn)了Material Design的基本布局結(jié)構(gòu),因此它經(jīng)常會作為MaterialApp的子Widget, Scaffold會自動填充可用的空間,這通常意味著它將占據(jù)整個窗口或屏幕,并且Scaffold會自動適配屏幕。我們的布局就是在Scaffold中進(jìn)行編寫的。
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:用于設(shè)置頂部的標(biāo)題欄。
? body:顯示Scaffold的主要內(nèi)容。
? bottomNavigationBar:用于設(shè)置Scaffold的底部導(dǎo)航欄,
? drawer:用于設(shè)置抽屜效果。
? floatingActionButton:用于設(shè)置位于右下角的按鈕。
效果如下所示:
可以看到在AppBar上有個抽屜的按鈕,點(diǎn)擊按鈕就會滑出抽屜。
3. AppBar
AppBar由toolbar和其他的可選Widget組成,比如TabBar和FlexibleSpaceBar。
AppBar會在頂部顯示leading、title、actions等內(nèi)容,底部bottom通常顯示TabBar,下圖展示了這些內(nèi)容的位置分布。
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類中。
上面代碼的Widget樹如下所示,遵守Material Design準(zhǔn)則的flutter應(yīng)用的Widget樹大致也是如此。
總結(jié)
本文總結(jié)了Material組件中的三種Widget,可以說它們是使用Material組件時最常使用的Widget,常用到我們可能會忽略它們。由于篇幅原因,會在下一篇介紹Material組件的其他Widget。