diff --git a/app/(tabs)/ask.tsx b/app/(tabs)/ask.tsx index d157744..1c90adc 100644 --- a/app/(tabs)/ask.tsx +++ b/app/(tabs)/ask.tsx @@ -6,7 +6,7 @@ import { ThemedText } from "@/components/ThemedText"; import { fetchApi } from "@/lib/server-api-util"; import { Message } from "@/types/ask"; import { router, useLocalSearchParams } from "expo-router"; -import React, { useEffect, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { Animated, Keyboard, @@ -14,6 +14,7 @@ import { Platform, ScrollView, StyleSheet, + TextInput, TouchableOpacity, View } from 'react-native'; @@ -38,14 +39,56 @@ export default function AskScreen() { newSession: string; }>(); - // 处理滚动到底部 - useEffect(() => { + // 处理滚动到底部 - 优化版本 + const scrollToBottom = useCallback((animated = true) => { if (scrollViewRef.current && !isHello) { - scrollViewRef.current.scrollToEnd({ animated: true }); + // 使用更长的延迟确保内容渲染完成 + setTimeout(() => { + scrollViewRef.current?.scrollToEnd({ animated }); + }, 150); } - }, [userMessages, isHello]); + }, [isHello]); - // 处理路由参数 + // 监听键盘显示/隐藏事件 - 增强版本 + useEffect(() => { + const keyboardDidShowListener = Keyboard.addListener( + 'keyboardDidShow', + (e) => { + // 键盘显示时滚动到底部 + setTimeout(() => { + scrollToBottom(true); + }, 100); + } + ); + + const keyboardDidHideListener = Keyboard.addListener( + 'keyboardDidHide', + () => { + // 键盘隐藏时也滚动到底部(可选) + setTimeout(() => { + scrollToBottom(false); + }, 100); + } + ); + + return () => { + keyboardDidShowListener.remove(); + keyboardDidHideListener.remove(); + }; + }, [scrollToBottom]); + + // 处理消息变化时滚动 - 优化版本 + useEffect(() => { + if (!isHello && userMessages.length > 0) { + // 消息变化时立即滚动到底部 + const timer = setTimeout(() => { + scrollToBottom(true); + }, 50); + return () => clearTimeout(timer); + } + }, [userMessages.length, isHello, scrollToBottom]); + + // 处理路由参数 - 优化版本 useEffect(() => { if (sessionId) { setConversationId(sessionId); @@ -81,17 +124,56 @@ export default function AskScreen() { Animated.parallel([ Animated.timing(fadeAnim, { toValue: 0, - duration: 1000, + duration: 300, useNativeDriver: true, }), Animated.timing(fadeAnimChat, { toValue: 1, - duration: 1000, + duration: 300, useNativeDriver: true, }) - ]).start(); + ]).start(() => { + // 动画完成后滚动到底部 + setTimeout(() => { + scrollToBottom(false); + }, 50); + }); } - }, [isHello, fadeAnim, fadeAnimChat]); + }, [isHello, fadeAnim, fadeAnimChat, scrollToBottom]); + + // 页面进入时的处理 - 新增 + useEffect(() => { + if (!isHello) { + // 页面完全加载后滚动到底部 + const timer = setTimeout(() => { + scrollToBottom(false); + }, 300); + return () => clearTimeout(timer); + } + }, [isHello, scrollToBottom]); + + // 新增:页面获得焦点时处理 + useEffect(() => { + // 页面进入时确保键盘关闭并滚动到底部 + const timer = setTimeout(() => { + if (!isHello) { + // 让所有输入框失去焦点 + try { + if (TextInput.State?.currentlyFocusedInput) { + const input = TextInput.State.currentlyFocusedInput(); + if (input) input.blur(); + } + } catch (error) { + console.log('失去焦点失败:', error); + } + + // 滚动到底部 + scrollToBottom(false); + } + }, 200); + + return () => clearTimeout(timer); + }, [isHello, scrollToBottom]); return ( @@ -100,8 +182,17 @@ export default function AskScreen() { { - router.push('/memo-list') + // 确保关闭键盘 + try { + if (TextInput.State?.currentlyFocusedInput) { + const input = TextInput.State.currentlyFocusedInput(); + if (input) input.blur(); + } + } catch (error) { + console.log('失去焦点失败:', error); + } Keyboard.dismiss(); + router.push('/memo-list'); }} > @@ -113,7 +204,6 @@ export default function AskScreen() { @@ -138,13 +228,27 @@ export default function AskScreen() { styles.absoluteView, { opacity: fadeAnimChat, - // 使用 pointerEvents 控制交互 pointerEvents: isHello ? 'none' : 'auto', zIndex: 0 } ]} > - + scrollToBottom(true)} + > + + @@ -210,16 +314,21 @@ const styles = StyleSheet.create({ contentContainer: { flex: 1, justifyContent: 'center', - paddingBottom: 20, }, absoluteView: { - position: 'absolute', // 保持绝对定位 + position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'white', }, + chatContainer: { + flex: 1, + }, + chatContentContainer: { + paddingBottom: 20, + }, inputContainer: { padding: 16, paddingBottom: 24,