如何在Flutter中使用CupertinoPicker实现多级联动选择器
实现公交站点联动选择方案
下面是修改后的完整代码,实现选择服务区域后,第二个CupertinoPicker自动切换对应城市的公交站点:
class _BookingPageState extends State<BookingPage> { FixedExtentScrollController scrollController = FixedExtentScrollController(); final List<String> ibadanBusstop = [ 'Lead City Bus Stop', 'Olorunsogo Bus Stop', 'Challenge Bus Stop', 'Mokola Bus Stop', ]; final List<String> lagosBusstop = [ 'Jibowu Bus Stop', 'Obalende Bus Stop', ]; final List<String> serviceAreas = [ 'Lagos', 'Oyo', ]; // 合并索引变量,统一管理当前选中的公交站点索引 int currentBusStopIndex = 0; int serviceAreaIndex = 0; // 根据选中区域动态返回对应公交站点列表 List<String> get currentBusStops { if (serviceAreaIndex == 0) { // 选中Lagos return lagosBusstop; } else { // 选中Oyo return ibadanBusstop; } } @override Widget build(BuildContext context) { return Scaffold( body: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( height: FraserDimensions.xFlexHeight(context, 24), ), GestureDetector( onTap: () { scrollController.dispose(); scrollController = FixedExtentScrollController(initialItem: serviceAreaIndex); showCupertinoModalPopup( context: context, builder: (context) => CupertinoActionSheet( actions: [ SizedBox( height: FraserDimensions.xFlexHeight(context, 3), child: CupertinoPicker( scrollController: scrollController, itemExtent: 64, onSelectedItemChanged: (index) { setState(() { serviceAreaIndex = index; // 切换区域时重置公交站点索引,避免越界 currentBusStopIndex = 0; }); }, children: serviceAreas .map((e) => Center( child: Text( e, style: FraserTextStyle.textBlack24, ), )) .toList(), ), ) ], ), ); }, child: Container( width: FraserDimensions.xFlexWidth(context, 1), height: FraserDimensions.xFlexHeight(context, 18), decoration: BoxDecoration( color: FraserColors.line, borderRadius: const BorderRadius.all( Radius.circular(24), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Padding( padding: const EdgeInsets.only(left: 24.0), child: Text( serviceAreas[serviceAreaIndex], style: FraserTextStyle.textGrey16, ), ), ), Padding( padding: const EdgeInsets.only(right: 16.0), child: Icon( Icons.arrow_drop_down_outlined, color: FraserColors.primaryBlack, size: 22, ), ), ], ), ), ), SizedBox( height: FraserDimensions.xFlexHeight(context, 64), ), GestureDetector( onTap: () { scrollController.dispose(); scrollController = FixedExtentScrollController(initialItem: currentBusStopIndex); showCupertinoModalPopup( context: context, builder: (context) => CupertinoActionSheet( actions: [ SizedBox( height: FraserDimensions.xFlexHeight(context, 3), child: CupertinoPicker( scrollController: scrollController, itemExtent: 64, onSelectedItemChanged: (index) { setState(() { currentBusStopIndex = index; }); }, children: currentBusStops .map((e) => Center( child: Text( e, style: FraserTextStyle.textBlack24, ), )) .toList(), ), ) ], ), ); }, child: Container( width: FraserDimensions.xFlexWidth(context, 1), height: FraserDimensions.xFlexHeight(context, 18), decoration: BoxDecoration( color: FraserColors.line, borderRadius: const BorderRadius.all( Radius.circular(24), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Padding( padding: const EdgeInsets.only(left: 24.0), child: Text( currentBusStops[currentBusStopIndex], style: FraserTextStyle.textGrey16, ), ), ), Padding( padding: const EdgeInsets.only(right: 16.0), child: Icon( Icons.arrow_drop_down_outlined, color: FraserColors.primaryBlack, size: 22, ), ), ], ), ), ), ], ), ), ); } }
关键改动说明:
- 合并状态变量:移除
ibadanIndex和lagosIndex,改用currentBusStopIndex统一管理当前选中的公交站点索引,减少冗余状态。 - 动态获取站点列表:新增
currentBusStopsgetter,根据当前选中的serviceAreaIndex自动返回对应城市的公交站点列表。 - 切换区域重置索引:在第一个Picker的选择回调中,切换区域后将公交站点索引重置为0,避免因不同城市站点数量差异导致的索引越界问题。
- 第二个Picker动态绑定:将第二个Picker的数据源、初始选中项、索引更新逻辑全部绑定到动态变量,实现区域与站点的联动效果。
内容的提问来源于stack exchange,提问作者Amen O. Olabode
相关产品推荐
相关产品推荐

