??????小菜繼續(xù)整理一些個人不太注意但非常有用的小功能點,可能也是大家熟悉的,只是為了以后使用方便查找。
1. Opacity 透明度
??????小菜以前在處理 Widget 的顯隱性時用的是設(shè)置 Widget 寬高均為0,方式不太好,偶然間了解到 Opacity,可以通過處理透明度來處理 Widget 的顯隱性。
??????Opacity 可以使子控件透明,可以通過設(shè)置 0.0~1.0之間的值來設(shè)置透明度;對于 0.0 子控件基本沒有繪制過,對于 1.0 會立即繪制而不實用中間緩沖區(qū)。這種方式比直接在 Widget 中添加和刪除子控件更有效。
??????Tips: opacity 的值必須在 0.0~1.0 之間,類似于 Android 中的 Visible 和 inVisible 效果。
Widget childOpacityWid(BuildContext context) {
return new Column(
children: <Widget>[
new Opacity(
opacity: 1.0,
child: new Container(
height: 80.0,
color: Colors.blue,
child: new Center(child: new Text('當(dāng)前 opacity = 1.0')))),
new Opacity(
opacity: 0.0,
child: new Container(
height: 80.0,
color: Colors.green,
child: new Center(child: new Text('當(dāng)前 opacity = 0.0')))),
new Opacity(
opacity: 0.5,
child: new Container(
height: 80.0,
color: Colors.redAccent,
child: new Center(child: new Text('當(dāng)前 opacity = 0.5'))))
],
);
}

2. Chip 標(biāo)簽
??????小菜以前自定義的標(biāo)簽都是用 Row 配合其他 Widget 來實現(xiàn)的,后來了解到 Chip 不僅節(jié)省了很多時間,效果也很好。配合 Wrap 流式布局可以解決很多問題。
const Chip({
Key key,
this.avatar, // 左側(cè)圖標(biāo)
@required this.label, // 標(biāo)簽內(nèi)容,一般是文字
this.labelStyle, // 標(biāo)簽樣式
this.labelPadding, // 標(biāo)簽內(nèi)邊距
this.deleteIcon, // 刪除圖標(biāo),自己配置
this.onDeleted, // 刪除方法,必須調(diào)用才會顯示刪除圖標(biāo)
this.deleteIconColor, // 刪除圖標(biāo)顏色
this.deleteButtonTooltipMessage, // 刪除圖標(biāo)的提示消息
this.shape, // 形狀,主要是整個標(biāo)簽樣式,包括圓角等
this.clipBehavior = Clip.none,
this.backgroundColor, // 背景顏色
this.padding, // 整個標(biāo)簽內(nèi)邊距
this.materialTapTargetSize, // 刪除圖標(biāo)點擊范圍,可不處理
})
Widget childChipWid(var string, var state) {
Widget childChip;
if (state == 1) { // 默認(rèn)圓角
childChip = Chip(
label: Text(string, style: new TextStyle(fontSize: 16.0)),
deleteIcon: Icon(Icons.clear, color: Colors.black12),
labelPadding: EdgeInsets.fromLTRB(6.0, 0.0, 6.0, 0.0),
);
} else if (state == 2) { // 設(shè)置形狀為圓角矩形
childChip = Chip(
label: Text(string, style: new TextStyle(fontSize: 16.0)),
deleteIcon: Icon(Icons.clear, color: Colors.black12),
labelPadding: EdgeInsets.fromLTRB(2.0, 0.0, 2.0, 0.0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(3.0)),
onDeleted: () {},
);
} else { // 添加前置圖標(biāo)樣式
childChip = Chip(
label: Text(string, style: new TextStyle(fontSize: 16.0)),
avatar: Icon(Icons.search),
deleteIcon: Icon(Icons.clear, color: Colors.black12),
labelPadding: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
onDeleted: () {},
);
}
return childChip;
}
??????Tips: 如果要顯示刪除圖標(biāo),一定要實現(xiàn) onDeleted:(){} 方法,否則不顯示。

3. Color 顏色
??????Color 對于每個開發(fā)者都很熟悉,對于小菜來說也必須用的屬性,Flutter 提供了很多設(shè)置顏色的方式,小菜簡單整理一下。
Colors 方式
??????Flutter 提供了很多便利的色值可以直接使用;大多數(shù)色值的顏色從 100 到 900,增量為 100,數(shù)字越小,顏色越淺,數(shù)字越大,顏色越深。重點樣本(例如redAccent)僅具有值 100/200/400/700。
Colors.redAccent,
Colors.red[200],
Colors.red,
Colors.red[800],
??????還有一系列具有常見不透明度的黑色和白色。例如:black54 是純黑色,具有 54% 的不透明度。
Colors.black54,
Colors.black87,
Color 方式
??????小菜在做 Android 開發(fā)時一般是用 16進(jìn)制的色值,Flutter 同樣支持,以 #EE5048 為例:
- ARGB 16進(jìn)制方式:0x 代表16進(jìn)制,進(jìn)行拆分,第一個參數(shù)為透明度;
Color.fromARGB(0xFF, 0xEE, 0x50, 0x48)
- ARGB 10進(jìn)制方式:與16進(jìn)制使用相同,只是需要逐個轉(zhuǎn)成10進(jìn)制數(shù);
Color.fromARGB(255, 240, 80, 72)
- RGBO 16進(jìn)制方式:最后一個參數(shù)為 0.0~1.0 之間透明度;
Color.fromRGBO(0xEE, 0x50, 0x48, 1.0)
- RGBO 10進(jìn)制方式:與上16進(jìn)制使用相同;
Color.fromRGBO(240, 80, 72, 1.0)
- 直接使用16進(jìn)制方式:只需添加 0x 代表16進(jìn)制;
Color(0xFFEE5048)
??????Tips: 0x 后需要設(shè)置透明度 FF (完全不透明) 或其他透明度,如果不設(shè)置透明度,默認(rèn)是全透明。

