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

如何在Flame游戏中添加可选择值的Dropdown Button?

在Flame中实现下拉菜单(Dropdown Button)

当然可以在Flame中实现下拉菜单,这里提供两种常用方案:

方案一:通过WidgetComponent集成Flutter原生DropdownButton

Flame提供了WidgetComponent,可以直接将Flutter的Widget嵌入到Flame游戏场景中,完美解决你提到的“Flutter组件非Flame组件”的问题。

实现步骤:

  1. 创建一个继承自WidgetComponent的类,包裹Flutter的DropdownButton:
class FlameDropdown extends WidgetComponent {
  final List<String> options;
  String selectedValue;
  final Function(String) onChanged;

  FlameDropdown({
    required this.options,
    required this.selectedValue,
    required this.onChanged,
    super.position,
    super.size,
  });

  @override
  Widget build(BuildContext context) {
    return DropdownButton<String>(
      value: selectedValue,
      items: options.map((String value) {
        return DropdownMenuItem<String>(
          value: value,
          child: Text(value),
        );
      }).toList(),
      onChanged: (String? newValue) {
        if (newValue != null) {
          onChanged(newValue);
          selectedValue = newValue;
          markNeedsBuild(); // 更新组件
        }
      },
    );
  }
}
  1. 在你的FlameGame中添加这个组件:
class MyGame extends FlameGame {
  late FlameDropdown dropdown;

  @override
  Future<void> onLoad() async {
    super.onLoad();
    dropdown = FlameDropdown(
      options: ['选项1', '选项2', '选项3'],
      selectedValue: '选项1',
      onChanged: (value) {
        print('选中了:$value');
        // 这里处理选择后的逻辑
      },
      position: Vector2(100, 50), // 设置下拉菜单在游戏中的位置
      size: Vector2(200, 50), // 设置组件大小
    );
    add(dropdown);
  }
}

方案二:纯Flame组件自定义下拉菜单

如果不想依赖Flutter的Widget,可以用Flame的基础组件(PositionComponent、TextComponent等)手动实现一个下拉菜单:

实现思路:

  • 创建一个主组件作为下拉按钮,显示当前选中值
  • 点击主组件时,展开/收起选项列表组件
  • 每个选项用TextComponent实现,点击时更新选中值并收起列表

示例代码:

class CustomDropdown extends PositionComponent {
  final List<String> options;
  String _selectedValue;
  bool _isExpanded = false;
  late final TextComponent _buttonText;
  late final PositionComponent _optionsContainer;

  CustomDropdown({
    required this.options,
    required String initialValue,
    super.position,
    super.size,
  }) : _selectedValue = initialValue;

  @override
  Future<void> onLoad() async {
    super.onLoad();
    // 构建下拉按钮
    final buttonBackground = RectangleComponent(
      size: size,
      paint: Paint()..color = Colors.grey.shade300,
    );
    add(buttonBackground);

    _buttonText = TextComponent(
      text: _selectedValue,
      textRenderer: TextPaint(
        style: const TextStyle(color: Colors.black, fontSize: 16),
      ),
      position: size / 2,
      anchor: Anchor.center,
    );
    add(_buttonText);

    // 构建选项容器(默认隐藏)
    _optionsContainer = PositionComponent(
      position: Vector2(0, size.y),
      size: Vector2(size.x, size.y * options.length),
      visible: false,
    );
    add(_optionsContainer);

    // 添加选项
    for (int i = 0; i < options.length; i++) {
      final optionBackground = RectangleComponent(
        size: Vector2(size.x, size.y),
        position: Vector2(0, size.y * i),
        paint: Paint()..color = Colors.white,
      );
      final optionText = TextComponent(
        text: options[i],
        textRenderer: TextPaint(
          style: TextStyle(
            color: options[i] == _selectedValue ? Colors.blue : Colors.black,
            fontSize: 16,
          ),
        ),
        position: Vector2(size.x / 2, size.y * i + size.y / 2),
        anchor: Anchor.center,
      );
      // 给选项添加点击事件
      optionBackground.add(RectangleHitbox());
      optionBackground.onTapDown = (event) {
        _selectedValue = options[i];
        _buttonText.text = _selectedValue;
        _isExpanded = false;
        _optionsContainer.visible = false;
        // 更新选项文本颜色
        for (final child in _optionsContainer.children) {
          if (child is TextComponent) {
            child.textRenderer = TextPaint(
              style: TextStyle(
                color: child.text == _selectedValue ? Colors.blue : Colors.black,
                fontSize: 16,
              ),
            );
          }
        }
      };
      _optionsContainer.add(optionBackground);
      _optionsContainer.add(optionText);
    }

    // 给下拉按钮添加点击事件
    add(RectangleHitbox());
    onTapDown = (event) {
      _isExpanded = !_isExpanded;
      _optionsContainer.visible = _isExpanded;
    };
  }
}

然后在游戏中添加这个自定义组件:

class MyGame extends FlameGame {
  @override
  Future<void> onLoad() async {
    super.onLoad();
    add(CustomDropdown(
      options: ['选项A', '选项B', '选项C'],
      initialValue: '选项A',
      position: Vector2(100, 50),
      size: Vector2(200, 50),
    ));
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 03:43:31