最近閑來無事學(xué)習(xí)flutter模仿開發(fā)一個應(yīng)用用來練手, 準(zhǔn)備將學(xué)習(xí)過程記錄成一系列文章備忘, 本文為該系列第(3)篇,全部代碼已上傳: github 界面布局就不再一一記錄,之后主要記錄下特別的地方
導(dǎo)航
- showModalBottomSheet
- 鍵盤遮蓋問題解決
showModalBottomSheet
商品詳情頁面有一個bottomSheet顯示商品規(guī)格,數(shù)量信息
showModalBottomSheet(
context: context,
builder: (context) {
return ActivitySelectSpec(
info: info,
skus: skus,
addShoppingCart: true,
);
});
鍵盤遮蓋問題解決
這里由于是modalBottomSheet存在一個問題是底部數(shù)量輸入框獲取焦點(diǎn)是會被鍵盤遮住..
正常界面在scaffold里有一個resizeToAvoidBottomInset參數(shù)默認(rèn)是true, 該參數(shù)控制鍵盤彈出時會重繪界面以防界面中元素被鍵盤遮擋. 但是在showModalBottomSheet中產(chǎn)生的widget是無效的
image.png
方案一 :
在showModalBottomSheet的builder中嵌套一個scaffold解決鍵盤遮擋問題. 效果如下
iphone5s
小屏幕下由于本身元素已經(jīng)布滿彈出窗口所以并沒什么問題.
iphone xs max
大屏情況下,鍵盤彈出問題是解決沒問題, 但是會看彈出框無法布滿底部會出現(xiàn)空白. 解決這種方法有控制彈出窗scaffold大小,并不知道內(nèi)部控件大小,
?? 這種方法當(dāng)android:theme為 @android:style/Theme.Light.NoTitleBar.Fullscreen 時無效, 為@android:style/Theme.Light.NoTitleBar時有效.. Fullscreen會影響這個效果 .. 如果想全屏只能initState時設(shè)置 SystemChrome.setEnabledSystemUIOverlays([]);
該方案可以解決鍵盤遮擋問題但會倒是布局不雅.. 目前本人測試可多種布局都無法解決空白問題, 哪位大神知道解決方法的可以告知一下
方案二 :
既然常規(guī)方案無法完成遮擋處理那就手工來控制
效果如下:
image.png
image.png
大小屏都沒問題.
解決思路如下:
當(dāng)鍵盤觸發(fā)時在整體布局底部padding加大底部變動區(qū)域,也就是修改整體界面的顯示區(qū)域接口,原因是滾動界面會記入當(dāng)前的滾動keepScrollOffset會自動調(diào)整顯示區(qū)到當(dāng)前獲取焦點(diǎn).
棄用純手工解決方案
當(dāng)鍵盤出發(fā)彈出時在整個界面下方插入一個鍵盤使得顯示界面變動區(qū)域,其值可以通過 MediaQuery.of(context).viewInsets.bottom 獲取.
取到值之后還需要對界面進(jìn)行滾動,因?yàn)槿绻麊渭冎皇遣迦胍粔K區(qū)域,并不能完全的讓鍵盤不遮擋,只不過是整個界面長度滾動到最下面的時候鍵盤不遮擋元素而已
代碼如下:
double viewport; //無鍵盤時顯示區(qū)域
double maxScroll; //無鍵盤是最大滾動區(qū)域
void _keyBorderShow() {
if (_focusNode.hasFocus) {
Future.delayed(Duration(milliseconds: 150), () {
double move = _controller.position.maxScrollExtent; // 移動到最底部
if (maxScroll == 0) {
//單界面就顯示完成的. 按顯示區(qū)域變動值移動
move = _controller.position.viewportDimension - viewport + 10;
if (move < 11) {
move = _controller.position.maxScrollExtent;
}
} else {
//原本就有滾動距離的,按多出來的距離移動
move = _controller.position.maxScrollExtent - maxScroll + 10;
}
if (_controller.position.maxScrollExtent < move) {
move = _controller.position.maxScrollExtent;
}
_controller.jumpTo(move);
});
}
}
分為2種情況:
1.沒有鍵盤時一個界面就顯示完成了,那么控制器取到的最大滾動值就是0那也就需要計(jì)算顯示區(qū)域變動了多少,然后滾動多少.
2. 沒有鍵盤是一個界面顯示不完原本就有滾動值,那就需要計(jì)算新的最大滾動值和原本的滾動值變化了多少,就滾動多少
這里使用了150毫秒的延時,是為了在鍵盤顯示時等待鍵盤新界面繪制完成,獲取新界面的值.
?? 注意: 這些代碼不能通用,只能說是一個解決思路可以參考