Flutter 即學即用系列部落格——06 超實用 Widget 集錦

AndroidTraveler發表於2019-03-04

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

本篇文章我們來講講一些比較常用的 Widget。

大家驗證的時候使用下面的程式碼替換 main.dart 程式碼,然後在 //TODO 語句返回下面常用 Widget 示例的程式碼。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: _buildWidget(),
        ),
      ),
    );
  }

  Widget _buildWidget() {
    //TODO
  }

}

複製程式碼

目錄

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

1. Text

1)基本使用

return Text('Show Regular Text');
複製程式碼

2)設定字型樣式

屬性:style

設定粗體:

return Text(
      'Show Bold Text',
      style: TextStyle(fontWeight: FontWeight.bold),
    );
複製程式碼

設定顏色:

return Text(
      'Show Bold Red Text',
      style: TextStyle(fontWeight: FontWeight.bold, color: Colors.red),
    );
複製程式碼

其他樣式相信大家學習過之前的文章,知道如何檢視一個 Widget 原始碼以及如何使用了。

3)設定最大行數及省略號

屬性:maxLinesoverflow

return Container(
      width: 100,
      child: Text(
        '設定文字超過 100,這樣能夠看到效果,這裡設定最多顯示一行',
        maxLines: 1,                      //設定最大行數
        overflow: TextOverflow.ellipsis,  //設定超過顯示省略號
      ),
    );
複製程式碼

大概效果如下:

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

2. Image

1)本地載入圖片

第一步:建立放置圖片的資料夾,這裡假設我們在 my_flutter 下面建立 assets/images/2.0xassets/images/3.0x 資料夾用於存放本地圖片。

第二步:拷貝圖片 wechat.png 到上述資料夾,一般如果切圖是用 sketch,則直接選擇對應的 2 倍圖和 3 倍圖。

第三步:在 pubspec.yaml 檔案確定要使用的圖片資源位置。這裡可以定義如下:

assets:
    - assets/images/wechat.png
複製程式碼

第四步:使用如下。

return Image.asset('assets/images/wechat.png')
複製程式碼

可能有小夥伴會覺得,如果我有很多圖片需要使用,是不是每次執行第三步和第四步的時候都要寫那麼長的路徑。

先說下第四步,如果你都是同個目錄,只是最後圖片名稱不一樣。那麼你可以自定義一個包裝類做一層包裝。

接著我們來說下第三步的情況。

假設你有很多圖片在同一個資料夾下面,那麼你是可以在 pubspec.yaml 裡面使用目錄定義的。但是,注意官方文件的一句話:

Note that only files located directly in the directory will be included; to add files located in subdirectories, create an entry per directory.

簡單的說就是你使用的目錄要到最底層,也就是這個目錄下面就是圖片而不是目錄了。

舉我們這個例子就是如果你要用目錄定義及使用,上面第三步替換為

assets:
    - assets/images/2.0x/
複製程式碼

第四步替換為

return Image.asset('assets/images/2.0x/wechat.png');
複製程式碼

可以看到這樣我們如果一張圖片要適配不同尺寸估計就不是很合適了。

因此對於有適配場景的,其實推薦第一種直接配置指定圖片的方式。

溫馨提示:

修改 pubspec.yaml 檔案之後建議執行之前增加清理工作。

比如之前是執行 flutter run

修改之後建議執行 flutter packages get;flutter clean;flutter run

上面定義的位置可以直接在 pubspec.yaml 檔案搜尋 assets,有註釋講解的位置就是你要新增的位置了。

官網:
https://flutter.dev/docs/development/ui/assets-and-images#loading-images

2)網路載入圖片

給定一個圖片 url,執行下面程式碼即可:

return Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875');
複製程式碼

3)指定寬高

指定寬高是直接使用 widthheight 屬性。

比如網路載入圖片指定寬高如下:

    return Image.network(
      'https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875',
      width: 300,
      height: 200,
    );
複製程式碼

大致效果如下:

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

3. Column

前面兩個講的都是單個小元件。接下來我們講的是類似於佈局的元件。(還是元件,畢竟 Flutter 一切皆 Widget)

1)基本使用

大家看到這個詞,應該會直觀認為這個就是對於一些佈局為列的場景吧,可能有多列,然而不是哦。

