??????小菜作為一個(gè)小學(xué)生在實(shí)際操作中遇到很多問(wèn)題,相對(duì)比較常見(jiàn),小菜來(lái)整理記錄一下。
問(wèn)題一:嵌套權(quán)重異常
??????小菜做 Android 時(shí)為了屏幕適配汁咏,用到權(quán)重/比例比較多,Flutter 也提供了實(shí)現(xiàn)權(quán)重的功能作媚,小菜嘗試過(guò) 權(quán)重基本用法攘滩,當(dāng)時(shí)沒(méi)有涉及到嵌套權(quán)重的問(wèn)題,小菜想要實(shí)現(xiàn)的是左側(cè)一張大圖纸泡,右側(cè)垂直兩張小圖漂问,水平方向 1:1 均分,小菜用 Expanded 配合 flex 在嵌套權(quán)重時(shí)遇到如下問(wèn)題,于是重新研究一下權(quán)重的使用;
嘗試一:
??????在根 Widget 中嘗試如下级解,Expanded 與 Flexible 均正常冒黑,默認(rèn)填滿布局,與小菜預(yù)計(jì)的相同勤哗;
??????小菜理解 Container 未設(shè)置寬高抡爹,但 Row/Column 默認(rèn) mainAxisSize=MainAxisSize.max,因此正常填滿芒划;
// Expanded
return new SafeArea(
top: false,
child: Scaffold(
appBar: new AppBar(
title: Text('Expanded Demo'),
),
body: Container(
child: Row(children: <Widget>[
Expanded(flex: 1, child: Container(color: Colors.red)),
Expanded(flex: 1,
child: Column(children: <Widget>[
Expanded(flex: 1, child: Container(color: Colors.blue)),
Expanded(flex: 1, child: Container(color: Colors.green))
]))
]))));
// Flexible
return new SafeArea(
top: false,
child: Scaffold(
appBar: new AppBar(
title: Text('Flexible Demo'),
),
body: Container(
child: Row(children: <Widget>[
Flexible(flex: 1, child: Container(color: Colors.red)),
Flexible(
flex: 1,
child: Column(children: <Widget>[
Flexible(flex: 1, child: Container(color: Colors.blue)),
Flexible(flex: 1, child: Container(color: Colors.green))
]))
]))));
嘗試二:
??????大多數(shù)情況頁(yè)面元素較多冬竟,最外層可能會(huì)嵌套 ListView/Column 或其他 Widget,此時(shí)用 Expanded 便會(huì)出現(xiàn)如上問(wèn)題民逼;日志中建議使用 Flexible 和 Column mainAxisSize: MainAxisSize.min泵殴,雖然不報(bào)錯(cuò),但是頁(yè)面空白無(wú)效果拼苍;若只用 Flexible 結(jié)果依然是上述問(wèn)題笑诅;
??????小菜理解兩層 Column 加上 Expanded/Flexible 無(wú)法計(jì)算 Container 高度,子 Widget 無(wú)法自適應(yīng)父 Widget 高度疮鲫;
return new SafeArea(
top: false,
child: Scaffold(
body: ListView(children: <Widget>[
Container(
child: Row(children: <Widget>[
Flexible(flex: 1, child: Container(color: Colors.red)),
Flexible(
flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(flex: 1, child: Container(color: Colors.blue)),
Flexible(flex: 1, child: Container(color: Colors.green))
]))
]))
])));
嘗試三:
??????根據(jù)上一步嘗試吆你,小菜理解 Container 高度為 0,需要手動(dòng)設(shè)置高度俊犯,但是設(shè)置在 Row 層還是 Column 層或子 Container 層是不同的妇多;
??????小菜理解不顯示的原因是高度未匹配,故嘗試不同位置設(shè)置默認(rèn)高度燕侠,但基本都在最外層設(shè)置并以最外層為基準(zhǔn)者祖;
return new SafeArea(
top: false,
child: Scaffold(
body: ListView(children: <Widget>[
Container(
height: 120,
child: Row(children: <Widget>[
Flexible(flex: 1, child: Container(color: Colors.red)),
Flexible( flex: 1,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible( flex: 1, child: Container(color: Colors.blue)),
Flexible( flex: 1, child: Container(color: Colors.green))
])))
]))
])));
嘗試四:
??????如果最外層不設(shè)置高度時(shí),則考慮根據(jù)需求使用帶有寬高的 Widget绢彤,小菜需要展示圖片七问,故直接用圖片占位;
??????小菜主要想實(shí)現(xiàn)圖片高度自適應(yīng)茫舶,而寬度隨屏幕比例占有烂瘫,右側(cè)兩圖正常為左圖占位一半,但為了防止異常奇适,通常在最外層設(shè)置高度;
return new SafeArea(
top: false,
child: Scaffold(
body: ListView(children: <Widget>[
Container(
child: Row(children: <Widget>[
Expanded(
flex: 1,
child: Image.network(
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1544938569112&di=feeab11968f3870520482630563c4f54&imgtype=0&src=http%3A%2F%2Fi1.hdslb.com%2Fbfs%2Farchive%2Fac5c906111130579c6909aae47f6656e20d0906b.jpg')),
Expanded(
flex: 1,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
child: Image.network(
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1544938569112&di=feeab11968f3870520482630563c4f54&imgtype=0&src=http%3A%2F%2Fi1.hdslb.com%2Fbfs%2Farchive%2Fac5c906111130579c6909aae47f6656e20d0906b.jpg'),
flex: 1),
Flexible(
child: Image.network(
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1544938569112&di=feeab11968f3870520482630563c4f54&imgtype=0&src=http%3A%2F%2Fi1.hdslb.com%2Fbfs%2Farchive%2Fac5c906111130579c6909aae47f6656e20d0906b.jpg'),
flex: 1)
])))
]))
])));
擴(kuò)展:
??????Flexible 的 FlexFit 分兩種芦鳍,在嵌套權(quán)重時(shí)只可以用默認(rèn)的 loose嚷往,在其他情況下,小菜測(cè)試差別不大柠衅;但小菜理解的官方說(shuō)明:tight 模式是強(qiáng)制填補(bǔ)剩余空間皮仁,而 loose 模式可以填滿剩余空間,也允許稍小不填滿,非強(qiáng)制贷祈;相對(duì) loose 使用范圍更廣趋急。
問(wèn)題二:SnackBar 找不到 Context
??????小菜嘗試 SnackBar 時(shí)總是找不到上下文環(huán)境而打不開(kāi);
嘗試一:
??????小菜將整體放在一個(gè) Widget 中势誊,傳入 BuildContext 參數(shù)呜达,無(wú)果,依舊是找不到上下文環(huán)境粟耻;
嘗試二:
??????按官網(wǎng)推薦查近,可新建一個(gè) Builder 動(dòng)態(tài)添加 BuildContext,但是小菜又出現(xiàn)新的問(wèn)題挤忙,不可在 Builder 中返回?zé)o大小的 Container霜威;仔細(xì)找了很久發(fā)現(xiàn) Builder 需要 return 一個(gè) Widget,太粗心册烈;
Widget _childExpandedWid() {
return SafeArea(
top: false,
child: Scaffold(
appBar: new AppBar(title: new Text("SnackBar Demo")),
body: Builder(builder: (BuildContext context) {
return Row(children: <Widget>[
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('測(cè)試一下 SnackBar 使用戈泼!')));
},
child: Container(color: Colors.red))),
Expanded(
flex: 1,
child: Column(children: <Widget>[
Expanded(flex: 1, child: Container(color: Colors.blue)),
Expanded(flex: 1, child: Container(color: Colors.green))
]))
]);
})));
}
嘗試三:
??????按官網(wǎng)推薦,可以將這些子 Widget 拆分為單獨(dú)的 StatelessWidget 組件赏僧,測(cè)試正常大猛;
class ChildExpandWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
top: false,
child: Scaffold(
appBar: new AppBar(title: new Text("SnackBar Demo")),
body: Row(children: <Widget>[
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('測(cè)試一下 SnackBar 使用!')));
},
child: Container(color: Colors.red))),
Expanded(
flex: 1,
child: Column(children: <Widget>[
Expanded(flex: 1, child: Container(color: Colors.blue)),
Expanded(flex: 1, child: Container(color: Colors.green))
]))
])));
}
}
??????小菜作為初學(xué)者次哈,遇到很多基礎(chǔ)的問(wèn)題胎署,僅做記錄;如有錯(cuò)誤請(qǐng)多多指導(dǎo)窑滞!
來(lái)源:阿策小和尚