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(), // 回复输入框
],
),
),
),
],
),
)
关键点:
- 拖拽面板:使用
DraggableScrollableSheet实现可拖拽效果 - @检测:通过正则表达式匹配@用户
- 高亮显示:使用
RichText和TextSpan实现不同样式 - 输入处理:在提交时解析@用户并处理相关逻辑
这样的实现既保持了良好的用户体验,又具备了完整的功能特性。