點進去原始碼可以看到如下注釋:

/// Creates a vertical array of children.
複製程式碼

大概意思是建立一組垂直的子元件集合。

如果你是 Android 開發,可以聯想到 LinearLayout 裡面的 orientation 設定為 vertical 時的佈局。

如下:

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

你也可以這樣記憶,Column 是列,說明佈局只有一列。所以就是上面這種了。

所以上面的 Text 效果圖和 Image 效果圖應該就知道是如何顯示了吧?

我們這裡給下示例程式碼,當然如果你是用帶劉海屏的裝置執行,可能頂部會看不到。後面我們會繼續說明。

return Column(
      children: <Widget>[
        Image.asset('assets/images/wechat.png'),
        Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875'),
        Image.network(
          'https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875',
          width: 300,
          height: 200,
        )
      ],
    );
複製程式碼

效果如下:

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

寫法也很簡單,就是設定一下 children 屬性就可以了。

然後裡面的 Widget 陣列填充我們要展示的 Widget 即可。

上面說了劉海屏裝置頂部會看不到,那怎麼辦?

2)mainAxisAlignment

mainAxisAlignment 你可以認為是主軸的對齊方式。對於豎直的 Column,那就是豎直方向的對齊。

影響整個 Column

因此可以設定如下:

return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Image.asset('assets/images/wechat.png'),
        Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875'),
        Image.network(
          'https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875',
          width: 300,
          height: 200,
        )
      ],
    );
複製程式碼

你就會發現整個 Column 在豎直方向都居中了。

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

3)crossAxisAlignment

crossAxisAlignment 你可以認為是交叉軸的對齊方式,對於豎直的 Column,那就是水平方向的對齊。

影響 Column 裡面的每一個 Widget

設定如下:

return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.end,
      children: <Widget>[
        Image.asset('assets/images/wechat.png'),
        Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875'),
        Image.network(
          'https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875',
          width: 300,
          height: 200,
        )
      ],
    );
複製程式碼

你會發現原本最後一張居中的圖片在水平方向向右邊對齊。

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

4. Row

1)基本使用

/// Creates a horizontal array of children.
複製程式碼

大概意思是建立一組水平的子元件集合,可以聯想到 LinearLayout 裡面的 orientation 設定為 horizontal 時的佈局。

也可以記憶為 Row 代表行,因此只有一行。

如下:

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

Sample:

return Row(
      children: <Widget>[
        Text('Widget One', style: TextStyle(color: Colors.blue),),
        Text('Widget Two'),
      ],
    );
複製程式碼

效果如下:

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

可以看到只有一行,所以使用 Row。

寫法也是比較簡單,就是設定一下 children 屬性就可以了。

然後裡面的 Widget 陣列填充我們要展示的 Widget 即可。

2)mainAxisAlignment

mainAxisAlignment 你可以認為是主軸的對齊方式,對於水平的 Row,那就是水平方向的對齊。

影響整個 Row

因此可以設定如下:

return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('Widget One', style: TextStyle(color: Colors.blue),),
        Text('Widget Two'),
      ],
    );
複製程式碼

這樣效果顯示就是上圖居中。

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

3)crossAxisAlignment

crossAxisAlignment 你可以認為是交叉軸的對齊方式,對於水平的 Row,那就是豎直方向的對齊。

影響 Row 裡面的每一個 Widget

設定如下:(這裡引入了一個後面才會講到的 Widget,大家可以暫時不理,看下效果)

return Container(
      width: 300,
      height: 300,
      color: Colors.grey,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.end,
        children: <Widget>[
          Container(
            width: 100,
            height: 100,
            color: Colors.blue,
            child: Text(
              'Widget One',
            ),
          ),
          Container(
            width: 100,
            height: 100,
            color: Colors.yellow,
            child: Text(
              'Widget Two',
            ),
          ),
        ],
      ),
    );
複製程式碼

灰色是我們的父容器,可以看到兩個控制元件水平方面居中,豎直方面向下對齊。

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

5. Container

Container 的使用超級廣泛。

我們這裡略微講一下一些使用場景。

1)給一些沒有自頻寬高的屬性設定寬高。

比如我們上面講到 Row 最後一個 Sample 的時候,給 Text、Row 設定寬高都是在外面套一層 Container。

  1. 設定間距。

