文章目錄
- 1. 前言
- 2. 借助 Scaffold 的特性自動調整
- 3. 使用 MediaQuery 精準控制抬升高度
- 3.1. 底部抽屜內輸入框的方案
- 4. 注意事項
- 5. 總結
1. 前言
在 Flutter 的開發過程中,經常會碰到某一個頁面有個 TextField 輸入組件,點擊的時候鍵盤會彈起來,這時候頁面應該需要抬升和鍵盤一樣的高度,好展示輸入內容,不然輸入內容就會被鍵盤遮擋。還有特殊場景,比如一個底部抽屜彈框,里面有 TextField 輸入組件,此時也要抬升頁面以方便輸入,這種場景下,如何完美解決呢?
其實,Flutter 提供了原生的解決方案,通過 Scaffold 組件的特性結合 MediaQuery 動態獲取鍵盤高度,就能輕松實現輸入框隨鍵盤抬升的效果。本文將從基礎場景到特殊場景,詳細講解這一方案的實現原理和具體操作。
2. 借助 Scaffold 的特性自動調整
Scaffold 是 Flutter 頁面布局的基礎組件,它內置了處理鍵盤彈出的機制,當鍵盤彈出時,會自動調整頁面布局以避免輸入框被遮擋,其核心在于resizeToAvoidBottomInset
屬性(默認值為 true)。
當resizeToAvoidBottomInset: true
時,Scaffold 會根據鍵盤的高度自動調整自身尺寸,將底部被鍵盤遮擋的部分向上抬升,確保輸入框可見。如下代碼,當點擊 TextField 彈出鍵盤時,Scaffold 會自動向上收縮,使輸入框位于鍵盤上方,避免被遮擋:
Scaffold(?resizeToAvoidBottomInset: true,body: Column(?mainAxisAlignment: MainAxisAlignment.end, // 輸入框在頁面底部?children: [?TextField(?decoration: const InputDecoration(?hintText: '請輸入內容',?border: OutlineInputBorder(),?),?),?],?),?
)
若需要關閉這一特性(例如某些自定義布局場景),可將其設為 false,此時鍵盤彈起,頁面不會被擠壓。
3. 使用 MediaQuery 精準控制抬升高度
對于特殊場景(如底部抽屜、自定義彈窗中的輸入框),僅依賴 Scaffold 的自動調整可能無法滿足需求。此時,可通過 MediaQuery.of(context).viewInsets.bottom 動態獲取鍵盤高度,手動調整輸入框所在容器的底部內邊距,實現精準抬升。如下代碼:
Container(?padding: EdgeInsets.only(?bottom: MediaQuery.of(context).viewInsets.bottom, // 該底部內邊距等于鍵盤高度?),?child: TextField(?decoration: const InputDecoration(?hintText: '請輸入內容',?border: OutlineInputBorder(),?),?),?
)
原理解析
MediaQuery.of(context).viewInsets 用于獲取屏幕邊緣被系統 UI 遮擋的區域尺寸,其中 bottom 屬性在鍵盤彈出時會返回鍵盤的高度(單位為邏輯像素),鍵盤收起時則為 0。?
利用這一特性,給輸入框所在的容器添加底部內邊距,值等于鍵盤高度,即可讓容器隨鍵盤同步抬升。
3.1. 底部抽屜內輸入框的方案
如下代碼:
class ButtomPopupPageState extends State<ButtomPopupPage> {/// 焦點final FocusNode myFocusNode = FocusNode();/// 文字final TextEditingController inputText = TextEditingController();/// 輸入框滾動控制器final ScrollController inputController = ScrollController();/// 打開彈窗void handleShowPopup() {showModalBottomSheet(context: context,clipBehavior: Clip.antiAlias,barrierColor: Colors.black.withAlpha(127),shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(20),topRight: Radius.circular(20),),),backgroundColor: const Color(0xFF232323),isScrollControlled: true, // 允許抽屜高度自適應內容enableDrag: false,builder: (BuildContext context) {return Padding(padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), // 適配鍵盤高度child: Container(height: 238,color: Colors.white,padding: EdgeInsets.all(16),child: Column(children: [Container(height: 110,clipBehavior: Clip.antiAlias,padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),decoration: BoxDecoration(color: const Color(0xFFEEF4FA),borderRadius: BorderRadius.circular(16),),child: TextField(expands: true,scrollController: inputController,controller: inputText,focusNode: myFocusNode,// 設置為 null 表示多行輸入maxLines: null,maxLength: 1000,keyboardType: TextInputType.multiline,textInputAction: TextInputAction.done,autofocus: false,decoration: InputDecoration(isCollapsed: true,contentPadding: EdgeInsets.zero,hintText: '請輸入......',// 去除輸入框底部的字符計數counterText: '',hintStyle: TextStyle(color: Color(0xff728BA4)),border: InputBorder.none,),cursorColor: Color(0xff1E1E1E),style: TextStyle(fontSize: 18,fontWeight: FontWeight.w500,color: Color(0xff1E1E1E),),onChanged: (text) {},onTapOutside: (PointerDownEvent _) {// 點擊輸入框外界主動失去焦點myFocusNode.unfocus();},),),// 確定按鈕Padding(padding: EdgeInsets.symmetric(vertical: 20),child: Container(alignment: Alignment.center,height: 56,decoration: BoxDecoration(borderRadius: BorderRadius.circular(28),color: Color(0xFF4165F1),),child: Text('確認'),),),],),),);});} Widget build(BuildContext context) {return Column(children: [Expanded(child: Container(alignment: Alignment.center,decoration: const BoxDecoration(color: Colors.white),child: TextButton(onPressed: handleShowPopup,child: const Text('點擊彈出',style: TextStyle(color: Colors.black, fontSize: 20),),),),),],);}
}
4. 注意事項
- 確保布局結構合理,輸入框所在容器的高度能夠隨內邊距調整(如使用 Column(mainAxisSize: MainAxisSize.min))。?
- 在底部抽屜中必須設置 isScrollControlled: true,否則可能因高度限制導致適配失效。?
5. 總結
核心在于利用系統提供的布局特性和動態高度獲取:?
- 基礎場景:直接使用 Scaffold,依賴其默認的 resizeToAvoidBottomInset: true 特性,即可實現頁面自動抬升,適用于大多數常規頁面。?
- 特殊場景:對于底部抽屜、自定義彈窗等獨立布局,通過 MediaQuery.of(context).viewInsets.bottom 獲取鍵盤高度,給輸入框容器添加對應底部內邊距,實現精準適配。?
通過這兩種方案的結合,無論是常規頁面還是特殊彈窗中的輸入框,都能完美避開鍵盤遮擋,為用戶提供流暢的輸入體驗。Flutter 的這套原生解決方案無需依賴第三方庫,性能更優,是處理鍵盤遮擋問題的首選方式。
本次分享就到這兒啦,我是鵬多多,如果您看了覺得有幫助,歡迎評論,關注,點贊,轉發,我們下次見~
往期文章
- vue中ref的詳解以及react的ref對比
- css使用aspect-ratio制作4:3和9:16和1:1等等比例布局
- Web前端頁面開發阿拉伯語種適配指南
- flutter-使用extended_image操作圖片的加載和狀態處理以及緩存和下載
- flutter-制作可縮放底部彈出抽屜評論區效果
- flutter-實現Tabs吸頂的PageView效果
- Vue2全家桶+Element搭建的PC端在線音樂網站
- 助你上手Vue3全家桶之Vue3教程
- 超詳細!vue組件通信的10種方式
- 超詳細!Vuex手把手教程
- 使用nvm管理node.js版本以及更換npm淘寶鏡像源
- vue中利用.env文件存儲全局環境變量,以及配置vue啟動和打包命令
個人主頁
- CSDN
- GitHub
- 掘金
- 簡書
- 博客園