Flutter计算器App自定义Widget模拟原生键盘实现方案咨询
在Flutter中实现自定义计算器键盘Widget
核心实现思路
通过禁用输入框的原生键盘,监听输入框焦点状态,在底部弹出自定义Widget作为键盘,将键盘输入操作与输入框的文本控制器绑定,同时模拟原生键盘的弹出/收起动画与样式。
步骤1:配置输入框,禁用原生键盘
给TextField设置keyboardType: TextInputType.none屏蔽原生键盘,用FocusNode监听焦点变化以控制自定义键盘的显示/隐藏,通过TextEditingController处理输入文本的更新。
final FocusNode _focusNode = FocusNode(); final TextEditingController _controller = TextEditingController(); bool _isKeyboardVisible = false; @override void initState() { super.initState(); _focusNode.addListener(() { setState(() { _isKeyboardVisible = _focusNode.hasFocus; }); }); } @override void dispose() { _focusNode.dispose(); _controller.dispose(); super.dispose(); } // 输入框Widget TextField( controller: _controller, focusNode: _focusNode, keyboardType: TextInputType.none, // 禁用原生键盘 decoration: const InputDecoration( hintText: "输入计算内容", border: OutlineInputBorder(), ), textAlign: TextAlign.right, style: const TextStyle(fontSize: 24), readOnly: false, // 保持可点击聚焦 )
步骤2:实现自定义键盘的弹出动画与原生样式
用AnimatedContainer结合SlideTransition实现底部滑入动画,高度设为原生键盘常规高度(300dp左右),添加圆角、阴影模仿原生样式,用GridView实现计算器按键布局。
// 自定义键盘Widget Widget _buildCustomKeyboard() { return AnimatedContainer( duration: const Duration(milliseconds: 200), // 匹配原生动画时长 height: _isKeyboardVisible ? 300 : 0, child: SlideTransition( position: Tween<Offset>( begin: const Offset(0, 1), end: Offset.zero, ).animate(CurvedAnimation( parent: ModalRoute.of(context)!.animation!, curve: Curves.easeOut, )), child: Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), boxShadow: [ BoxShadow( color: Colors.black12, blurRadius: 10, spreadRadius: 2, ) ], ), child: GridView.count( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), crossAxisCount: 4, children: [ _buildKeyButton("1"), _buildKeyButton("2"), _buildKeyButton("3"), _buildKeyButton("÷", color: Colors.orange), _buildKeyButton("4"), _buildKeyButton("5"), _buildKeyButton("6"), _buildKeyButton("×", color: Colors.orange), _buildKeyButton("7"), _buildKeyButton("8"), _buildKeyButton("9"), _buildKeyButton("-", color: Colors.orange), _buildKeyButton("C", color: Colors.grey), _buildKeyButton("0"), _buildKeyButton("←", color: Colors.grey), _buildKeyButton("+", color: Colors.orange), _buildKeyButton("=", color: Colors.orange, crossAxisCount: 4), ], ), ), ), ); } // 键盘按键Widget Widget _buildKeyButton(String text, {Color color = Colors.black, int crossAxisCount = 1}) { return InkWell( onTap: () => _handleKeyPress(text), child: Container( alignment: Alignment.center, child: Text( text, style: TextStyle(fontSize: 24, color: color), ), ), ); }
步骤3:处理键盘输入逻辑
编写_handleKeyPress方法,根据按键类型实现数字输入、运算符输入、清空、删除、计算等功能:
void _handleKeyPress(String key) { switch (key) { case "C": _controller.clear(); break; case "←": if (_controller.text.isNotEmpty) { _controller.text = _controller.text.substring(0, _controller.text.length - 1); } break; case "=": // 这里可添加表达式解析与计算逻辑,示例为简化处理 try { // 实际开发中需处理运算符优先级、异常输入等,可引入计算库 double result = double.parse(_controller.text); // 仅示例,需替换为真实计算逻辑 _controller.text = result.toString(); } catch (e) { _controller.text = "输入错误"; } break; default: _controller.text += key; break; } }
步骤4:整合页面布局
将输入框和自定义键盘整合到Scaffold中,键盘放在底部区域:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("计算器")), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _controller, focusNode: _focusNode, keyboardType: TextInputType.none, decoration: const InputDecoration( hintText: "输入计算内容", border: OutlineInputBorder(), ), textAlign: TextAlign.right, style: const TextStyle(fontSize: 24), readOnly: false, ), const SizedBox(height: 20), // 可添加结果显示区域等其他UI ], ), ), bottomSheet: _buildCustomKeyboard(), ); }
额外优化建议
- 点击空白区域收起键盘:给页面添加
GestureDetector,点击时调用_focusNode.unfocus()。 - 适配屏幕:用
MediaQuery.of(context).size动态调整键盘高度。 - 按键反馈:添加振动或按压动画,增强原生交互体验。
内容的提问来源于stack exchange,提问作者user21766581
相关产品推荐
相关产品推荐