以上面 Column 的三張圖片為例,他們一開始是下面程式碼:

return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Image.asset('assets/images/wechat.png'),
        Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875'),
        Image.network(
          'https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875',
          width: 300,
          height: 200,
        )
      ],
    );
複製程式碼

效果如下:

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

我們希望第一張和第二張圖片有點距離,可以這樣設定:

return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Image.asset('assets/images/wechat.png'),
        Container(
          padding: EdgeInsets.only(top: 20.0),
          child: Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875'),
        ),
        Image.network(
          'https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875',
          width: 300,
          height: 200,
        )
      ],
    );
複製程式碼

效果如下:

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

我們程式碼裡面使用 Container 都是把 Widget 拿出來作為 Container 的 child。

這裡的 padding 使用有三種常用寫法:

第一種:上下左右 padding 的值都一樣

原始碼:

const EdgeInsets.all(double value)
      : left = value, top = value, right = value, bottom = value;
複製程式碼

第二種:上下左右 padding 不一致或者只想設定某一個或某幾個方向

原始碼:

const EdgeInsets.only({
    this.left = 0.0,
    this.top = 0.0,
    this.right = 0.0,
    this.bottom = 0.0
  });
複製程式碼

第三種:設定水平或者垂直方向的 padding

原始碼:

const EdgeInsets.symmetric({ double vertical = 0.0,
                             double horizontal = 0.0 })
    : left = horizontal, top = vertical, right = horizontal, bottom = vertical;
複製程式碼

相信現在給出原始碼,大家都知道怎麼寫了。

記得花括號是可選引數哈~

Sample:

          padding: EdgeInsets.all(left : 20.0),
          padding: EdgeInsets.only(left : 20.0),
          padding: EdgeInsets.symmetric(horizontal : 20.0),
複製程式碼

margin 和 padding 也是類似的,區別相信學過 Android 的都知道,你也可以自己測試一下區別,這裡就不贅餘了。

另外注意 Container 原始碼有個註釋:

/// The `height` and `width` values include the padding.
複製程式碼

舉個例子就是假設有一張圖片寬 100,假設你左右預留 padding 10,那麼你寬需要設定為 120。

6. SizedBox

你可以用來替換需要套一層 Container 來設定 margin 或者 padding 的 Widget。

比如上面的程式碼

return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Image.asset('assets/images/wechat.png'),
        Container(
          padding: EdgeInsets.only(top: 20.0),
          child: Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875'),
        ),
        Image.network(
          'https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875',
          width: 300,
          height: 200,
        )
      ],
    );
複製程式碼

可以等效替換為

return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Image.asset('assets/images/wechat.png'),
        SizedBox(
          height: 20.0,
        ),
        Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875'),
        Image.network(
          'https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875',
          width: 300,
          height: 200,
        )
      ],
    );
複製程式碼

        Container(
          padding: EdgeInsets.only(top: 20.0),
          child: Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875'),
        ),
複製程式碼

替換成了

        SizedBox(
          height: 20.0,
        ),
        Image.network('https://user-gold-cdn.xitu.io/2019/3/4/169466d552919d6c?w=1240&h=677&f=jpeg&s=162875'),
複製程式碼

當然這裡由於 Widget 沒有限制寬高,所以 padding 或者 margin 在這裡起到一樣作用。

嚴格來說 SizedBox 應該是替換 margin。替換 padding 需要注意上面說的寬高影響。

常用的 Widget 我們就介紹到這裡。

其他的我們後續再介紹或者大家自行查閱官網 Widget 集合。

相信現在的你可以根據官網的 Sample 和說明以及親自測試快速掌握新 Widget 的使用。

官網 Widget 集合:
https://flutter.dev/docs/development/ui/widgets

更多閱讀:
Flutter 即學即用系列部落格——01 環境搭建
Flutter 即學即用系列部落格——02 一個純 Flutter Demo 說明
Flutter 即學即用系列部落格——03 在舊有專案引入 Flutter
Flutter 即學即用系列部落格——04 Flutter UI 初窺
Flutter 即學即用系列部落格——05 StatelessWidget vs StatefulWidget

Flutter 即學即用系列部落格——06 超實用 Widget 集錦

相關文章