接上篇,我們新建一個Flutter Project:
flutter項目中有android、ios、lib等目錄,可能剛開始有不少同學建完項目,就直奔android目錄準備開發了,但其實,flutter的編程目錄是在lib下的,所有編程文件後綴都爲.dart,我們也可以把其看做安卓開發時.java以及java目錄,可以更好的理解!
其中的pubspec.yaml這個文件很重要,類似於安卓開發時app目錄下的build.gradle,我們在引用一些第三方的工具或插件時都要在該文件中聲明,如下圖:
引入後點擊右上角的Pakage get,就可以獲取該包,然後再項目中引入該包路徑,就可以使用裏面提供的方法了。
在新建的flutter項目的lib目錄下,都會有一個mian.dart,這個就是程序的入口,裏面提供的有示例,在我們着手開始寫代碼之前,還是 有必要去了解一下Flutter UI方面的一些知識。
- dart導入包跟java一樣,用import關鍵字,當你輸入import時,AS會自動提示很方便;
- 如java一樣,dart同樣用class聲明類,extends繼承類;
- java的精髓是萬物皆對象,flutter的精髓是萬物皆組件,所以你在開發flutter時會經常用到Widget;
- Widget可以理解爲安卓中的View;
- 更多內容可以去官網學習
我們在佈局一個界面的UI時經常要用到兩個類:StatelessWidget和StatefulWidget:
StatelessWidget表示靜態頁面,就像我們常說的寫死的,不會有改變的;而StatefulWidget是動態的,也就是UI會根據數據的改變做出動態響應的;我們看到主程序裏面第一個組類就是StatelessWidget:
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'),
);
}
}
build方法中返回的Widget 就像是該界面整個UI的一個最頂級的ViewGroup,像一個底板,然後裏面的接下來的所有組件都會在這個group中一層套一層的佈局;另外,這個結構看起來似曾相識啊:
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
區別就是,安卓中我們用xml佈局,而Flutter中我們要用代碼佈局,UI中的所有組件我們都要用代碼一個一個實現,是不是有種想放棄的感覺,哈哈!
MaterialApp就是Material風格的app了,做安卓開發的再熟悉不過了,裏面的屬性大家可以自行查看官網說明,重點說home這個屬性:字面意思,家,就是這個界面的家,在home中也就需要我們根據UI設計去一點一點佈局了;
home: MyHomePage(title: 'Flutter Demo Home Page'),
MyHomePage繼承了StatefulWidget,說明這個界面是一個動態的;我們需要知道,安卓開發中,我們可以直接去操控view,改變view的屬性,但Flutter中卻不能,我們需要通過數據的改變去重繪UI,也就是我們只能改變數據,而不能直接操控組件,跟微信小程序開發是一樣的道理;
而實現要實現動態界面,StatefulWidget和State兩個類是緊緊相連的:
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
),
body: Center(
));
}
}
MyHomePage 重寫createState方法,返回State(_MyHomePageState ),接下來該界面所使用的變量,方法等都可以在_MyHomePageState 類中聲明,改變UI則可以通過方法 setState:
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
而真正佈局的開始,則是在_MyHomePageState 的Widget build(BuildContext context)方法中:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
),
body: Center(
));
}
Scaffold 實現了Material風格的佈局及組件,僅從佈局意義上講,我們仍然可以把其理解爲一個ViewGroup,主要屬性說明:
- appBar:Material 的標題欄;
- body:UI主要內容(標題欄以下)
- floatingActionButton: 在 Material 中定義的一個功能按鈕;
- persistentFooterButtons:固定在下方顯示的按鈕;
- drawer:側邊欄;
- bottomNavigationBar:底部導航欄;
- backgroundColor:背景顏色;
- resizeToAvoidBottomPadding: 控制界面內容 body是否重新佈局來避免底部被覆蓋了,比如當鍵盤顯示的時候,重新佈局避免被鍵盤蓋住內容;
對於組件的聲明我們可以前面加上new如: new Text(‘標題’),也可以不加如:Text(‘標題’),所以大家在看到不同項目中有的有new,有的沒有時不要疑惑,沒有任何區別;接下來,我們來了解一下常用的一些組件:
- 文本:Text;
- 輸入框:TextField;
- 列表:ListView;
- divider:Divider;
- 邊框:BoxDecoration;
- 包裹容器:Container;
- 水平佈局容器:Row;
- 垂直佈局容器:Column;
- 可伸縮佈局容器:Flexible;
- 圖片:Image;
等等…不在過多羅列,各種組件都有其對應的各種屬性如:margin,padding,width,heigth等等;
下面我們來實現一個上面是內容,底部是輸入框的這麼一個界面:
class _MyHomePageState extends State<MyHomePage> {
TextEditingController _textController = new TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: new Column(children: <Widget>[
new Text("Hello World"),
new Divider(height: 1.0), //分界線
new TextField(
controller: _textController,
decoration: new InputDecoration.collapsed(hintText: '請輸入消息'),
)
]));
}
}
先用最簡單的實現,首先思考佈局,上面是內容,下面是輸入框,這類似於LinlearLayout的垂直佈局,那麼在flutter中我們可以用Column來實現,需要注意的是:Column和Row容器中可以有多個子Widget,也就相當於可以有多個子View,類似於LinearLayout,RelayLayout等,對應的屬性是children,字面意思:孩子們,而像Container,Flexible等容器中只能有一個組件,類似於ScrollView,對應的屬性是child,對比children意思一目瞭然,而Text,Image等組件跟安卓中想同,爲最小View,他們中不能再有組件;
另外注意組件的書寫方式:
child:組件(
屬性:xx,
屬性:xx,
),
children: <Widget>[
組件(
屬性:xx,
child:組件(
屬性:xx,
child:xx,
),
),
組件(
屬性:xx,
屬性:xx,
),
]
所有屬性以及組件間用逗號“,”隔開,並注意屬性及組件的層次遞進;
輸入框TextField實現時需要一個控制器TextEditingController,再類中聲明一下即可,過後我們就可以用這個對象實現獲取輸入框中的內容,清空輸入框的內容等一系列操作了;
運行程序,效果如下:
本篇講述了flutrer項目結構,佈局規則,及不同組件的作用及使用方法,大家對Flutter項目的開發有一個最基本的瞭解之後,下一篇將繼續講解如何實現一個Flutter版的聊天機器人。