flutter筆記7:flutter頁面佈局基礎,看完這篇就能夠用flutter寫APP了

不知不覺已經到了第7篇,然而不少萌新玩家可能仍是不知道如何堆砌控件,像用CSS同樣搭出漂亮的APP界面,我也同樣,紅紅火火恍恍惚惚,直到今天含淚讀完Flutter佈局基礎,彷彿打開了一個全新的世界。html

基本概念

在flutter中,一切皆控件!一切皆控件!一切皆控件!緊緊記住這個概念。Text是控件,Image是控件,Icon是控件,佈局腳手架也Scaffold也是控件,甚至整個APP也是控件。前端

用戶自定義控件分爲有狀態控件和無狀態控件兩種類型,其特性在前面的筆記4中能夠感覺感覺。git

flutter的內置控件分爲兩種:github

  • 可視控件(visible widget)。即咱們直接看到的控件,如text、Icon、Button,名稱理解和html標籤相同。
  • 佈局控件(layout widget)。能夠理解爲架子,如Row、Column、Container。佈局控件不會直接呈現內容,可看做承載可視控件的容器。全部的佈局控件都有承載子控件的屬性:childchildrenchild可承載單個子控件,children可承載多個子控件。每一個佈局控件有默認的佈局方式,使其子控件按照本身的樣式安放到位子上。佈局控件提供了各類樣式的參數,可實現子控件的對齊(align)、縮放(size)、包裝(pack)和嵌套(Nest)。簡單總結爲:佈局控件是爲了實現可視控件的各類視覺效果而作的包裝,好比前端的html爲了實現sticky、雙飛翼、聖盃等佈局經常內容區外層添加div包裹層。

佈局控件也是能夠模擬顯示的,一般用於調試佈局樣式時用到的網格線、標尺、動畫幀等。啓用方式:
1.在main.dart中,引入包:web

import 'package:flutter/rendering.dart' show debugPaintSizeEnabled;

2.在main函數中打開開關:app

void main() {
  debugPaintSizeEnabled = true;      //打開視覺調試開關
  runApp(new MyApp());
}

運行代碼後APP效果以下:
視覺調試模式下的APP界面函數

flutter的內置控件已經定義了不少屬性,玩家能夠參考Widgets Catalog瞭解每種控件的詳細屬性和用法。本篇經過幾個例子,介紹頁面上的控件如何堆砌和佈局。工具

彆着急,因爲下面的案例中,可能用到圖片,先交待一下加載圖片的基本配置方法:佈局

  1. 到項目根目錄下建立一個文件夾,命名:images,將圖片放置到該文件夾中。
  2. 打開根目錄下的pubspec.yaml文件,在其下添加註釋中的屬性:
flutter:
  uses-material-design: true
  assets:                            //若是沒有這個屬性則添加到flutter標籤下
    - images/lake.jpg          //聲明圖片的路徑
  1. 到代碼中,以image控件的方式引用圖片:
new Image.asset(
              'images/lake.jpg',        //圖片的路徑
              width: 600.0,              //圖片控件的寬度
              height: 240.0,            //圖片控件的高度
              fit: BoxFit.cover,        //告訴引用圖片的控件,圖像應儘量小,但覆蓋整個控件。
            ),

案例

控件的排列

行(Row)和列(Column),是flutter中最經常使用的兩個佈局控件,他們只能容納當前屏幕尺寸大小的內容,若是其內部的子控件超出屏幕尺寸,不但不會自動生成滾動條,還會報錯。學習

案例1-行排列
橫向排列

如圖上圖所示,圖中有3個100px寬的圖片,經過水平平均間隔的方式居中橫向排列顯示到一行中,代碼示例:

new Center(                //居中控件
  child: new Row(        //行控件
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,      //對齊方式:平均間隔
    children: [
      new Image.asset('images/pic1.jpg'),        //引入三張圖片
      new Image.asset('images/pic2.jpg'),
      new Image.asset('images/pic3.jpg'),
    ]
  )
)

能夠看到上圖用到了2個佈局控件Center和Row,經過Center包裹Row,使行控件保持居中,而ROW控件包裹了3個圖片控件Image,經過配置Row的mainAxisAlignment對齊屬性,使三個圖片空間經過平均間隔的方式進行橫向排列。

完整代碼:
Dart code: main.dart
Images: images
Pubspec: pubspec.yaml

案例2-列排列
縱向排列

如上圖所示,仍是那3張圖,經過縱向平均間隔的方式顯示到一列中,代碼以下:

new Center(
  child: new Column(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,        //對齊方式:平均間隔
    children: [
      new Image.asset('images/pic1.jpg'),
      new Image.asset('images/pic2.jpg'),
      new Image.asset('images/pic3.jpg'),
    ]
  )
)

完整代碼:
Dart code: main.dart
Images: images
Pubspec: pubspec.yaml

對比案例1和2能夠看到,代碼結構相同,Row和Column中都用到了mainAxisAlignment屬性,除此之外還有crossAxisAlignment屬性。值得注意的是,在Row中mainAxisAlignment控制水平方向對齊,crossAxisAlignment控制垂直方向對齊,而在Column中則正好相反。相關參數值請參考MainAxisAlignmentCrossAxisAlignment

佈局控件的嵌套

案例3-行列嵌套
行列嵌套

如上圖,咱們將圖中的元素按圖中的框線進行分解:

1.最外層的使用Row控件包裹,使其內部的兩個子控件:淺藍色框的菜品介紹和右邊的菜品大圖橫向排列,代碼以下:

