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

Flutter:如何删除动态创建并存储在列表中的自定义Tag组件?

Flutter 自定义标签组件删除与UI更新解决方案

核心问题解决思路

  1. 精准删除标签:传递索引到删除函数
    给自定义Tag组件的删除回调绑定当前标签在列表中的索引,让deleteTag能精准定位要删除的元素,避免重复标签删除出错。
  2. 触发UI更新:状态驱动刷新
    标签列表修改后必须调用setState((){}),通知Flutter框架重新构建UI,否则ListView.builder无法感知列表变化。

完整代码实现

import 'package:flutter/material.dart';

void main() => runApp(const TagDemoApp());

class TagDemoApp extends StatelessWidget {
  const TagDemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('自定义标签示例')),
        body: const TagListPage(),
      ),
    );
  }
}

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

  @override
  State<TagListPage> createState() => _TagListPageState();
}

class _TagListPageState extends State<TagListPage> {
  // 存储标签的列表
  final List<String> tags = [];

  // 添加标签的函数
  void add_tag(String tagName) {
    setState(() {
      tags.add(tagName);
    });
  }

  // 删除标签的函数,接收索引参数
  void deleteTag(int index) {
    setState(() {
      tags.removeAt(index);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          // 添加标签的输入框和按钮
          Row(
            children: [
              Expanded(
                child: TextField(
                  decoration: const InputDecoration(hintText: '输入标签名'),
                  onSubmitted: add_tag, // 回车提交添加标签
                ),
              ),
              const SizedBox(width: 8),
              ElevatedButton(
                onPressed: () {
                  add_tag('test_${tags.length + 1}');
                },
                child: const Text('添加标签'),
              ),
            ],
          ),
          const SizedBox(height: 16),
          // 标签列表
          Expanded(
            child: ListView.builder(
              itemCount: tags.length,
              itemBuilder: (context, index) {
                return Tag(
                  name: tags[index],
                  onDelete: () => deleteTag(index), // 绑定当前索引到删除回调
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

// 自定义Tag组件
class Tag extends StatelessWidget {
  final String name;
  final VoidCallback onDelete;

  const Tag({super.key, required this.name, required this.onDelete});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Stack(
        children: [
          // 标签容器
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
            margin: const EdgeInsets.only(left: 16), // 给删除按钮留位置
            decoration: BoxDecoration(
              color: Colors.grey[200],
              borderRadius: BorderRadius.circular(20),
            ),
            child: Text(name),
          ),
          // 左上角红色删除按钮
          Positioned(
            left: 0,
            top: 0,
            child: GestureDetector(
              onTap: onDelete,
              child: Container(
                width: 32,
                height: 32,
                decoration: const BoxDecoration(
                  color: Colors.red,
                  shape: BoxShape.circle,
                ),
                child: const Icon(Icons.close, color: Colors.white, size: 18),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

关键细节说明

  • Tag组件删除回调:通过onDelete传递绑定了当前索引的匿名函数,点击删除按钮时直接触发deleteTag(index),精准删除对应标签。
  • 状态刷新逻辑:所有修改tags列表的操作(添加、删除)都包裹在setState中,确保Flutter感知到列表变化并更新UI。
  • ListView.builder配置:itemCount必须设置为tags.length,否则框架无法确定渲染数量;itemBuilder根据索引从列表中取对应数据构建组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:40:11