新增一个chat_popup 来显示聊天窗口
This commit is contained in:
@@ -1,99 +0,0 @@
|
||||
import 'package:ai_chat_assistant/models/chat_message.dart';
|
||||
import 'package:basic_intl/intl.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../enums/message_status.dart';
|
||||
import '../widgets/chat_box.dart';
|
||||
import '../widgets/gradient_background.dart';
|
||||
import '../services/message_service.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../widgets/chat_header.dart';
|
||||
import '../widgets/chat_footer.dart';
|
||||
|
||||
class FullScreen extends StatefulWidget {
|
||||
const FullScreen({super.key});
|
||||
|
||||
@override
|
||||
State<FullScreen> createState() => _FullScreenState();
|
||||
}
|
||||
|
||||
class _FullScreenState extends State<FullScreen> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _scrollToBottom() {
|
||||
if (_scrollController.hasClients) {
|
||||
_scrollController.animateTo(
|
||||
0.0,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.easeOut,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: GradientBackground(
|
||||
colors: const [
|
||||
Color(0XFF3B0A3F),
|
||||
Color(0xFF0E0E24),
|
||||
Color(0xFF0C0B33),
|
||||
],
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
ChatHeader(
|
||||
onClose: () {
|
||||
Provider.of<MessageService>(context, listen: false)
|
||||
.abortReply();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Expanded(
|
||||
child: Consumer<MessageService>(
|
||||
builder: (context, messageService, child) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_scrollToBottom();
|
||||
});
|
||||
if (messageService.messages.isEmpty) {
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
String text = Intl.getCurrentLocale().startsWith('zh')
|
||||
? "您好,我是众众,请问有什么可以帮您?"
|
||||
: "Hi, I'm Zhongzhong, may I help you ? ";
|
||||
messageService.addMessage(text, false, MessageStatus.normal);
|
||||
});
|
||||
}
|
||||
return ChatBox(
|
||||
scrollController: _scrollController,
|
||||
messages: messageService.messages,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Consumer<MessageService>(
|
||||
builder: (context, messageService, child) => ChatFooter(
|
||||
onClear: () {
|
||||
messageService.abortReply();
|
||||
messageService.clearMessages();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../widgets/floating_icon.dart';
|
||||
import '../utils/assets_util.dart';
|
||||
import '../widgets/chat_popup.dart';
|
||||
import '../widgets/chat_floating_icon.dart';
|
||||
|
||||
class MainScreen extends StatefulWidget {
|
||||
const MainScreen({super.key});
|
||||
@@ -34,7 +36,8 @@ class _MainScreenState extends State<MainScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
FloatingIcon(),
|
||||
// FloatingIcon(),
|
||||
ChatPopup()
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:ui';
|
||||
import '../widgets/chat_box.dart';
|
||||
import '../screens/full_screen.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../services/message_service.dart';
|
||||
import '../widgets/gradient_background.dart';
|
||||
import '../utils/assets_util.dart';
|
||||
import '../pages/full_screen.dart';
|
||||
|
||||
class PartScreen extends StatefulWidget {
|
||||
final VoidCallback? onHide;
|
||||
@@ -66,7 +66,7 @@ class _PartScreenState extends State<PartScreen> {
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ChangeNotifierProvider.value(
|
||||
value: messageService, // 传递同一个单例实例
|
||||
child: const FullScreen(),
|
||||
child: const FullScreenPage(),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -76,13 +76,21 @@ class _PartScreenState extends State<PartScreen> {
|
||||
EdgeInsets _calculatePosition(BoxConstraints constraints) {
|
||||
final screenWidth = constraints.maxWidth;
|
||||
final screenHeight = constraints.maxHeight;
|
||||
final iconX = screenWidth - widget.floatingIconPosition.dx;
|
||||
final iconY = screenHeight - widget.floatingIconPosition.dy;
|
||||
|
||||
// 聊天框的尺寸
|
||||
final chatWidth = screenWidth * 0.94;
|
||||
final maxChatHeight = screenHeight * 0.4;
|
||||
|
||||
final iconX = screenWidth - widget.floatingIconPosition.dx;
|
||||
final iconY = screenHeight - widget.floatingIconPosition.dy;
|
||||
|
||||
// 1. 先将icon的right/bottom转为屏幕坐标(icon左下角)
|
||||
var iconPosition = widget.floatingIconPosition;
|
||||
|
||||
final iconLeft = screenWidth - iconPosition.dx - widget.iconSize;
|
||||
final iconBottom = iconPosition.dy;
|
||||
final iconTop = iconBottom + widget.iconSize;
|
||||
final iconCenterX = iconLeft + widget.iconSize / 2;
|
||||
|
||||
// 判断FloatingIcon在屏幕的哪一边
|
||||
final isOnRightSide = iconX < screenWidth / 2;
|
||||
|
||||
@@ -96,18 +104,31 @@ class _PartScreenState extends State<PartScreen> {
|
||||
leftPadding = screenWidth - chatWidth - (screenWidth - chatWidth) * 0.1;
|
||||
}
|
||||
|
||||
// 计算垂直位置,确保聊天框在图标上方
|
||||
double bottomPadding = iconY + widget.iconSize + 20;
|
||||
// 优先尝试放在icon上方
|
||||
double chatBottom = iconTop + 12; // 聊天框底部距离icon顶部12px
|
||||
double chatTop = screenHeight - chatBottom - maxChatHeight;
|
||||
|
||||
// 确保聊天框不会超出屏幕
|
||||
final minBottomPadding = screenHeight * 0.15;
|
||||
final maxBottomPadding = screenHeight - maxChatHeight - 50;
|
||||
bottomPadding = bottomPadding.clamp(minBottomPadding, maxBottomPadding);
|
||||
// 如果上方空间不足,则放在icon下方
|
||||
if (chatTop < 0) {
|
||||
chatBottom = iconBottom - 12 - maxChatHeight / 2; // 聊天框顶部距离icon底部12px
|
||||
// 如果下方也不足,则贴底
|
||||
if (chatBottom < 0) {
|
||||
chatBottom = 20; // 距离底部20px
|
||||
}
|
||||
}
|
||||
|
||||
// // 计算垂直位置,确保聊天框在图标上方
|
||||
// double bottomPadding = iconY + widget.iconSize + 20;
|
||||
//
|
||||
// // 确保聊天框不会超出屏幕
|
||||
// final minBottomPadding = screenHeight * 0.15;
|
||||
// final maxBottomPadding = screenHeight - maxChatHeight - 50;
|
||||
// bottomPadding = bottomPadding.clamp(minBottomPadding, maxBottomPadding);
|
||||
|
||||
return EdgeInsets.only(
|
||||
left: leftPadding,
|
||||
right: screenWidth - leftPadding - chatWidth,
|
||||
bottom: bottomPadding,
|
||||
bottom: chatBottom,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user