今天和各位分享一個博主在實際開發中遇到的問題,以及解決方法。廢話不多說,我們先來看需求:
我們要做一個iOS風格的底部選單彈出元件,具體涉及showCupertinoModalPopup()方法,該方法被執行後,會出現如下圖類似所示的選單彈出檢視:
為了簡化程式碼以突出重點,下面放上我在一開始的實現方案:
openActionSheet() {
List<Widget> menuWidgets = new List();
menuItems.forEach((element) {
menuWidgets.add(CupertinoActionSheetAction(
child: Text(element),
onPressed: () {
Navigator.pop(context);
debugPrint("操作$element被執行“);
},
isDefaultAction: true,
));
});
showCupertinoModalPopup(
context: context,
builder: (buildContext) {
return CupertinoActionSheet(
title: Text('測試選單'),
message: Text('點選選單項試試吧!'),
actions: menuWidgets);
});
}
複製程式碼
如上述程式碼所示,openActionSheet()是顯示該元件的方法。其中,showCupertinoModalPopup()為Flutter SDK內建方法,其作用即顯示這個元件;再其上面的迴圈以及List宣告、賦值等操作實際上就是在動態新增選單項。menuItems型別是List<String>。
通過對程式碼的解釋,相信大家能夠一目瞭然地看出,當某個選單項被點選時,整個選單元件消失,並列印Debug Log(對應為真實專案要執行的操作)。
大家覺得上述程式碼有問題嗎?如果有問題,問題在哪兒呢?
現在公佈答案:這段程式碼有問題!
上述程式碼執行時,當使用者點選選單項後,其執行結果並非如我們預想的那樣:選單組消失並輸出Log,而變成了:整個頁面被Pop,選單組保留,並輸出Log!
這是什麼原因呢?
實際上,罪魁禍首就在我們迴圈遍歷賦值操作時的這條語句:
Navigator.pop(context);
複製程式碼
這裡的context是整個頁面的BuildContext,而非選單組的。這裡我們要明確一個概念——我們想Pop誰,一定要用誰的BuildContext物件。
在這裡,正確的BuildContext物件是誰呢?它在這裡:
showCupertinoModalPopup(
context: context,
builder: (buildContext) {
return CupertinoActionSheet(
title: Text('測試選單'),
message: Text('點選選單項試試吧!'),
actions: menuWidgets);
}
);
複製程式碼
注意到了嗎?上面第三行括號裡的buildContext才是我們真正要用的物件。因此,正確的做法是什麼呢?
openActionSheet() {
BuildContext tempContext;
List<Widget> menuWidgets = new List();
menuItems.forEach((element) {
menuWidgets.add(CupertinoActionSheetAction(
child: Text(element),
onPressed: () {
Navigator.pop(tempContext);
debugPrint("操作$element被執行");
},
isDefaultAction: true,
));
});
showCupertinoModalPopup(
context: context,
builder: (buildContext) {
tempContext = buildContext;
return CupertinoActionSheet(
title: Text('測試選單'),
message: Text('點選選單項試試吧!'),
actions: menuWidgets);
});
}
複製程式碼
如上所示,我們只需將正確的物件“帶”到其作用域外面就可以了。
好了,這就是本篇文章的全部內容,希望能夠對你有所幫助!