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

Flutter开发:如何在Dropdown组件中嵌入GridView?

实现GridView样式的下拉选择组件

Flutter自带的DropdownButton确实不支持将下拉列表改为GridView布局,你可以通过自定义弹出层来实现需求,下面是原生实现的方案:

核心思路

用showMenu方法弹出一个包含GridView的自定义弹窗,配合状态管理实现选中逻辑,同时模拟下拉按钮的样式。

完整代码示例

class GridViewDropdown extends StatefulWidget {
  const GridViewDropdown({super.key});

  @override
  State<GridViewDropdown> createState() => _GridViewDropdownState();
}

class _GridViewDropdownState extends State<GridViewDropdown> {
  // 模拟选项数据,可根据需求替换
  final List<String> _options = List.generate(20, (index) => "选项${index+1}");
  String? _selectedOption;

  // 弹出GridView选择弹窗
  void _showGridViewPicker() async {
    final renderBox = context.findRenderObject() as RenderBox;
    final offset = renderBox.localToGlobal(Offset.zero);
    final size = renderBox.size;

    // 弹出菜单,嵌套GridView
    final selectedValue = await showMenu<String>(
      context: context,
      // 定位弹窗到按钮下方
      position: RelativeRect.fromLTRB(
        offset.dx,
        offset.dy + size.height,
        offset.dx + size.width,
        offset.dy + size.height + 300, // 弹窗固定高度
      ),
      items: [
        PopupMenuItem<String>(
          padding: EdgeInsets.zero,
          child: SizedBox(
            width: 300,
            height: 300,
            child: GridView.builder(
              padding: const EdgeInsets.all(8),
              // 配置GridView布局:每行3个,设置间距
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
                crossAxisSpacing: 8,
                mainAxisSpacing: 8,
              ),
              itemCount: _options.length,
              itemBuilder: (context, index) {
                final option = _options[index];
                return GestureDetector(
                  onTap: () => Navigator.pop(context, option),
                  child: Container(
                    decoration: BoxDecoration(
                      color: _selectedOption == option ? Colors.blue[100] : Colors.grey[100],
                      borderRadius: BorderRadius.circular(8),
                    ),
                    alignment: Alignment.center,
                    child: Text(option),
                  ),
                );
              },
            ),
          ),
        ),
      ],
    );

    // 更新选中值
    if (selectedValue != null) {
      setState(() {
        _selectedOption = selectedValue;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("GridView下拉选择")),
      body: Center(
        // 模拟下拉按钮样式
        child: InkWell(
          onTap: _showGridViewPicker,
          child: Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
            decoration: BoxDecoration(
              border: Border.all(color: Colors.grey),
              borderRadius: BorderRadius.circular(8),
            ),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(_selectedOption ?? "请选择"),
                const SizedBox(width: 8),
                const Icon(Icons.arrow_drop_down),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

关键说明

  • 弹窗定位:通过RelativeRect.fromLTRB将弹窗固定在触发按钮的正下方,你可以调整参数修改弹窗的位置和大小
  • 选中状态:点击GridView中的选项后,通过Navigator.pop返回选中值,再更新组件状态
  • 样式自定义:可以修改Container的装饰、GridView的行列数、间距等参数,适配你的UI需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 14:40:33