先說明一下
這裡不講怎麼安裝flutter環境等前置操作(就提一些我安裝的時候踩的坑),我直接講自己開發的實際經歷(其實也就開發了兩到三個星期)。flutter是牛逼,但是生態環境是真的少,目前還是RN比較多人用。
安裝遇到的坑:
- flutter sdk最好不要安裝1.17.0,因為我自己安裝的時候執行命令列flutter run一直報錯,各種各樣的錯,我換成低版本一點的就不會,截止目前(文章發表日期)時間。以後不會報錯再說。
- sdk下載太慢的話可以換迅雷下載,挺快的。
- 記得開啟虛擬設定(一般第一次安裝都需要進入BIOS介面去修改),不會的朋友自行百度,謝謝。
- 在環境變數裡面記得配置國內映象(PUB_HOSTED_URL:pub.flutter-io.cn和FLUTTER_STORAGE_BASE_URL:storage.flutter-io.cn)
- 順便在環境變數裡面新增命令列
開始學習
當你可以開始執行flutter並且可以看到類似下面的圖片的時候,恭喜你,這裡就是從零開始。
基礎學習資料
這裡推薦先去看看官方文件的東西,可以先大概過一下,因為剛開始的時候是記不住那麼多東西,只要有個印象就可以。不用死記硬背,需要的時候再去查就可以,因為我自己現在也是這樣,哈哈哈哈。
學習視訊
我又來給jspang大神推廣了......
推薦必看知識
Flutter實戰 一些基礎知識(而且有一說一,裡面講到的元件是真的少,不過講到的都說的不錯,畢竟不是主講元件的)
Flutter中文網 這個一定要去看一下里面的 Flutter for Web開發者這一章,不需要很懂,但需要大概瞭解一下(我自己是web開發者,之前也沒有接觸過其他app框架)
後面需要用到的時候再看
flutter元件網這裡推薦一個講元件的網站,雖然不是全部,但也挺多了。
基礎知識
dart語法
我是覺得有點像java(我的java只停留在大學課本級別),這個你如果看完上面flutter實戰應該多少會有一些瞭解,那就足夠了其實,我自己也沒有特地去學習dart,只是在需要的時候再去查,因為很多東西和js還是很像的,不過它有一些很好用的操作符,例如?./??等等......
Widget簡介
官網介紹:在Flutter中幾乎所有的物件都是一個Widget。與原生開發中“控制元件”不同的是,Flutter中的Widget的概念更廣泛,它不僅可以表示UI元素,也可以表示一些功能性的元件如:用於手勢檢測的 GestureDetector widget、用於APP主題資料傳遞的Theme等等,而原生開發中的控制元件通常只是指UI元素。在後面的內容中,我們在描述UI元素時可能會用到“控制元件”、“元件”這樣的概念,讀者心裡需要知道他們就是widget,只是在不同場景的不同表述而已。由於Flutter主要就是用於構建使用者介面的,所以,在大多數時候,讀者可以認為widget就是一個控制元件,不必糾結於概念。
這裡主要是要了解StatelessWidget和StatefulWidget的區別,這兩個官網講得都挺詳細的。(看不太懂的話,有個大概瞭解就可以,因為我也不是很懂,後面用著用著就知道了)
StatelessWidget(個人理解)
類似一個靜態頁面/元件,不需要進行資料互動的時候或者說僅依賴於物件本身的配置資訊,僅僅是用於展示給定的資訊,可以繼承這個。
StatefulWidget(個人理解)
需要進行資料互動等操作的時候繼承這個(大多情況下是這個),這個多了初始化(initState)、銷燬(dispose)等可以過載的回撥函式。
簡單總結一下,當我們的Widget是StatelessWidget,那麼當他的內容被建立出來之後,就不能再改變了。相反StatefulWidget就可以。
基礎元件庫?material牛逼
這個就是官方說得基礎元件庫,也就是我們開發當中經常用到的。說是元件庫,我個人覺得有點像一個頁面的主骨幹,要往上面新增什麼東西就看自己需要。為什麼這樣說呢?因為它為我們提供了以個頁面的基本骨架(頂部標題、主體、底部導航等等)。例如我們初始化一個專案後的程式碼(lib/main.dart為例),這裡可以大概看一下,不懂的往下看自然就明白了
import 'package:flutter/material.dart';//引入material元件
void main() => runApp(MyApp());//主入口
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,//主題色
),
home: MyHomePage(title: 'Flutter Demo Home Page'),//這個就是主頁顯示的元件,MyHomePage在下面定義(title是傳入的引數)
);
}
}
//下面的程式碼也可以直接和上面的程式碼進行合併,不過大家一般會拆開來寫,這樣好看,容易維護,也體現了元件化思想
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);//這個是用來獲取傳進來的引數的,接收了上面的title
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
//初始化資料,dart語法在第一次賦值的時候就就需要定義型別,之後不可以再轉換,不像js可以隨便換
//可以用var來定義一個變數,但當給變數第一次賦值時候就會自動定義型別
int _counter = 0;
//自己寫的一個函式
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
//頂部標題欄,title就是接收的引數
appBar: AppBar(
title: Text(widget.title),
),
//主體
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
//這個是懸浮按鈕
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,//繫結事件
tooltip: 'Increment',
child: Icon(Icons.add),
),
//底部導航
bottomNavigationBar: BottomAppBar(
color: Colors.white,
child: Row(
children: [
IconButton(icon: Icon(Icons.home)),
IconButton(icon: Icon(Icons.business)),
],
mainAxisAlignment: MainAxisAlignment.spaceAround, //均分底部導航欄橫向空間
),
),
);
}
}
複製程式碼
元件?flutter萬物皆元件?
下面不會提到所有,只提一些我們平常開發(其實是我自己開發時)比較常用的。
基礎元件(先說幾個比較簡單常用的)
這裡指的是可以顯示出來的元件(我自己這樣認為),例如文字(不像web那樣直接放的),圖片等。而且這裡不是型別所有都講,想看具體請自行看官網或者百度
文字
最基本的使用方法
Text('我是最簡單的文字'),
Text(
'我是居中的文字',
textAlign: TextAlign.center, //這個居中是相對於它自身所在位置(不是相對於螢幕),果它所在的位置的寬度變寬,它的位置也會改變,我這裡使用的是ListView(下面會說到)
),
Text(
'我是限制了行數的文字' * 9,
maxLines: 1,//最大行數
overflow: TextOverflow.ellipsis,//超出時顯示的方式
),
複製程式碼
文字新增樣式
Text(
'我是有樣式的文字',
style: TextStyle(
backgroundColor: Colors.blue, //背景色 Colors是直接用官方給的顏色
color: Color.fromRGBO(100, 100, 100,
1), //字型顏色 Color.fromRGBO(red,green,bule,opacity)可以自定義顏色,還有一個是Color.fromARGB
fontSize: 15,
height: 15, //該屬性用於指定行高,但它並不是一個絕對值,而是一個因子,具體的行高等於fontSize*height
decoration: TextDecoration.lineThrough,//下劃線,上劃線等
decorationStyle: TextDecorationStyle.dashed,//上面那個屬性的樣式,實線,虛線什麼的
),
)
複製程式碼
一個Text使用多種樣式
Text.rich(
TextSpan(
children: [
TextSpan(text: "第一種樣式"),
TextSpan(
text: "第二種樣式",
style: TextStyle(color: Colors.blue),
),
],
),
)
複製程式碼
按鈕
RaisedButton(
child: Text("我是簡單的按鈕"),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.thumb_up),
onPressed: () {},
),
RaisedButton.icon(
//這個還有其他差不多樣式 就是換個名字而已RaisedButton/OutlineButton/FlatButton
icon: Icon(Icons.account_balance_wallet),
label: Text("icon+文字"),
onPressed: () {},
),
FlatButton(
color: Colors.blue,
highlightColor: Colors.green[700],
colorBrightness: Brightness.dark, //按鈕主題 深色或淺色
splashColor: Colors.grey,
child: Text("沒有icon自定義"),
shape: RoundedRectangleBorder(//形狀
borderRadius: BorderRadius.circular(20.0),//圓角
),
onPressed: () {},
),
FlatButton.icon(
color: Colors.blue,
icon: Icon(Icons.thumb_up),
highlightColor: Colors.blue[700],
colorBrightness: Brightness.dark,
splashColor: Colors.grey,
label: Text("有icon自定義"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
onPressed: () {},
)
複製程式碼
圖片/icon
Image(
image: AssetImage('images/demo/img1.jpg'),//為什麼這樣寫下面會講到
width: 100.0,
),
Image.asset(
//等同於上面的寫法
"images/demo/img2.jpg",
width: 100.0,
),
Image.network(
//引用網路的
'https://cdn.jsdelivr.net/gh/flutterchina/website@1.0/images/flutter-mark-square-100.png',
),
Icon(Icons.home),
Icon(
Icons.home,
color: Colors.blueAccent,
size: 100,
),
複製程式碼
這裡圖片的用法和我們web的引用相對路徑不用,需要先在配置檔案裡面先定義好
官方說法輸入框
TextField(
autofocus: false,//是否有自動聚焦
keyboardType: TextInputType.number, //輸入框形式 文字、數字等
onChanged: (value) {
print(value);
//賦值操作
},
),
複製程式碼
樣式什麼的太多了,這裡就不提了,這裡的數字輸入框在ios端是沒有完成按鈕的,解決方法在我另外一篇flutter踩坑日記裡面就有解決方法
容器?我的div呢?
Container(這不就是我想要的div嗎)
Container,顧名思義,就是一個容器,用來存放你的其他元件(文字,圖片什麼的),它本身並沒有特別的含義(類似我們的div,可以這樣說)。當然,它肯定不止用來放元件這麼簡單,它定義其他一些屬性,例如邊框、背景這些樣式。
最最最簡單的例子
Container(
child: Text('我的父級就是一個Container容器'),
),
複製程式碼
好了,container就說這些了,怎麼可能,這個可是我最喜歡的,開發中我最常用的。
Container(
width: 100,
height: 100,
// margin: EdgeInsets.all(10),//外邊距,這種是全部
// margin: EdgeInsets.only(left: 200, top: 20), //這種是單獨的
margin: EdgeInsets.fromLTRB(10, 20, 30, 40), //這種是四個
padding: EdgeInsets.all(10), //內邊距,同上
// color: Colors.blueAccent, //背景色,記得這個會和decoration裡面的color衝突,如果有decoration就需要在decoration裡面設定,不能在外面
// foregroundDecoration: BoxDecoration(//也是裝飾,但是會繪製在 child 之上,也就是會覆蓋 child(很少用到)
// color: Colors.blue,
// ),
decoration: BoxDecoration(
color: Colors.greenAccent, //背景色
border: Border.all(color: Colors.blueAccent, width: 5), //全部
// border: Border(
// top: BorderSide(color: Colors.pinkAccent, width: 5),//單個
// right: BorderSide(color: Colors.blueAccent, width: 5),
// ),
borderRadius: BorderRadius.all(
//全部
Radius.circular(10),
),
// borderRadius: BorderRadius.only(//單個
// topLeft: Radius.circular(10),
// bottomRight: Radius.circular(20),
// ),
// gradient: LinearGradient(
// //背景漸變
// colors: [Colors.red, Colors.green, Colors.blue],
// ),
boxShadow: [
BoxShadow(
color: Colors.pinkAccent,
blurRadius: 25.0, //延伸距離,會有模糊效果
offset: Offset(10.0, -5.0), //X軸 Y軸偏移量
spreadRadius: 9.0, //延伸距離,不會有模糊效果
)
],
),
child: Text('文字'), //子元素
),
複製程式碼
因為這裡的顯示的不同東西太多,就乾脆只放一張最終的了(不然寫一下放一張怕是要十幾張)
佈局元件?這又是什麼?
佈局類元件都會包含一個或多個子元件,不同的佈局類元件對子元件排版(layout)方式不同(後面的這句畫重點)
Row/Column/Expanded(flex???)
還是顧名思義,典型的行列布局
這裡沒有提到溢位的情況(畫重點),因為溢位問題需要用到其他元件(滾動元件),如果你出現了溢位情況請耐心地往下看。
Row
Row(
mainAxisSize:MainAxisSize.max,//Row在主軸(這裡的主軸是相對而言的,Row的主軸是水平的 Column的主軸是垂直的)方向佔用的空間,
mainAxisAlignment: MainAxisAlignment.start,//子元件在主軸的(同上)上的對齊方式,當mainAxisSize為min是沒有意義
verticalDirection:VerticalDirection.down,//表示Row縱軸(垂直)的對齊方向,預設是VerticalDirection.down,表示從上到下
crossAxisAlignment:CrossAxisAlignment.start,//子元件在副軸(副軸是我自己喜歡的叫法)(row的是指垂直)的(同上)上的對齊方式,可以看到當我
textDirection: TextDirection.ltr,//子元件佈局順序 ltr表示從左開始佈局(預設),rtl表示從右開始佈局
children: <Widget>[
Text('行佈局'),
RaisedButton(
child: Text("我是簡單的按鈕"),
onPressed: () {},
),
Image(
image: AssetImage('images/demo/img1.jpg'),
width: 100.0,
),
Image(
image: AssetImage('images/demo/img1.jpg'),
width: 100.0,
),
],
),
複製程式碼
Column
這個其實和行佈局差不多的,只是換成垂直方向而已,記得Column的主軸是垂直的,副軸是水平的
Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,//我這裡相對上面的row佈局換了引數
crossAxisAlignment: CrossAxisAlignment.center,//我這裡相對上面的row佈局換了引數
textDirection: TextDirection.ltr,
children: <Widget>[
Text('列布局'),
RaisedButton(
child: Text("我是簡單的按鈕"),
onPressed: () {},
),
Image(
image: AssetImage('images/demo/img2.jpg'),
width: 100.0,
),
Image(
image: AssetImage('images/demo/img2.jpg'),
width: 100.0,
),
],
),
複製程式碼
Expanded
這個是覺得Flutter實戰講的很到位,我就直接搬過來了。
如果Row裡面巢狀Row,或者Column裡面再巢狀Column,那麼只有最外面的Row或Column會佔用盡可能大的空間,裡面Row或Column所佔用的空間為實際大小
Container(
color: Colors.green,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max, //有效,外層Colum高度為整個螢幕
children: <Widget>[
Container(
color: Colors.red,
child: Column(
mainAxisSize: MainAxisSize.max,//無效,內層Colum高度為實際高度
children: <Widget>[
Text("hello world "),
Text("I am Jack "),
],
),
)
],
),
),
);
複製程式碼
如果要讓裡面的Column佔滿外部Column,可以使用Expanded 元件
Expanded(
child: Container(
color: Colors.red,
child: Column(
mainAxisAlignment: MainAxisAlignment.center, //垂直方向居中對齊
children: <Widget>[
Text("hello world "),
Text("I am Jack "),
],
),
),
)
複製程式碼
Stack/Positioned
這個我覺得有點像我們web開發中的父相子絕(父元素相對定位,子元素絕對定位),flutter好像沒有相對螢幕進行定位的(例如我們的position:fixed)。記得Positioned這個是需要和Stack在一起巢狀使用的。
Stack(
alignment: AlignmentDirectional
.bottomStart, //此引數決定如何去對齊沒有定位(沒有使用Positioned)或部分定位的子元件
overflow: Overflow
.visible, //此屬性決定如何顯示超出Stack顯示空間的子元件 Overflow.clip(裁剪/隱藏) Overflow.visible(可見)
textDirection: TextDirection.ltr, //這個和row佈局一樣
fit: StackFit.loose,//此引數用於確定沒有定位的子元件如何去適應Stack的大小 loose表示使用子元件的大小,expand表示擴伸到Stack的大小。
children: <Widget>[
Positioned(
top: 100, //相對Stack的定位
left: 10,
width: 100,
height: 100,
child: Container(
color: Colors.blueAccent,
),
),
Positioned(
//假如位置相同,寫在後面的元件會覆蓋前面的元件,上面設定了藍色,這裡設定了粉色,但是隻能看見粉色
top: 100,
left: 10,
width: 100,
height: 100,
child: Container(
color: Colors.pinkAccent,
),
),
Positioned(
//覆蓋了上面的一半
top: 150,
left: 10,
width: 100,
height: 100,
child: Container(
color: Colors.orangeAccent,
),
),
Container(
color: Colors.greenAccent,
child: Text('我沒有設定定位'),
),
],
),
複製程式碼
可見和隱藏的區別
佈局元件就講到這裡,還有其他佈局元件如果需要可以直接看官網或者百度。滾動元件?不會自己動起來嗎?溢位?什麼鬼?不會自動隱藏的嗎?
本來想和溢位分開講的,但感覺合在一起講好像更好就合起來了。
這裡先說一下溢位是什麼情況,當我們設定的子元件超出螢幕範圍(例如我在row元件設定了很多張圖片,如下圖),這種情況我們稱為溢位。
那是因為它不會自己動起來呀(如果你覺得這裡黃色是因為你帶了黃色的眼睛(dog))。。。這時候我們就需要讓它動起來。ListView
最簡單的寫法,因為我們在開發中用到這個元件的是一般是從介面拿到資料,並不知道有第多少個
ListView(
scrollDirection: Axis.vertical, //滾動方向
padding: EdgeInsets.all(20.0), //內邊距
// itemExtent:10,
// shrinkWrap: true,//該屬性表示是否根據子元件的總長度來設定ListView的長度,預設值為false 。預設情況下,ListView的會在滾動方向儘可能多的佔用空間。當ListView在一個無邊界(滾動方向
children: <Widget>[
Container(
height: 150,
color: Colors.pinkAccent,
),
Container(
height: 150,
color: Colors.greenAccent,
),
Container(
height: 150,
color: Colors.blueAccent,
),
Container(
height: 150,
color: Colors.black54,
),
Container(
height: 150,
color: Colors.orangeAccent,
),
Container(
height: 150,
color: Colors.cyanAccent,
),
],
),
複製程式碼
更高階的寫法,動態生成
import 'package:flutter/material.dart';
class ListViewDemo extends StatefulWidget {
@override
_ListViewDemoState createState() => _ListViewDemoState();
}
class _ListViewDemoState extends State<ListViewDemo>
with SingleTickerProviderStateMixin {
//定義一個陣列
List list = [
{'name': '1'},
{'name': '2'},
{'name': '3'},
{'name': '4'},
{'name': '5'},
{'name': '6'},
{'name': '7'},
];
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('滾動元件ListView'),
centerTitle: true,
),
body: ListView.builder(
itemCount: list.length, //陣列長度
itemBuilder: (context, index) {//上下文和索引
return Container(//返回一個容器元件
height: 150,
color: Color.fromRGBO(200, 200, index * 30, 1),//這裡是我為了更好分辨
child: Text(list[index]['name']),
);
},
),
);
}
}
複製程式碼
GridView
這個和上面的大同小異,不做過多講述。
import 'package:flutter/material.dart';
class GridViewDemo extends StatefulWidget {
@override
_GridViewDemoState createState() => _GridViewDemoState();
}
class _GridViewDemoState extends State<GridViewDemo>
with SingleTickerProviderStateMixin {
List list = [
Icons.ac_unit,
Icons.airport_shuttle,
Icons.all_inclusive,
Icons.tag_faces,
Icons.beach_access,
Icons.cake,
Icons.free_breakfast,
];
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('網格滾動GridView'),
centerTitle: true,
),
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 1.0,
),
itemCount: list.length,
itemBuilder: (context, index) {
// return Text(list[index].toString()+'222');
return Icon(list[index]);
},
),
// GridView(
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 3, //橫軸三個子widget
// childAspectRatio: 1.0 //子元素在橫軸長度和主軸長度的比例。由於crossAxisCount指定後,子元素橫軸長度就確定了,然後通過此引數值就可以確定子元素在主軸的長度
// ),
// children: <Widget>[
// Icon(Icons.ac_unit),
// Icon(Icons.airport_shuttle),
// Icon(Icons.all_inclusive),
// Icon(Icons.beach_access),
// Icon(Icons.cake),
// Icon(Icons.free_breakfast)
// ],
// ),
// GridView.count(//和上面相同 寫法不一樣而已
// crossAxisCount: 3,
// childAspectRatio: 1.0,
// children: <Widget>[
// Icon(Icons.ac_unit),
// Icon(Icons.airport_shuttle),
// Icon(Icons.all_inclusive),
// Icon(Icons.beach_access),
// Icon(Icons.cake),
// Icon(Icons.free_breakfast),
// ],
// ),
);
}
}
複製程式碼
進階知識(這個會慢慢新增,下個應該是http請求封裝)
路由?怎麼進行路由配置管理?
這裡不說Navigator.pushNamed(context, '/路徑')這些,這裡主要講的是將路由進行統一管理配置。
第一種 直接在入口檔案配置
import 'package:flutter/material.dart';
/* 引入頁面 */
import './page/homePage.dart';
import './page/404.dart';
/* demo */
import './demo/index.dart';
import './demo/text.dart';
import './demo/button.dart';
import './demo/imgAndIcon.dart';
import './demo/input.dart';
import './demo/container.dart';
import './demo/row.dart';
import './demo/column.dart';
import './demo/stackPositioned.dart';
import './demo/listView.dart';
import './demo/gridView.dart';
import './demo/customScrollView.dart';
/* 定義路由路徑 */
final routes = {
'/': (context) => MyHomePage(),
'/notFind': (context) => NotFind(),
/* demo */
'/demoEntry': (context) => DemoEntry(),
'/textDemo': (context, {arguments}) => TextDemo(),
'/buttonDemo': (context, {arguments}) => ButtonDemo(),
'/imgAndIcon': (context, {arguments}) => ImgAndIcon(),
'/inputDemo': (context, {arguments}) => InputDemo(),
'/containerDemo': (context, {arguments}) => ContainerDemo(),
'/rowDemo': (context, {arguments}) => RowDemo(),
'/columnDemo': (context, {arguments}) => ColumnDemo(),
'/stackPositionedDemo': (context, {arguments}) => StackPositionedDemo(),
'/listViewDemo': (context, {arguments}) => ListViewDemo(),
'/gridViewDemo': (context, {arguments}) => GridViewDemo(),
'/customScrollViewDemo': (context, {arguments}) => CustomScrollViewDemo(),
};
/* 路由攔截(這裡可以對跳轉的路由引數等進行處理) */
Function onGenerateRoute = (RouteSettings settings) {
final String routeName = settings.name;
final Function buildContext = routes[routeName];
Route route;
print(buildContext);
if (buildContext != null) {
//如果路由存在
if (settings.arguments != null) {
//如果有路由傳參的話
route = MaterialPageRoute(
builder: (context) =>
buildContext(context, arguments: settings.arguments));
} else {
route = MaterialPageRoute(builder: (context) => buildContext(context));
}
} else {
//路由不存在跳到指定頁面
route =
MaterialPageRoute(builder: (context) => routes['/notFind'](context));
}
return route;
};
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
routes:
routes, //這個是下面那個兩個有一個就可以,不過下面的onGenerateRoute可以進行攔截,兩個同時使用的話只有routes會生效
onGenerateRoute: onGenerateRoute,
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/', //入口路由
);
}
}
複製程式碼
第二種 另起一個路由配置檔案(推薦)
最好是將路由放在另外的檔案方便進行管理,我們只需要在主入口檔案引入路由檔案就可以。 router.dart檔案
import 'package:flutter/material.dart';
import '../page/homePage.dart';
import '../page/404.dart';
/* demo */
import '../demo/index.dart';
import '../demo/text.dart';
import '../demo/button.dart';
import '../demo/imgAndIcon.dart';
import '../demo/input.dart';
import '../demo/container.dart';
import '../demo/row.dart';
import '../demo/column.dart';
import '../demo/stackPositioned.dart';
import '../demo/listView.dart';
import '../demo/gridView.dart';
import '../demo/customScrollView.dart';
final routes = {
'/': (context) => MyHomePage(),
'/notFind': (context) => NotFind(),
/* demo */
'/demoEntry': (context) => DemoEntry(),
'/textDemo': (context, {arguments}) => TextDemo(),
'/buttonDemo': (context, {arguments}) => ButtonDemo(),
'/imgAndIcon': (context, {arguments}) => ImgAndIcon(),
'/inputDemo': (context, {arguments}) => InputDemo(),
'/containerDemo': (context, {arguments}) => ContainerDemo(),
'/rowDemo': (context, {arguments}) => RowDemo(),
'/columnDemo': (context, {arguments}) => ColumnDemo(),
'/stackPositionedDemo': (context, {arguments}) => StackPositionedDemo(),
'/listViewDemo': (context, {arguments}) => ListViewDemo(),
'/gridViewDemo': (context, {arguments}) => GridViewDemo(),
'/customScrollViewDemo': (context, {arguments}) => CustomScrollViewDemo(),
};
/* 路由攔截 */
Function onGenerateRoute = (RouteSettings settings) {
final String routeName = settings.name;
final Function buildContext = routes[routeName];
Route route;
// print(buildContext);
if (buildContext != null) {
if (settings.arguments != null) {
route = MaterialPageRoute(
builder: (context) =>
buildContext(context, arguments: settings.arguments));
} else {
route = MaterialPageRoute(builder: (context) => buildContext(context));
}
} else {
route =
MaterialPageRoute(builder: (context) => routes['/notFind'](context));
}
return route;
};
複製程式碼
主入口檔案
import 'package:flutter/material.dart';
import './router/router.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
// routes: routes,
onGenerateRoute: onGenerateRoute,
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/',
);
}
}
複製程式碼
第二種是不是看起來好看的多了
http請求封裝(暫時還沒有,還在弄)
吐槽
包括環境安裝(還是在自己的玩遊戲電腦上安裝了這些),寫demo等,前前後後也搞了快一天的時間(可能是我太垃圾了),所以覺得文章有點幫助的,求求給個贊!!!
覺得文章太廢的,求求給點意見,謝謝大家
這裡附上自己寫的另外一篇文章Flutter踩坑日記和github地址