本篇文章我們來講講一些比較常用的 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
}
}
目錄
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)設置最大行數及省略號
屬性:maxLines、overflow
return Container(
width: 100,
child: Text(
'設置文本超過 100,這樣能夠看到效果,這裡設置最多顯示一行',
maxLines: 1, //設置最大行數
overflow: TextOverflow.ellipsis, //設置超過顯示省略號
),
);
大概效果如下:
2. Image
1)本地加載圖片
第一步:創建放置圖片的文件夾,這裡假設我們在 my_flutter 下面創建 assets/images/2.0x 和 assets/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)指定寬高
指定寬高是直接使用 width 和 height 屬性。
比如網絡加載圖片指定寬高如下:
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,
);
大致效果如下:
3. Column
前面兩個講的都是單個小組件。接下來我們講的是類似於佈局的組件。(還是組件,畢竟 Flutter 一切皆 Widget)
1)基本使用
大家看到這個詞,應該會直觀認為這個就是對於一些佈局為列的場景吧,可能有多列,然而不是哦。
點進去源碼可以看到如下注釋:
/// Creates a vertical array of children.
大概意思是創建一組垂直的子組件集合。
如果你是 Android 開發,可以聯想到 LinearLayout 裡面的 orientation 設置為 vertical 時的佈局。
如下:
你也可以這樣記憶,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,
)
],
);
/<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,
)
],
);
/<widget>
你就會發現整個 Column 在豎直方向都居中了。
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,
)
],
);
/<widget>
你會發現原本最後一張居中的圖片在水平方向向右邊對齊。
4. Row
1)基本使用
/// Creates a horizontal array of children.
大概意思是創建一組水平的子組件集合,可以聯想到 LinearLayout 裡面的 orientation 設置為 horizontal 時的佈局。
也可以記憶為 Row 代表行,因此只有一行。
如下:
Sample:
return Row(
children: <widget>[
Text('Widget One', style: TextStyle(color: Colors.blue),),
Text('Widget Two'),
],
);
/<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'),
],
);
/<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',
),
),
],
),
);
/<widget>
灰色是我們的父容器,可以看到兩個控件水平方面居中,豎直方面向下對齊。
5. Container
Container 的使用超級廣泛。
我們這裡略微講一下一些使用場景。
1)給一些沒有自帶寬高的屬性設置寬高。
比如我們上面講到 Row 最後一個 Sample 的時候,給 Text、Row 設置寬高都是在外面套一層 Container。
2) 設置間距。
以上面 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,
)
],
);
/<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,
)
],
);
/<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,
)
],
);
/<widget>
可以等效替換為
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,
)
],
);
/<widget>
將
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
更多閱讀:
閱讀更多 安卓小煜 的文章