4. Text 文字換行
??????Text 是我們?nèi)粘R欢〞玫降?Widget,根據(jù)設(shè)置不同的屬性產(chǎn)生不同的樣式效果。小菜主要嘗試了一下?lián)Q行時的效果。
-
softWrap: false
只有一行內(nèi)容時,若超過設(shè)置最大寬度,是否自動換行,true 為換行,false 為不換行; - overflow: TextOverflow.clip 只有一行內(nèi)容,不換行時,默認(rèn)截斷超出內(nèi)容,與設(shè)置 clip 屬性效果相同;
-
overflow: TextOverflow.fade
只有一行內(nèi)容,不換行時,將超出的文本淡化為透明;當(dāng)設(shè)置多行顯示時,會將最后一行底部略透明顯示; -
overflow: TextOverflow.ellipsis
只有一行內(nèi)容,不換行時,將超出部分用 ... 代替;當(dāng)設(shè)置超過多行時,最后內(nèi)容以 ... 顯示。但就目前小菜研究中,無法像 Android 設(shè)置 ... 在中間或跑馬燈效果,如果有哪位大神了解還請多多指教。
Widget childTextWid(BuildContext context) {
return ListView(
children: <Widget>[
Container( height: 50.0, color: Colors.green,
child: Padding( padding: EdgeInsets.all(5.0),
child: Text(
'Text 測試,超過內(nèi)容自動換行!Hello, How are you?Hello, How are you?Hello, How are you?Hello, How are you?',
softWrap: true))),
Container( height: 50.0, color: Colors.black54,
child: Padding( padding: EdgeInsets.all(5.0),
child: Text(
'Text 測試,超過內(nèi)容不換行!默認(rèn)自動截斷,Hello, How are you?Hello, How are you?Hello, How are you?',
softWrap: false))),
Container( height: 50.0, color: Colors.black38,
child: Padding( padding: EdgeInsets.all(5.0),
child: Text(
'Text 測試,超過內(nèi)容不換行!手動設(shè)置自動截斷,Hello, How are you?Hello, How are you?Hello, How are you?',
softWrap: false, overflow: TextOverflow.clip))),
Container( height: 50.0, color: Colors.redAccent,
child: Padding( padding: EdgeInsets.all(5.0),
child: Text(
'Text 測試,超過內(nèi)容不換行!漸變隱藏,Hello, How are you?Hello, How are you?Hello, How are you?',
softWrap: false, overflow: TextOverflow.fade))),
Container( height: 50.0, color: Colors.blue,
child: Padding( padding: EdgeInsets.all(5.0),
child: Text(
'Text 測試,超過內(nèi)容不換行!省略號樣式,Hello, How are you?Hello, How are you?Hello, How are you?',
softWrap: false, overflow: TextOverflow.ellipsis))),
Container( color: Colors.blueGrey,
child: Padding( padding: EdgeInsets.all(5.0),
child: Text(
'Text 測試,超過內(nèi)容換行!設(shè)置超出超出行數(shù)漸變隱藏,Hello, How are you?Hello, How are you?Hello, How are you?Hello, How are you?Hello, How are you?Hello, How are you?',
softWrap: true, maxLines: 2, overflow: TextOverflow.fade))),
Container( color: Colors.brown, height: 50.0,
child: Padding( padding: EdgeInsets.all(5.0),
child: Text(
'Text 測試,超過內(nèi)容換行!設(shè)置超出超出行數(shù)漸變隱藏,Hello, How are you?Hello, How are you?Hello, How are you?Hello, How are you?Hello, How are you?Hello, How are you?',
softWrap: true, maxLines: 2, overflow: TextOverflow.ellipsis))),
],
);
}

5. BoxConstraints 布局約束
??????小菜在處理圖片時,為了方便適配,借助 Expanded 均分大小而非固定大小,此時小菜想把圖片截取中間部分填充滿而不拉伸,采用 Image 的 BoxFit 不能很好的實現(xiàn),小菜學(xué)習(xí)了一下 BoxConstraints 布局約束方式,根據(jù)父類布局的最大最小寬高進(jìn)行填充。
Widget childBoxImgWid(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
flex: 1,
child: ConstrainedBox(
child: Image.asset(
'images/icon_hzw01.jpg', fit: BoxFit.cover,
),
constraints: new BoxConstraints.expand(),
)),
Expanded(
flex: 1,
child: ConstrainedBox(
child: Image.asset(
'images/icon_hzw02.jpg', fit: BoxFit.cover,
),
constraints: new BoxConstraints.expand(),
)),
Expanded(
flex: 1,
child: ConstrainedBox(
child: Image.asset(
'images/icon_hzw03.jpg', fit: BoxFit.cover
),
constraints: new BoxConstraints.expand(),
)),
],
);
}

Widget childBoxImgWid(BuildContext context) {
return Column(
children: <Widget>[
Expanded( flex: 1,
child: Image.asset('images/icon_hzw01.jpg', fit: BoxFit.cover)),
Expanded( flex: 1,
child: Image.asset('images/icon_hzw02.jpg', fit: BoxFit.cover)),
Expanded( flex: 1,
child: Image.asset('images/icon_hzw03.jpg', fit: BoxFit.cover))
],
);
}

??????小菜剛接觸 Flutter 時間不長,還有很多不清楚和不理解的地方,如果又不對的地方還希望多多指出。
來源:阿策小和尚