You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

322 lines
10 KiB

import 'package:dating_touchme_app/extension/ex_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../generated/assets.dart';
import '../../config/emoji_config.dart';
import '../emoji_panel.dart';
import 'more_options_view.dart';
import 'voice_input_view.dart';
import 'video_input_view.dart';
class ChatInputBar extends StatefulWidget {
final ValueChanged<String> onSendMessage;
final ValueChanged<List<String>>? onImageSelected;
final Function(String filePath, int seconds)? onVoiceRecorded;
final Function(String filePath, int duration)? onVideoRecorded;
const ChatInputBar({
required this.onSendMessage,
this.onImageSelected,
this.onVoiceRecorded,
this.onVideoRecorded,
super.key,
});
@override
State<ChatInputBar> createState() => _ChatInputBarState();
}
class _ChatInputBarState extends State<ChatInputBar> {
final TextEditingController _textController = TextEditingController();
bool _isMoreOptionsVisible = false;
bool _isVoiceVisible = false;
bool _isVideoVisible = false;
bool _isEmojiVisible = false;
void _handleSendMessage() {
if (_textController.text.isNotEmpty) {
widget.onSendMessage(_textController.text);
_textController.clear();
}
}
// 切换更多选项的显示状态
void _toggleMoreOptions() {
print('📷 [ChatInputBar] 更多选项(图片)按钮被点击');
setState(() {
_isMoreOptionsVisible = !_isMoreOptionsVisible;
if (_isMoreOptionsVisible) {
_isVoiceVisible = false;
_isVideoVisible = false;
_isEmojiVisible = false;
}
// 收起键盘
FocusManager.instance.primaryFocus?.unfocus();
});
}
void _handleImageTap(List<String> imagePaths) {
// 将图片路径列表传递给父组件
if (widget.onImageSelected != null) {
widget.onImageSelected!(imagePaths);
}
}
void _handleCameraTap(String imagePath) {
// 将单个图片路径包装成列表传递给父组件
if (widget.onImageSelected != null) {
widget.onImageSelected!([imagePath]);
}
}
void _toggleVoiceOptions() {
setState(() {
_isVoiceVisible = !_isVoiceVisible;
if (_isVoiceVisible) {
_isMoreOptionsVisible = false;
_isVideoVisible = false;
_isEmojiVisible = false;
}
FocusManager.instance.primaryFocus?.unfocus();
});
}
void _toggleVideoOptions() {
print('🎬 [ChatInputBar] 视频按钮被点击,当前状态: $_isVideoVisible');
setState(() {
_isVideoVisible = !_isVideoVisible;
if (_isVideoVisible) {
_isMoreOptionsVisible = false;
_isVoiceVisible = false;
_isEmojiVisible = false;
}
FocusManager.instance.primaryFocus?.unfocus();
});
print('🎬 [ChatInputBar] 视频面板状态改变为: $_isVideoVisible');
}
void _toggleEmojiPanel() {
setState(() {
_isEmojiVisible = !_isEmojiVisible;
if (_isEmojiVisible) {
_isMoreOptionsVisible = false;
_isVoiceVisible = false;
_isVideoVisible = false;
}
FocusManager.instance.primaryFocus?.unfocus();
});
}
void _handleEmojiSelected(EmojiItem emoji) {
// 将表情添加到输入框
final currentText = _textController.text;
final emojiText = '[emoji:${emoji.id}]';
_textController.text = currentText + emojiText;
// 将光标移到末尾
_textController.selection = TextSelection.fromPosition(
TextPosition(offset: _textController.text.length),
);
setState(() {}); // 刷新显示
}
/// 构建输入框内容(文本+表情)
List<Widget> _buildInputContentWidgets() {
final List<Widget> widgets = [];
final text = _textController.text;
final RegExp emojiRegex = RegExp(r'\[emoji:(\d+)\]');
int lastMatchEnd = 0;
final matches = emojiRegex.allMatches(text);
for (final match in matches) {
// 添加表情之前的文本
if (match.start > lastMatchEnd) {
final textPart = text.substring(lastMatchEnd, match.start);
widgets.add(
Text(
textPart,
style: TextStyle(fontSize: 14.sp, color: Colors.black),
),
);
}
// 添加表情图片
final emojiId = match.group(1);
if (emojiId != null) {
final emoji = EmojiConfig.getEmojiById(emojiId);
if (emoji != null) {
widgets.add(
Padding(
padding: EdgeInsets.symmetric(horizontal: 2.w),
child: Image.asset(
emoji.path,
width: 24.w,
height: 24.w,
fit: BoxFit.contain,
),
),
);
}
}
lastMatchEnd = match.end;
}
// 添加剩余的文本
if (lastMatchEnd < text.length) {
final textPart = text.substring(lastMatchEnd);
widgets.add(
Text(
textPart,
style: TextStyle(fontSize: 14.sp, color: Colors.black),
),
);
}
return widgets;
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 16.w),
color: Colors.white,
child: Column(
children: [
SizedBox(height: 10.h),
Row(
children: [
Expanded(
child: Container(
height: 40.h,
decoration: BoxDecoration(
color: Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(5.h),
),
padding: EdgeInsets.symmetric(horizontal: 16.w),
child: Stack(
children: [
// 真实的输入框
TextField(
controller: _textController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: "请输入聊天内容~",
hintStyle: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
),
),
style: TextStyle(
fontSize: 14.sp,
color: _textController.text.contains('[emoji:')
? Colors.transparent
: Colors.black,
),
onChanged: (value) {
setState(() {}); // 刷新以更新表情显示
},
),
// 表情显示层
if (_textController.text.contains('[emoji:'))
Positioned.fill(
child: IgnorePointer(
child: Align(
alignment: Alignment.centerLeft,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: _buildInputContentWidgets(),
),
),
),
),
),
],
),
),
),
SizedBox(width: 12.w),
// 发送按钮
Container(
padding: EdgeInsets.symmetric(
horizontal: 16.w,
vertical: 8.h,
),
decoration: BoxDecoration(
color: Color.fromRGBO(117, 98, 249, 1),
borderRadius: BorderRadius.circular(5.h),
),
child: Text(
"发送",
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
).onTap(_handleSendMessage),
],
),
SizedBox(height: 12.h),
// 底部工具栏
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// 语音按钮
Image.asset(
Assets.imagesAudio,
width: 24.w,
height: 24.w,
).onTap(_toggleVoiceOptions),
// 视频按钮
Image.asset(
Assets.imagesVideo,
width: 24.w,
height: 24.w,
).onTap(_toggleVideoOptions),
// 礼物按钮
Image.asset(Assets.imagesGift, width: 24.w, height: 24.w),
// 表情按钮
Image.asset(Assets.imagesEmoji, width: 24.w, height: 24.w).onTap(_toggleEmojiPanel),
// 更多按钮
Image.asset(
Assets.imagesAdd,
width: 24.w,
height: 24.w,
).onTap(_toggleMoreOptions),
],
),
],
),
),
// 更多选项展开视图(支持图片和视频)
MoreOptionsView(
isVisible: _isMoreOptionsVisible,
onImageSelected: _handleImageTap,
onCameraSelected: _handleCameraTap,
onVideoSelected: widget.onVideoRecorded,
),
// 语音输入展开视图(与 MoreOptionsView 相同的展开方式)
VoiceInputView(
isVisible: _isVoiceVisible,
onVoiceRecorded: widget.onVoiceRecorded,
),
// 视频输入展开视图
VideoInputView(
isVisible: _isVideoVisible,
onVideoRecorded: widget.onVideoRecorded,
),
// 表情面板
EmojiPanel(
isVisible: _isEmojiVisible,
onEmojiSelected: _handleEmojiSelected,
),
],
);
}
}