flutter是一款移動應(yīng)用跨平臺框架,使用Dart語言編寫的一份代碼可以生成iOS和Android兩個高性能、高保真的應(yīng)用程序。Flutter不借助原生的渲染能力,而是自己實現(xiàn)了一套與Android和iOS一樣的渲染原理,從而在性能上與原生平臺基本保持一致。目前Flutter支持了iOS、Android,Windows、linux、macOS、Web平臺的運行。
1、項目創(chuàng)建
開發(fā)flutter應(yīng)用,我們通常使用的工具是Android Studio。創(chuàng)建一個flutter項目,可以通過Android Studio來創(chuàng)建,也可以通過命令行來創(chuàng)建。
1.通過Android Studio來創(chuàng)建
- 啟動
Android Studio,找到Create New Flutter Project; - 然后會來到一個讓選擇項目類型的頁面
Flutter Application、Flutter Plugin、Flutter Package、Flutter Module;選擇Flutter Application; - 輸入
Project name、Flutter SDK path、Project location信息,點擊下一步,然后等待一小會即可創(chuàng)建成功。
注意事項:
1.Flutter Application-全新的App,包含標準的Dart與Native層;Flutter Module-混編到已有的Android/iOS工程內(nèi);Flutter Plugin-平臺插件,包含Dart與Native層的實現(xiàn);Flutter Package-純Dart工程,僅有Dart層實現(xiàn)。
2.需要注意的是Project name只能只用小寫字母或者下劃線;
2.通過命令行創(chuàng)建
/*創(chuàng)建Flutter Application*/
flutter create appname
/*創(chuàng)建Flutter Module*/
flutter create -t module appname_module
/*創(chuàng)建Flutter Plugin*/
flutter create --template=plugin appname_plugin
/*創(chuàng)建Flutter Package*/
flutter create --template=package appname_package
在創(chuàng)建項目的過程中可以指定
Android和iOS的平臺開發(fā)語言:-i objc或-i swift可指定iOS平臺是OC還是Swift;-a java或-a kotlin可指定Android是Java還是Kotlin。更多選項可以通過flutter create --help來查看。
創(chuàng)建好的項目,包括android,ios,lib等目錄,main函數(shù)和我們開發(fā)寫的Dart代碼都在lib目錄中。
2、基礎(chǔ)語法
基礎(chǔ)類型:
- num
包括int & double
int.isEven, int.isOdd;
int.toDouble;double.toInt();
double.round();//常用函數(shù)
- String:
var a = "today";var b = "hello", var c = a + b; //字符串拼接
a[0];//取第一個字符; a*2;//字符串a(chǎn)的內(nèi)容重復2遍
print("a + b = ${ a + b}")//{放運算表達式}
- list
創(chuàng)建可變list: var list = [1,2,3,"name"]
創(chuàng)建不可變list:var list = const [1,2,3,"name"]
按下標訪問list[2]="xyz"
添加/刪除元素list.add("xxx"); list.insert(1,"cat");list.remove("cat");list.clear();
排序:list.sort()
截取:list.sublist(5,7)//從4到7,前閉后開,包含3個元素
- Map
創(chuàng)建可變Map: var map = {"name":"ccc", "age":244};
創(chuàng)建不可變Map:var map =const {"name":"ccc"};
按鍵訪問 map["name"] = "520";
var list = ["ccc", "255"]; list.asMap()//{0:"ccc", 1:244}
- ??=, ??
var a; a ??= 5; a=10; //如果a為nil就賦值,否則直接返回
var b; print("${b ?? 5}")//如果b有值,直接返回,反之取??后面的
- =>箭頭函數(shù)
- 可選參數(shù),空安全
- 匿名函數(shù)
- 閉包:定義在函數(shù)里面的的函數(shù)就是閉包,閉包也是一個對象,可以訪問外部函數(shù)的局部變量。
func() {
int count = 0;
return ()=>print(count++);
}
let func1 = func();
func1();func1();func1();func1();//分別打印1/2/3/4
let func2 = func();
func2();func2();func2();func2();//分別打印1/2/3/4
flutter項目使用的dart語言,其基礎(chǔ)語法與Swift和Kotlin非常接近。
接下來我們簡單列舉一個例子,定義一個Worker類
class Worker {
//定義靜態(tài)變量:格式:類型 變量名 = 初始值
//在外部通過 = Worker.key; Worker.key = "22"進行讀寫 (類似于swift的 static var key = "worker")
//在內(nèi)不通過 = key;key = ""進行讀寫
//static String _i = "111";如果帶下劃線將不能被外部訪問
static String key = 'Worker';
//定義成員變量:格式:類型 變量名 = 初始值
//如果成員變量不給初始值,那么需要指定該成員變量是空安全(null-safety,跟swift的可選類型類似)或者指定為構(gòu)造函數(shù)參數(shù)
//如果成員邊量帶下劃線,表示該成員變量盡在該文件內(nèi)可以訪問。(跟swift的fileprivate類似)
//const常量:在編譯期確定變量測值,不可用運行態(tài)的內(nèi)容來賦值,如時間戳/隨機數(shù);賦值后不可修改。在申明的時候就需要賦值。
//final最終變量:賦值一次后不可以改變,可以賦值為時間戳和隨機數(shù)等。如果沒有賦值不能使用。
String name = '';
String _nickname = '';
int? height;////未初始化的變量指向null
int? age;//未初始化的變量指向null
//構(gòu)造函數(shù)
//同名的參數(shù)(可以簡寫成如下方式,私有成員變量不可以)
Worker(this.name,this.height, String _nickname){
this._nickname = _nickname;
}
//函數(shù):返回值 函數(shù)名 (參數(shù)列表)
//帶前置下劃線的函數(shù)不能被外部訪問,與帶下劃線的的成員變量相同
int printAll() {
print(
'printAll:key=$key, name=$name, _nickname=$_nickname, height=$height, age=$age');
return 8;
}
int _printAll(){
print('_printAll:key=$key, name=$name, _nickname=$_nickname, height=$height, age=$age');
return 9;
}
}
調(diào)用部分如下:
void main() {
Worker.key = "222";
print(Worker.key);
Worker worker = Worker("name", 19, "nickname");
worker.printAll();
}
3.基礎(chǔ)結(jié)構(gòu)
flutter項目從main啟動后,調(diào)用runApp(),即可將UI載入:
void main() {
runApp(TextWidget());
}
//在widget中我們重載Widget build(BuildContext context)函數(shù),返回創(chuàng)建的widget
class TextWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(44),
color: Colors.yellow,
child: Text(
"Hello Flutter",
textAlign:TextAlign.center,/*文本居中顯示*/
textDirection:TextDirection.ltr,/*文字閱讀順序*/
style: TextStyle(
color: Colors.red,/*文字顏色*/
fontSize: 40/*文字大小*/
)
)
);
}
}
flutter中MaterialApp代表Material Design風格的應(yīng)用,內(nèi)部包含該風格應(yīng)用所需要的基本控件, 其home屬性應(yīng)用的根節(jié)點。Scaffold名為腳手架,為應(yīng)用提供了導航欄、Tab等:
- appBar:導航欄NavigationBar位居頁面最頂部
- bottomNavigationBar:標簽欄Tabbar,位居頁面最底部
- body:除appBar/bottomNavigationBar以外的屏幕中間區(qū)域
接下來,我們把這些基礎(chǔ)組建給弄出來看看:
void main() {
runApp(const App());
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner:false,
home: Scaffold(
appBar: AppBar(
title: Text('Explorer App')
),
body: TextWidget()
)
);
}
}
這樣我們后面做基礎(chǔ)組建的學習只需要修改Scaffold.body即可。
4.布局控件
在原生開發(fā)中我們常用frame、AutoLayout布局,在h5項目中我們常用flex布局。在flutter開發(fā)中,Dart為我們提供了類似flex布局Row,Column, Stack等。
4.1 Row、Column表示一組平面上排列的元素
其中Row主軸mainAxisAlignment是從屏幕左側(cè)到右側(cè),交叉軸從屏幕頂部到下方;Column主軸crossAxisAlignment從屏幕的上方到下方,交叉軸是從屏幕的左側(cè)到右側(cè)。
-
mainAxisAlignment變量-主軸
start-元素居左/居上顯示,元素之間間距為0,多余的空間居右/下;
center-元素居中顯示,元素間艱巨為0,多余的空間一分為二居左右/上下;
end-元素居右/下顯示,元素之間間距為0,多余的空間居左/上;
spaceBetween-元素分開顯示,多余的空間分配到元素與元素之間;
spaceAround-整體空間按照元素的個數(shù)均分,多余的空間顯示在元素的左右/上下兩側(cè);
spaceEvenly-將多余的空間均分于左+元素之間+右/上+元素之間+下;
Row布局(cross軸為center)
Column布局(cross軸為center)
-
CrossAxisAlignment變量-交叉軸:
start:元素居上/左顯示;
center:元素居上下居中/左右居中;
end:元素居下/右顯示
stretch:元素拉伸
baseline:用于Text基線對齊
Row布局(main軸為center)
Column布局(main軸為center)
Row布局的主軸為x+方向,交叉軸為y+方向;Column的主軸為y+方向,交叉軸為x+方向。搞清楚這兩個最常用的布局,開發(fā)中如魚得水。
4.2.Stack一組垂直于屏幕排列的元素,
整組處于父容器中的位置通過alignment來確定,alignment接受一個AlignmentDirectional類型的對象,該對象兩個屬性start,y分別表示處在x軸,y軸上的位置。內(nèi)部定義父視圖x軸方向起點為-1,中點為0,右側(cè)為1,父視圖y軸方向起點為-1,中點為0,右側(cè)為1。該類也有一些常用的位置定義,比如
/// The center point, both horizontally and vertically.
///
/// Consider using [Alignment.center] instead, as it does not need to
/// be [resolve]d to be used.
static const AlignmentDirectional center = AlignmentDirectional(0.0, 0.0);
該布局用起來相對簡單:
Stack布局
5.繼承、混入
abstract class Worker {
void work(){print("Person->work");}
}
mixin MixinWorker implements Worker {
void mixinWork(){print("MixinWorker->mixinWork");}
}
extension ExtensionWorker on Worker {
void extensionWork(){print("ExtensionWorker->extensionWork");}
}
class Developer extends Worker {
void develop(){print("Developer-> develop");}
@override work(){print("Developer-> work");}
//__test(){
Developer d = Developer("", 0, "");
d.work();
d.delelop();
d.extensionWork();
//d.mixinWork();//error
}
}