Flutter如何实现可拖拽评论面板+回复输入框+@高亮功能

在Flutter开发中,想实现一个类似社交App的评论功能:底部有一个可拖拽的评论面板(类似小红书那样可以上下滑动),面板内要支持回复输入框,并且能在评论内容中高亮显示@的用户名。目前尝试过使用DraggableScrollableSheet实现面板拖拽,但遇到两个问题:1. 面板滑动到顶部时会突然弹回中间位置;2. 输入框获取焦点时键盘会把面板顶上去导致布局错乱。另外@高亮功能用RichText实现后发现性能较差,尤其在长评论区滚动时卡顿明显。请问有没有成熟的实现方案或优化建议?

2 回复

使用Draggable组件实现可拖拽面板,结合TextField输入框和GestureDetector处理@功能。通过TextSpan和RichText实现@高亮显示,监听输入变化匹配@符号触发用户列表。

更多关于Flutter如何实现可拖拽评论面板+回复输入框+@高亮功能的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中实现可拖拽评论面板、回复输入框和@高亮功能,可以通过以下步骤实现:

1. 可拖拽评论面板

使用DraggableScrollableSheet组件实现:

DraggableScrollableSheet(
  initialChildSize: 0.3, // 初始高度比例
  minChildSize: 0.1,     // 最小高度
  maxChildSize: 0.8,     // 最大高度
  builder: (context, scrollController) {
    return Container(
      decoration: BoxDecoration(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
        color: Colors.white,
      ),
      child: ListView.builder(
        controller: scrollController,
        itemCount: comments.length,
        itemBuilder: (context, index) => CommentItem(comments[index]),
      ),
    );
  },
)

2. 回复输入框与@高亮

使用TextField配合TextSpan实现:

class CommentInput extends StatefulWidget {
  @override
  _CommentInputState createState() => _CommentInputState();
}

class _CommentInputState extends State<CommentInput> {
  final TextEditingController _controller = TextEditingController();
  final FocusNode _focusNode = FocusNode();

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: _controller,
      focusNode: _focusNode,
      decoration: InputDecoration(
        hintText: '回复评论...',
        suffixIcon: IconButton(
          icon: Icon(Icons.send),
          onPressed: _submitComment,
        ),
      ),
    );
  }

  void _submitComment() {
    final text = _controller.text;
    // 处理@用户逻辑
    final atUsers = _extractAtUsers(text);
    // 提交评论
    _controller.clear();
  }

  List<String> _extractAtUsers(String text) {
    final RegExp atRegExp = RegExp(r'@(\w+)');
    return atRegExp.allMatches(text).map((match) => match.group(1)!).toList();
  }
}

3. @高亮显示

使用RichText显示评论内容:

Widget _buildCommentText(String content) {
  final atRegExp = RegExp(r'@(\w+)');
  final matches = atRegExp.allMatches(content);
  
  final textSpans = <TextSpan>[];
  int lastEnd = 0;

  for (final match in matches) {
    // 添加普通文本
    if (match.start > lastEnd) {
      textSpans.add(TextSpan(
        text: content.substring(lastEnd, match.start),
        style: TextStyle(color: Colors.black),
      ));
    }
    
    // 添加高亮@文本
    textSpans.add(TextSpan(
      text: match.group(0),
      style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
    ));
    
    lastEnd = match.end;
  }

  // 添加剩余文本
  if (lastEnd < content.length) {
    textSpans.add(TextSpan(
      text: content.substring(lastEnd),
      style: TextStyle(color: Colors.black),
    ));
  }

  return RichText(text: TextSpan(children: textSpans));
}

完整示例组合:

Scaffold(
  body: Stack(
    children: [
      // 主内容
      YourMainContent(),
      
      // 底部评论面板
      Align(
        alignment: Alignment.bottomCenter,
        child: DraggableScrollableSheet(
          // ... 参数配置
          builder: (context, scrollController) => Column(
            children: [
              Expanded(
                child: ListView.builder(
                  controller: scrollController,
                  itemBuilder: (context, index) => ListTile(
                    title: _buildCommentText(comments[index].content),
                  ),
                ),
              ),
              CommentInput(), // 回复输入框
            ],
          ),
        ),
      ),
    ],
  ),
)

关键点:

  1. 拖拽面板:使用DraggableScrollableSheet实现可拖拽效果
  2. @检测:通过正则表达式匹配@用户
  3. 高亮显示:使用RichTextTextSpan实现不同样式
  4. 输入处理:在提交时解析@用户并处理相关逻辑

这样的实现既保持了良好的用户体验,又具备了完整的功能特性。

回到顶部