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

Flutter Flame中选中组件时添加名称标签的实现方法

在Flutter Flame中实现选中组件顶部显示名称文本

1. 定义可选中的自定义组件

创建继承PositionComponent并混入TapCallbacks的组件类,用来处理点击选中逻辑,同时维护选中状态和名称属性:

class SelectableComponent extends PositionComponent with TapCallbacks, HasGameRef {
  final String name;
  bool isSelected = false;
  late TextPaint textPaint;

  SelectableComponent({required this.name, required Vector2 size}) : super(size: size) {
    // 初始化文本画笔,设置样式
    textPaint = TextPaint(
      style: const TextStyle(
        color: Colors.white,
        fontSize: 16,
        fontWeight: FontWeight.bold,
      ),
    );
  }

  // 点击切换选中状态
  @override
  void onTapDown(TapDownEvent event) {
    isSelected = !isSelected;
    // 如需单选,取消其他组件选中状态
    // gameRef.children.whereType<SelectableComponent>().forEach((comp) {
    //   if (comp != this) comp.isSelected = false;
    // });
    super.onTapDown(event);
  }

  // 绘制组件本体与选中时的名称文本
  @override
  void render(Canvas canvas) {
    super.render(canvas);
    // 绘制组件基础样式(示例为矩形)
    Paint paint = Paint()..color = isSelected ? Colors.blue : Colors.grey;
    canvas.drawRect(size.toRect(), paint);

    // 选中时在顶部绘制名称
    if (isSelected) {
      final textSize = textPaint.measureText(name);
      // 计算文本位置:组件顶部居中,向上偏移4px
      final textX = (size.x - textSize.width) / 2;
      final textY = -textSize.height - 4;
      textPaint.render(canvas, name, Vector2(textX, textY));
    }
  }
}

2. 在游戏类中添加组件

在你的Flame游戏类里初始化并挂载自定义组件:

class MyGame extends FlameGame {
  @override
  Future<void> onLoad() async {
    super.onLoad();
    // 添加两个示例组件到不同位置
    add(SelectableComponent(
      name: "组件A",
      size: Vector2(100, 100),
    )..position = Vector2(100, 100));

    add(SelectableComponent(
      name: "组件B",
      size: Vector2(100, 100),
    )..position = Vector2(300, 100));
  }
}

3. 可选:用TextComponent子组件实现

如果偏好组件化的方式,可以给SelectableComponent添加TextComponent子组件,通过控制visible属性显示/隐藏名称:

class SelectableComponent extends PositionComponent with TapCallbacks, HasGameRef {
  final String name;
  bool isSelected = false;
  late TextComponent nameText;

  SelectableComponent({required this.name, required Vector2 size}) : super(size: size) {
    nameText = TextComponent(
      text: name,
      textRenderer: TextPaint(
        style: const TextStyle(
          color: Colors.white,
          fontSize: 16,
          fontWeight: FontWeight.bold,
        ),
      ),
      position: Vector2(size.x / 2, -20), // 顶部居中位置
      anchor: Anchor.center,
    )..visible = false;
    add(nameText);
  }

  @override
  void onTapDown(TapDownEvent event) {
    isSelected = !isSelected;
    nameText.visible = isSelected;
    // 单选逻辑同上
    super.onTapDown(event);
  }

  @override
  void render(Canvas canvas) {
    super.render(canvas);
    Paint paint = Paint()..color = isSelected ? Colors.blue : Colors.grey;
    canvas.drawRect(size.toRect(), paint);
  }
}

核心注意点

  • 借助TapCallbacks监听组件点击,切换选中状态
  • 两种文本显示方式按需选择:直接绘制更轻量,子组件方式更符合Flame组件化思想
  • 文本位置需根据组件尺寸计算,确保在顶部居中显示
  • 单选场景下,记得在选中当前组件时取消其他同类型组件的选中状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 19:26:28