Flutter中如何实现图示样式的toggle button组件

Flutter 实现该样式分段切换按钮的方法
这种带圆角、选中态填充的横向分段toggle,不需要引入第三方依赖,原生就有两种成熟实现方案:
方案1:使用官方内置ToggleButtons组件(开发效率最高)
这个组件是Flutter SDK自带的,专门用来做这类多选项切换控件,只要配置好样式参数就能快速对齐设计效果:
- 首先在组件的State中声明变量记录当前选中的选项索引,以及选项文案列表
- 配置组件的圆角、边框、选中/未选中态的文字和填充颜色
- 在点击回调中更新选中索引,触发UI重绘
核心实现代码:
// 状态变量 int _selectedIndex = 0; final List<String> _optionList = ["选项1", "选项2", "选项3"]; // 组件构建部分 ToggleButtons( isSelected: List.generate(_optionList.length, (i) => i == _selectedIndex), borderRadius: BorderRadius.circular(24), // 调整数值匹配圆角大小 borderColor: Colors.grey.shade300, selectedBorderColor: Colors.blue, fillColor: Colors.blue, // 选中项填充色 selectedColor: Colors.white, // 选中项文字颜色 color: Colors.grey.shade700, // 未选中项文字颜色 borderWidth: 1, splashColor: Colors.blue.withOpacity(0.2), onPressed: (index) { setState(() { _selectedIndex = index; }); }, children: _optionList .map((text) => Padding( padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 6), child: Text(text), )) .toList(), )
如果需要实现图中选中项的轻微浮起阴影效果,直接给ToggleButtons外层套一个Container,加对应的阴影装饰即可。
方案2:自定义组件封装(灵活度最高)
如果需要加图标、自定义切换动画、调整内边距规则,官方组件的配置满足不了需求的话,可以直接手写组件,逻辑也很简单:
- 外层用
Container做整体的背景、圆角、内边距 - 内部用
Row排列所有选项,选中的选项单独设置填充色,用AnimatedContainer做颜色切换的过渡动画 - 每个选项套
GestureDetector监听点击,更新选中状态
核心实现代码:
// 状态变量 int _currentIndex = 0; final _tabs = ["选项1", "选项2", "选项3"]; // 组件构建部分 Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: Colors.grey.shade200, borderRadius: BorderRadius.circular(24), ), child: Row( mainAxisSize: MainAxisSize.min, children: List.generate(_tabs.length, (index) { final selected = index == _currentIndex; return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _currentIndex = index), child: AnimatedContainer( duration: const Duration(milliseconds: 180), padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 8), decoration: BoxDecoration( color: selected ? Colors.blue : Colors.transparent, borderRadius: BorderRadius.circular(20), boxShadow: selected ? [ BoxShadow( color: Colors.blue.withOpacity(0.3), blurRadius: 4, offset: const Offset(0, 2), ) ] : [], ), child: Text( _tabs[index], style: TextStyle( color: selected ? Colors.white : Colors.grey.shade700, fontWeight: selected ? FontWeight.w500 : FontWeight.normal, ), ), ), ); }), ), )
如果需要选项等宽撑满父容器,直接给每个选项的外层套
Expanded组件即可,不需要额外计算宽度。
内容的提问来源于stack exchange,提问作者Sher Khan Kakar
相关产品推荐
相关产品推荐

