Flutter中如何在两个互斥切换按钮间嵌入TextField?
解决Flutter中带中间TextField的单选切换按钮布局问题
你可以通过自定义StatefulWidget来封装这组控件,把两个切换按钮和中间的TextField整合到同一个组件中,同时内部维护单选状态,既满足两个按钮属于同一组件的需求,也不会把TextField变成可点击的按钮项。
基础实现示例
class ToggleWithTextField extends StatefulWidget { const ToggleWithTextField({super.key}); @override State<ToggleWithTextField> createState() => _ToggleWithTextFieldState(); } class _ToggleWithTextFieldState extends State<ToggleWithTextField> { // 0代表左侧按钮选中,1代表右侧按钮选中 int _selectedIndex = 0; @override Widget build(BuildContext context) { return Row( children: [ // 左侧切换按钮 ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: _selectedIndex == 0 ? Colors.blue : Colors.grey[200], foregroundColor: _selectedIndex == 0 ? Colors.white : Colors.black, ), onPressed: () => setState(() => _selectedIndex = 0), child: const Text("按钮1"), ), const SizedBox(width: 16), // 中间的TextField,用Expanded占满剩余空间 Expanded( child: TextField( decoration: const InputDecoration( hintText: "输入内容", border: OutlineInputBorder(), ), ), ), const SizedBox(width: 16), // 右侧切换按钮 ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: _selectedIndex == 1 ? Colors.blue : Colors.grey[200], foregroundColor: _selectedIndex == 1 ? Colors.white : Colors.black, ), onPressed: () => setState(() => _selectedIndex = 1), child: const Text("按钮2"), ), ], ); } }
灵活扩展版本
如果需要支持自定义按钮文字、TextField控制器或监听切换事件,可以给组件添加参数:
class ToggleWithTextField extends StatefulWidget { final String leftButtonText; final String rightButtonText; final TextEditingController? textController; final ValueChanged<int>? onToggleChanged; const ToggleWithTextField({ super.key, required this.leftButtonText, required this.rightButtonText, this.textController, this.onToggleChanged, }); @override State<ToggleWithTextField> createState() => _ToggleWithTextFieldState(); } class _ToggleWithTextFieldState extends State<ToggleWithTextField> { int _selectedIndex = 0; @override Widget build(BuildContext context) { return Row( children: [ ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: _selectedIndex == 0 ? Colors.blue : Colors.grey[200], foregroundColor: _selectedIndex == 0 ? Colors.white : Colors.black, ), onPressed: () { setState(() => _selectedIndex = 0); widget.onToggleChanged?.call(0); }, child: Text(widget.leftButtonText), ), const SizedBox(width: 16), Expanded( child: TextField( controller: widget.textController, decoration: const InputDecoration( hintText: "输入内容", border: OutlineInputBorder(), ), ), ), const SizedBox(width: 16), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: _selectedIndex == 1 ? Colors.blue : Colors.grey[200], foregroundColor: _selectedIndex == 1 ? Colors.white : Colors.black, ), onPressed: () { setState(() => _selectedIndex = 1); widget.onToggleChanged?.call(1); }, child: Text(widget.rightButtonText), ), ], ); } }
使用方式
在需要的地方直接调用这个自定义组件即可:
const ToggleWithTextField( leftButtonText: "选项A", rightButtonText: "选项B", )
这种方案把两个按钮的单选逻辑完全封装在组件内部,符合你对“两个按钮属于同一组件”的要求,同时TextField独立于按钮的选中逻辑,不会被当作可点击的切换项。
内容的提问来源于stack exchange,提问作者user5182503
相关产品推荐
相关产品推荐