new Scaffold(                                                                              //腳手架控件
      appBar: new AppBar(                                                            //工具欄控件
        title: new Text(widget.title),
      ),
  body: new Center(
  child: new Container(                                                                 //Container控件用於調整外邊距
    margin: new EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 30.0),        
    height: 600.0,
    child: new Card(                                                                       //Card控件控制卡片的視覺效果
      child: new Row(                                                                     //Row控件使其子控件橫向排列
        crossAxisAlignment: CrossAxisAlignment.start,                  //縱向對齊方式:起始邊對齊
        children: [
          new Container(                                                                  //Container控件用於調整寬度
            width: 440.0,   
            child: leftColumn,                                                            //左邊的菜品介紹控件
          ),
          mainImage,                                                                        //右邊的大圖控件
        ],
      ),
    ),
  ),
)
)

2.把淺藍色框內的信息,用Column包裹,使其內容垂直排列:

new Container(
      padding: new EdgeInsets.fromLTRB(20.0, 30.0, 20.0, 20.0),
      child: new Column(                                                                    //Column控件,使其子控件垂直排列
        children: [
          titleText,        //標題行,包含了可視Text控件
          subTitle,        //副標題行,包含了可視Text控件
          ratings,         //投票信息行
          iconList,        //小圖標行
        ],
      ),
    );

3.因爲titleText和subTitle都是簡單的包裝了Text控件,再也不貼代碼和註釋,重點講下ratings和iconList:
ratings和iconList控件

ratings和iconList控件是垂直排列的兩行,而各自內部有本身的佈局信息,所以將這兩行分別拆解爲:

ratings

ratings下包含了兩個水平排列:Row控件用於顯示星級,Text控件用於顯示用戶瀏覽數,而評分星級控件ROW又分解爲5個水平排列的Icon控件。

iconList控件結構

iconList橫向排列了3個縱向顯示的控件,層次一目瞭然。

對照代碼結構:

//ratings控件
new Container(
      padding: new EdgeInsets.all(20.0),
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          new Row(
            mainAxisSize: MainAxisSize.min,       //mainAxisSize,可壓縮或伸長行內控件的間距
            children: [
              new Icon(Icons.star, color: Colors.black),
              new Icon(Icons.star, color: Colors.black),
              new Icon(Icons.star, color: Colors.black),
              new Icon(Icons.star, color: Colors.black),
              new Icon(Icons.star, color: Colors.black),
            ],
          ),
          new Text(
            '170 Reviews',
            style: new TextStyle(
              color: Colors.black,
              fontWeight: FontWeight.w800,
              fontFamily: 'Roboto',
              letterSpacing: 0.5,
              fontSize: 20.0,
            ),
          ),
        ],
      ),
    )

//iconList控件
new Container(
        padding: new EdgeInsets.all(20.0),
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            new Column(
              children: [
                new Icon(Icons.kitchen, color: Colors.green[500]),
                new Text('PREP:'),
                new Text('25 min'),
              ],
            ),
            new Column(
              children: [
                new Icon(Icons.timer, color: Colors.green[500]),
                new Text('COOK:'),
                new Text('1 hr'),
              ],
            ),
            new Column(
              children: [
                new Icon(Icons.restaurant, color: Colors.green[500]),
                new Text('FEEDS:'),
                new Text('4-6'),
              ],
            ),
          ],
        ),
      )

Row和Column能夠相互包裹,使頁面可以實現整齊的佈局,只因其特性老是橫向或縱向充滿父控件,好比最外層使用時,會自動充滿全屏幕。可是當頁面內容須要超出屏幕尺寸時,就用ListTileListView代替。

最終顯示效果

完整代碼(因爲手機屏幕尺寸沒法適應此案例,運行後長和寬都會報溢出錯誤,你們最好使用平板虛擬機測試此案例,或者調整代碼中的字體大小和控件尺寸,以知足顯示要求):
Dart code: main.dart
Images: images
Pubspec: pubspec.yaml

控件的縮放

案例4-縮放
子控件縮放

上圖中,三個橫向排列的圖片控件,中間控件的尺寸比兩邊的大一倍,代碼以下:

new Center(
  child: new Row(
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      new Expanded(
        child: new Image.asset('images/pic1.jpg'),
      ),
      new Expanded(              //使用Expanded控件對Image控件進行包裹
        flex: 2,                 //flex值默認爲1,這裏改爲2以後,其子控件2倍放大
        child: new Image.asset('images/pic2.jpg'),
      ),
     new Expanded(
        child: new Image.asset('images/pic3.jpg'),
      ),
))

完整代碼:
Dart code: main.dart
Images: images
Pubspec: pubspec.yaml

因爲處理邏輯和佈局樣式都一塊兒書寫到代碼中,加上控件的嵌套,flutter的代碼會如同html的標籤同樣嵌套不少層,對前端開發者可能須要時間適應,但對我這種新萌來講下降了從CSS和處理代碼之間來回對照的麻煩,而且flutter的內置控件默認的樣式已經十分整潔,無需單獨再學習相似前端CSS處理頁面佈局的語法和結構,整體來講下降了很多學習成本,上手更快更簡單。能在短期內掌握生產技能,成就感油然而生,天然有繼續學下去的動力。

以上即是最基礎的排列布局介紹,相信看到這裏的小夥伴已經明白怎麼寫APP了,今天就到這裏~感謝你們支持!
flutter 中文社區(官方QQ羣:338252156)

相關文章
相關標籤/搜索