如何在Flutter中实现双选项滑动切换组件?求组件名称及实现方法
组件名称及Flutter实现方案
一、组件名称
这个组件叫做分段切换器(Segmented Control),最初是iOS系统的原生组件,后来被广泛应用于多平台APP设计中。它的核心逻辑是提供一组互斥的选项,通过滑动的高亮容器标识当前选中项,和你描述的设计完全匹配。
二、Flutter实现方案
下面提供两种实现方式,一种是用官方组件快速落地,另一种是自定义实现满足个性化样式需求。
1. 官方Cupertino组件快速实现
Flutter的cupertino库自带CupertinoSegmentedControl,原生支持滑动选中效果,代码示例:
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class SegmentedControlDemo extends StatefulWidget { const SegmentedControlDemo({super.key}); @override State<SegmentedControlDemo> createState() => _SegmentedControlDemoState(); } class _SegmentedControlDemoState extends State<SegmentedControlDemo> { int _selectedIndex = 0; final Map<int, Widget> _segments = { 0: const Text('Option 1'), 1: const Text('Option 2'), }; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: CupertinoSegmentedControl( children: _segments, groupValue: _selectedIndex, onValueChanged: (int value) { setState(() { _selectedIndex = value; }); }, selectedColor: Colors.blue, unselectedColor: Colors.grey.shade200, borderColor: Colors.blue, ), ), ); } }
该组件会自动处理选中块的滑动动画,样式可通过参数直接调整。
2. 自定义实现个性化样式
如果需要完全控制选中块形状、动画速度等细节,可通过Stack+AnimatedPositioned实现,代码示例:
import 'package:flutter/material.dart'; class CustomSegmentedControl extends StatefulWidget { final List<String> options; final ValueChanged<int> onSelected; final Color selectedBgColor; final Color unselectedTextColor; final Color selectedTextColor; const CustomSegmentedControl({ super.key, required this.options, required this.onSelected, this.selectedBgColor = Colors.blue, this.unselectedTextColor = Colors.black54, this.selectedTextColor = Colors.white, }); @override State<CustomSegmentedControl> createState() => _CustomSegmentedControlState(); } class _CustomSegmentedControlState extends State<CustomSegmentedControl> { int _selectedIndex = 0; @override Widget build(BuildContext context) { final double itemWidth = (MediaQuery.of(context).size.width - 20) / widget.options.length; return Container( margin: const EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: Colors.grey.shade200, ), child: Stack( children: [ // 滑动选中背景块 AnimatedPositioned( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, left: _selectedIndex * itemWidth, top: 0, bottom: 0, width: itemWidth, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: widget.selectedBgColor, ), ), ), // 选项文本区域 Row( children: List.generate(widget.options.length, (index) { return GestureDetector( onTap: () { setState(() { _selectedIndex = index; }); widget.onSelected(index); }, child: Container( width: itemWidth, padding: const EdgeInsets.symmetric(vertical: 12), alignment: Alignment.center, child: Text( widget.options[index], style: TextStyle( color: _selectedIndex == index ? widget.selectedTextColor : widget.unselectedTextColor, fontWeight: FontWeight.w500, ), ), ), ); }), ), ], ), ); } } // 使用示例 class CustomSegmentDemo extends StatelessWidget { const CustomSegmentDemo({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: CustomSegmentedControl( options: const ['Option 1', 'Option 2'], onSelected: (index) { print('选中了选项${index+1}'); }, ), ), ); } }
这种方式可以自由定制组件的圆角、动画曲线、文字样式等细节。
内容的提问来源于stack exchange,提问作者Cidiko Andorem
相关产品推荐
相关产品推荐

