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

Flutter聊天应用中选中ActionChip时如何重建ListView

解决ActionChip点击后ListView不更新的问题

你的问题核心是:点击ActionChip时,虽然已经往列表里添加了新内容,但因为没调用setState()触发状态更新,所以ListView不会自动重建刷新。

直接修复方案

只需要把ActionChip的onPressed里的逻辑包裹进setState()即可,修改状态后会通知Flutter重新构建UI:

import 'package:flutter/material.dart';
import 'package:chat_bubbles/chat_bubbles.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Chat(),
    );
  }
}

class Chat extends StatefulWidget {
  const Chat({
    Key? key,
  }) : super(key: key);

  @override
  _ChatState createState() => _ChatState();
}

class _ChatState extends State<Chat> {
  List<Container> listViews = [];
  int _numLists = 0;

  void _addItemsToView() {
    setState(() {
      listViews.add(Container(
        child: BubbleNormal(
          text: 'Select one of these options',
          isSender: false,
          color: Color(0xFF1B97F3),
          tail: true,
          textStyle: TextStyle(
            fontSize: 20,
            color: Colors.white,
          ),
        ),
      ));
      _numLists++;

      var actionChipOptions = ['option 1', 'option 2', 'option 3'];
      for (int i = 0; i < actionChipOptions.length; i++) {
        debugPrint('Adding chip $i');
        listViews.add(Container(
          child: ActionChip(
              label: Text(actionChipOptions[i]),
              onPressed: () {
                setState(() { // 这里添加setState包裹状态更新逻辑
                  final selectedOption = actionChipOptions[i];
                  listViews.add(Container(
                    child: BubbleNormal(
                      text: selectedOption,
                      isSender: true,
                      color: Color(0xFFE8E8EE),
                      tail: true,
                      sent: true,
                    ),
                  ));
                  _numLists++;
                });
              }),
        ));
        _numLists++;
      };
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ActionChips in ListView'),
      ),
      body: Center(
        child: ListView.builder(
            itemCount: _numLists,
            itemBuilder: (context, index) => listViews[index]),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addItemsToView,
        tooltip: 'Add Item',
        child: const Icon(Icons.add),
      ),
    );
  }
}

优化建议(更规范的写法)

直接存储Widget列表不是最佳实践,建议用数据模型管理聊天内容,区分消息类型,代码会更易维护:

import 'package:flutter/material.dart';
import 'package:chat_bubbles/chat_bubbles.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Chat(),
    );
  }
}

// 定义消息类型枚举
enum MessageType { bubble, chip }
// 定义消息数据模型
class ChatMessage {
  final MessageType type;
  final String content;
  final bool isSender;

  ChatMessage({required this.type, required this.content, this.isSender = false});
}

class Chat extends StatefulWidget {
  const Chat({Key? key}) : super(key: key);

  @override
  _ChatState createState() => _ChatState();
}

class _ChatState extends State<Chat> {
  final List<ChatMessage> _messages = [];

  void _addItemsToView() {
    setState(() {
      // 添加提示气泡
      _messages.add(ChatMessage(
        type: MessageType.bubble,
        content: 'Select one of these options',
        isSender: false,
      ));
      // 添加选项芯片
      ['option 1', 'option 2', 'option 3'].forEach((option) {
        _messages.add(ChatMessage(
          type: MessageType.chip,
          content: option,
        ));
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ActionChips in ListView'),
      ),
      body: ListView.builder(
        itemCount: _messages.length,
        itemBuilder: (context, index) {
          final message = _messages[index];
          // 根据消息类型生成对应的UI
          switch(message.type) {
            case MessageType.bubble:
              return BubbleNormal(
                text: message.content,
                isSender: message.isSender,
                color: message.isSender ? Color(0xFFE8E8EE) : Color(0xFF1B97F3),
                tail: true,
                sent: message.isSender,
                textStyle: TextStyle(
                  fontSize: 20,
                  color: message.isSender ? Colors.black : Colors.white,
                ),
              );
            case MessageType.chip:
              return ActionChip(
                label: Text(message.content),
                onPressed: () {
                  setState(() {
                    // 点击芯片后添加用户选择的气泡消息
                    _messages.add(ChatMessage(
                      type: MessageType.bubble,
                      content: message.content,
                      isSender: true,
                    ));
                  });
                },
              );
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addItemsToView,
        tooltip: 'Add Item',
        child: const Icon(Icons.add),
      ),
    );
  }
}

这种写法把数据和UI分离,后续扩展功能(比如修改样式、添加更多消息类型)会更灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 18:54:40