You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中实现带图标、点击上下箭头切换选中的下拉组件

带图标上下箭头选择器效果图

实现思路
  • 整体用StatefulWidget开发,需要维护选中下标状态来刷新UI
  • 核心布局分为三个模块:顶部上箭头点击区域、选中项展示区域(图标+文字)、底部下箭头点击区域
  • 点击上箭头时选中下标减1,点击下箭头时选中下标加1,均需要做边界判断,避免数组越界
完整实现代码

首先定义选项数据模型:

class OptionItem {
  final IconData icon;
  final String title;
  const OptionItem({required this.icon, required this.title});
}

选择器核心组件代码:

class IconArrowPicker extends StatefulWidget {
  // 所有可选选项列表
  final List<OptionItem> optionList;
  // 默认选中下标,可选参数
  final int defaultIndex;
  const IconArrowPicker({super.key, required this.optionList, this.defaultIndex = 0});

  @override
  State<IconArrowPicker> createState() => _IconArrowPickerState();
}

class _IconArrowPickerState extends State<IconArrowPicker> {
  late int _currentSelectedIndex;

  @override
  void initState() {
    super.initState();
    _currentSelectedIndex = widget.defaultIndex;
    // 初始化时做边界校验
    if (_currentSelectedIndex < 0) _currentSelectedIndex = 0;
    if (_currentSelectedIndex >= widget.optionList.length) _currentSelectedIndex = widget.optionList.length -1;
  }

  // 切换到上一个选项
  void _toPrev() {
    if (_currentSelectedIndex <= 0) return;
    setState(() {
      _currentSelectedIndex --;
    });
  }

  // 切换到下一个选项
  void _toNext() {
    if (_currentSelectedIndex >= widget.optionList.length -1) return;
    setState(() {
      _currentSelectedIndex ++;
    });
  }

  @override
  Widget build(BuildContext context) {
    final currentItem = widget.optionList[_currentSelectedIndex];
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        // 上箭头
        IconButton(
          onPressed: _toPrev,
          icon: const Icon(Icons.arrow_drop_up, size: 32),
          padding: EdgeInsets.zero,
          constraints: const BoxConstraints(),
        ),
        const SizedBox(height: 8),
        // 选中项展示
        Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(currentItem.icon, size: 24),
            const SizedBox(width: 8),
            Text(currentItem.title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
          ],
        ),
        const SizedBox(height: 8),
        // 下箭头
        IconButton(
          onPressed: _toNext,
          icon: const Icon(Icons.arrow_drop_down, size: 32),
          padding: EdgeInsets.zero,
          constraints: const BoxConstraints(),
        ),
      ],
    );
  }
}

组件调用示例:

// 页面中使用
IconArrowPicker(
  optionList: const [
    OptionItem(icon: Icons.directions_car, title: "驾车"),
    OptionItem(icon: Icons.directions_bus, title: "公交"),
    OptionItem(icon: Icons.directions_walk, title: "步行"),
    OptionItem(icon: Icons.directions_bike, title: "骑行"),
  ],
  defaultIndex: 0,
)
调整说明
  • 可以直接修改Icon、Text的样式参数适配你的设计需求
  • 如果需要增加选项切换的动画效果,可以在选中项外层包裹AnimatedSwitcher组件实现过渡动画
  • 可以自定义箭头的样式、点击热区大小,提升移动端点击舒适度

内容的提问来源于stack exchange,提问作者Mahi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 23:09:04