??????小菜今天搭建了一個(gè)很丑的【簽到】小頁(yè)面,頁(yè)面很簡(jiǎn)單,只有寥寥幾個(gè)控件,但小菜想通過(guò)這個(gè)簡(jiǎn)單的小頁(yè)面學(xué)習(xí)一下權(quán)重/比例的使用方式,順便也學(xué)習(xí)了一下如何繪制圓形效果。

繪制圓形
??????小菜為了頁(yè)面稍微美觀一點(diǎn),準(zhǔn)備用圓形來(lái)替換普通的按鈕,小菜發(fā)現(xiàn) Flutter 提供了很多便捷的繪制圓形的方式,比 Android 要方便很多。小菜測(cè)試時(shí)用到了如下兩種:
ClipOval
??????ClipOval 是一個(gè)很強(qiáng)大的裁剪子控件為橢圓或圓角的控件;子控件沒(méi)有特殊限制。同時(shí)衍生出其他幾種裁剪方式:
- CustomClipper:可以創(chuàng)建自定義裁剪方式;
- ClipRect:可以裁剪不同寬高比例,通過(guò) heightFactor 屬性來(lái)處理;
- ClipRRect:可以設(shè)置圓角矩形或圓形;
- ClipPath:可以為任意形狀的裁剪方式;
new ClipOval(
child: new SizedBox(
width: 100.0,
height: 100.0,
// 子控件為網(wǎng)絡(luò)圖片
child: new Image.network(
"https://...pic.jpg",
fit: BoxFit.fill,
),
// 子控件為 Container
// child: new Container( color: Colors.redAccent, ),
),
),
// 圓角矩形
new ClipRRect(
borderRadius: const BorderRadius.all(const Radius.circular(30.0)),
child: new Container(
width: 90.0,
height: 90.0,
color: Colors.red,
),
),),
// heightFactor 為高/寬比例
new ClipRect(
child: new Align(
alignment: Alignment.topCenter,
heightFactor: 1.0,
child: new Container(color: Colors.yellow,height:90.0,width: 90.0,),
),
)
CircleAvatar
??????小菜以為 CircleAvatar 是繪制正圓最方便的方式,Flutter 直接提供的繪制圓形的控件,可添加背景色及背景圖;且在加載網(wǎng)絡(luò)圖片時(shí),網(wǎng)絡(luò)狀態(tài)不佳或圖片有問(wèn)題時(shí)只顯示背景色,更人性化。
// 只有背景色
new CircleAvatar(
backgroundColor: Colors.greenAccent,
radius: 90.0,
),
// 添加背景圖
new Align(
alignment: Alignment.center,
child: new CircleAvatar(
backgroundImage: new NetworkImage("https://...pic.jpg"),
backgroundColor: Colors.greenAccent,
radius: 90.0,
),
),

權(quán)重/比例
??????小菜在 Android 開(kāi)發(fā)過(guò)程中為了適配不同機(jī)型,常用到權(quán)重 android:weight,這樣在均分布局時(shí)起到重要作用;小菜尚在 Flutter 中沒(méi)有直接發(fā)現(xiàn) weight 的身影,Flutter 常用 Row 和 Column 來(lái)設(shè)置橫向和縱向布局。小菜發(fā)現(xiàn)可以通過(guò)如下方式來(lái)處理權(quán)重/比例。
Flexible
??????Flexible 默認(rèn)也是讓子控件占滿填充整個(gè)父類布局,Flexible 中的 flex 屬性可以調(diào)整,若兩個(gè) Flexible 控件 A/B,A 中 flex 設(shè)為 2,B 中 flex 設(shè)為 1,則整個(gè)布局中 A:B=2:1 整體占滿整個(gè)布局。
new Row(
children: <Widget>[
new Flexible(
child: new Container(
color: Colors.redAccent,
height: 40.0,
),
flex: 1,
),
new Flexible(
child: new Container(
color: Colors.blueAccent,
height: 40.0,
),
flex: 2,
),
],
),
Expanded
??????Expanded 默認(rèn)讓子控件占滿填充整個(gè)父類布局,Expanded 中的 flex 屬性為1,而 Expanded 繼承的是 Flexible;Flexible 支持的分割布局權(quán)重的方式 Expanded 也一樣,而與 Flexible 不同的是默認(rèn)會(huì)將子控件充滿布局。
new Row(
children: <Widget>[
new Expanded(
child: new Container(
color: Colors.redAccent,
height: 40.0,
),
flex: 2,
),
new Expanded(
child: new Container(
color: Colors.blueAccent,
height: 40.0,
),
flex: 1,
),
],
),
??????無(wú)論時(shí) Expanded 還是 Flexible 小菜都建議依靠 Row 和 Column 共同使用。小菜測(cè)試,兩者一起使用也不會(huì)太大影響。

主要源碼
class ItemSignPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Container(
child: new Column(
children: <Widget>[
new Container(
height: 10.0,
),
new Flexible(
child: new Container(
child: new Row(children: <Widget>[
new Flexible(
child: new Container(),
flex: 1,
),
new Container(
width: 16.0,
height: 1.0,
),
new Container(
width: 1.0,
color: Colors.blueAccent,
),
new Container(
width: 16.0,
height: 1.0,
color: Colors.blueAccent,
),
new Flexible(
child: new Container(
child: buildListData(
context, Color.fromARGB(40, 50, 40, 80), '上班簽到'),
),
flex: 1,
),
]),
),
flex: 1,
),
new Flexible(
child: new Container(
child: new Row(children: <Widget>[
new Flexible(
child: new Container(
child: buildListData(context, Colors.greenAccent, '下班簽退'),
),
flex: 1,
),
new Container(
width: 16.0,
height: 1.0,
color: Colors.blueAccent,
),
new Container(
width: 1.0,
color: Colors.blueAccent,
),
new Container(
width: 16.0,
height: 1.0,
),
new Flexible(
child: new Container(),
flex: 1,
),
]),
),
flex: 1,
),
new Container(
height: 60.0,
child: new Center(
child: new Text(
'請(qǐng)及時(shí)簽到哦~',
style: new TextStyle(color: Colors.blue, fontSize: 16.0),
),
),
),
],
),
);
}
Widget buildListData(BuildContext context, Color color, String text) {
return new Center(
child: new GestureDetector(
child: new CircleAvatar(
backgroundColor: color,
radius: 72.0,
child: new Text(
text,
style: new TextStyle(color: Colors.blue, fontSize: 18.0),
),
),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return new AlertDialog(
title: new Text(
'溫馨提示',
style: new TextStyle(
color: Colors.black54,
fontSize: 18.0,
),
),
content: new Text('您點(diǎn)擊的item內(nèi)容為:$text'),
);
},
);
},
),
);
}
}

??????小菜剛接觸 Flutter 時(shí)間不長(zhǎng),還有很多不清楚和不理解的地方,如果又不對(duì)的地方還希望多多指出。
來(lái)源:阿策小和尚