用Flutter實現小Q聊天機器人(二)

接上篇,我們新建一個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版的聊天機器人。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章