diff --git a/keyBoard/Class/AiTalk/V/KBChatTableView.m b/keyBoard/Class/AiTalk/V/KBChatTableView.m index ef22a69..1d6671e 100644 --- a/keyBoard/Class/AiTalk/V/KBChatTableView.m +++ b/keyBoard/Class/AiTalk/V/KBChatTableView.m @@ -24,7 +24,7 @@ static const NSTimeInterval kTimestampInterval = 5 * 60; // 5 分钟 @interface KBChatTableView () -@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, strong) BaseTableView *tableView; @property (nonatomic, strong) NSMutableArray *messages; @property (nonatomic, strong) AVAudioPlayer *audioPlayer; @property (nonatomic, strong) NSIndexPath *playingCellIndexPath; @@ -58,8 +58,9 @@ static const NSTimeInterval kTimestampInterval = 5 * 60; // 5 分钟 self.hasMoreData = YES; // 创建 TableView - self.tableView = [[UITableView alloc] initWithFrame:self.bounds + self.tableView = [[BaseTableView alloc] initWithFrame:self.bounds style:UITableViewStylePlain]; + self.tableView.useEmptyDataSet = false; self.tableView.dataSource = self; self.tableView.delegate = self; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; diff --git a/keyBoard/Class/AiTalk/V/KBPersonaChatCell.h b/keyBoard/Class/AiTalk/V/KBPersonaChatCell.h index 3016ad0..fa9956a 100644 --- a/keyBoard/Class/AiTalk/V/KBPersonaChatCell.h +++ b/keyBoard/Class/AiTalk/V/KBPersonaChatCell.h @@ -7,12 +7,14 @@ #import #import "KBPersonaModel.h" +#import "KBChatTableView.h" NS_ASSUME_NONNULL_BEGIN /// 人设聊天 Cell @interface KBPersonaChatCell : UICollectionViewCell - +/// 聊天列表 +@property (nonatomic, strong) KBChatTableView *chatView; /// 人设数据 @property (nonatomic, strong) KBPersonaModel *persona; diff --git a/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m b/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m index 6bc58a4..7d8ac0b 100644 --- a/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m +++ b/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m @@ -6,7 +6,6 @@ // #import "KBPersonaChatCell.h" -#import "KBChatTableView.h" #import "KBAiChatMessage.h" #import "KBChatHistoryPageModel.h" #import "AiVM.h" @@ -30,8 +29,7 @@ /// 开场白 @property (nonatomic, strong) UILabel *openingLabel; -/// 聊天列表 -@property (nonatomic, strong) KBChatTableView *chatView; + /// 聊天消息 @property (nonatomic, strong) NSMutableArray *messages; diff --git a/keyBoard/Class/AiTalk/V/KBVoiceInputBar.m b/keyBoard/Class/AiTalk/V/KBVoiceInputBar.m index 3b96d3e..c919509 100644 --- a/keyBoard/Class/AiTalk/V/KBVoiceInputBar.m +++ b/keyBoard/Class/AiTalk/V/KBVoiceInputBar.m @@ -86,11 +86,11 @@ // 输入区域容器 [self addSubview:self.inputContainer]; [self.inputContainer mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(self.statusLabel.mas_bottom).offset(12); +// make.top.equalTo(self.statusLabel.mas_bottom).offset(12); make.left.equalTo(self).offset(20); make.right.equalTo(self).offset(-20); make.height.mas_equalTo(50); - make.bottom.lessThanOrEqualTo(self).offset(-16); + make.bottom.lessThanOrEqualTo(self).offset(-10); }]; UILongPressGestureRecognizer *longPress = diff --git a/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m b/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m index 659604d..8932c79 100644 --- a/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m +++ b/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m @@ -110,8 +110,8 @@ #pragma mark - 1:控件初始化 - (void)setupUI { - self.voiceInputBarHeight = 150.0; - self.baseInputBarBottomSpacing = 20.0; + self.voiceInputBarHeight = 120.0; + self.baseInputBarBottomSpacing = KB_TABBAR_HEIGHT; [self.view addSubview:self.collectionView]; [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.view); @@ -350,12 +350,30 @@ NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; UIViewAnimationOptions options = ([userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16); + // 将键盘的 frame 转换到当前 view 的坐标系 CGRect convertedFrame = [self.view convertRect:endFrame fromView:nil]; CGFloat keyboardHeight = MAX(0.0, CGRectGetMaxY(self.view.bounds) - CGRectGetMinY(convertedFrame)); self.currentKeyboardHeight = keyboardHeight; - CGFloat bottomSpacing = (keyboardHeight > 0.0) ? (keyboardHeight + 8.0) : self.baseInputBarBottomSpacing; + NSLog(@"[KBAIHomeVC] 键盘高度: %.2f, 屏幕高度: %.2f, 键盘 Y: %.2f", + keyboardHeight, CGRectGetMaxY(self.view.bounds), CGRectGetMinY(convertedFrame)); + + // 问题1修复:计算 VoiceInputBar 应该距离 view.bottom 多远 + CGFloat bottomSpacing; + if (keyboardHeight > 0.0) { + // 键盘弹起时:让 VoiceInputBar 紧贴键盘上方(距离 5px) + // bottomSpacing = 键盘高度 - 5px(因为是负的 offset) + bottomSpacing = keyboardHeight - 5.0; + } else { + // 键盘隐藏时:恢复到原始位置 + bottomSpacing = self.baseInputBarBottomSpacing; + } + + NSLog(@"[KBAIHomeVC] VoiceInputBar bottomSpacing: %.2f", bottomSpacing); + [self.voiceInputBarBottomConstraint setOffset:-bottomSpacing]; + + // 问题2修复:键盘弹起时更新 ChatView 的 bottomInset [self updateChatViewBottomInset]; [UIView animateWithDuration:duration @@ -433,13 +451,49 @@ #pragma mark - Private - (void)updateChatViewBottomInset { - CGFloat bottomSpacing = (self.currentKeyboardHeight > 0.0) ? (self.currentKeyboardHeight + 8.0) : self.baseInputBarBottomSpacing; + // 问题2修复:键盘弹起时,增加 bottomInset 让最后一条消息显示在 VoiceInputBar 上方 + CGFloat bottomInset; - // 关键修复:减少 bottomInset,因为 chatView 已经通过约束避开了底部的 avatar 区域 - // 只需要留出一点空间(比如20)让最后一条消息不紧贴 chatView 底部即可 - CGFloat bottomInset = 20; // 简单的缓冲空间 + if (self.currentKeyboardHeight > 0.0) { + // 键盘弹起时: + // avatarImageView 距离屏幕底部的距离 = KB_TABBAR_HEIGHT + 50 + 20 + // chatView 物理底部到屏幕底部 = KB_TABBAR_HEIGHT + 50 + 20 + 54(头像) + 10(间距) ≈ 153 + // 但是 VoiceInputBar 和键盘会遮挡 chatView + // 需要的 bottomInset = 键盘高度 + VoiceInputBar 高度 - chatView 已经避开的底部区域 + + CGFloat avatarBottomSpace = KB_TABBAR_HEIGHT + 50 + 20; // avatarImageView 距离底部的距离 + CGFloat chatViewPhysicalBottomSpace = avatarBottomSpace + 54 + 10; // chatView 物理底部距离屏幕底部 + + // 需要抬高的额外距离 = (键盘 + InputBar) - chatView 已经避开的空间 + bottomInset = (self.currentKeyboardHeight + self.voiceInputBarHeight) - chatViewPhysicalBottomSpace; + + // 确保不会是负数 + bottomInset = MAX(bottomInset, 20); + + NSLog(@"[KBAIHomeVC] 键盘弹起 - bottomInset: %.2f (键盘: %.2f + InputBar: %.2f - 已避开: %.2f)", + bottomInset, self.currentKeyboardHeight, self.voiceInputBarHeight, chatViewPhysicalBottomSpace); + } else { + // 键盘隐藏时:恢复原来的 bottomInset + bottomInset = 20; // 简单的缓冲空间 + NSLog(@"[KBAIHomeVC] 键盘隐藏 - bottomInset: %.2f", bottomInset); + } - NSLog(@"[KBAIHomeVC] 更新 ChatView bottomInset: %.2f", bottomInset); + for (NSIndexPath *indexPath in self.collectionView.indexPathsForVisibleItems) { + KBPersonaChatCell *cell = (KBPersonaChatCell *)[self.collectionView cellForItemAtIndexPath:indexPath]; + if (cell) { + [cell updateChatViewBottomInset:bottomInset]; + + // 键盘弹起时,自动滚动到最后一条消息 + if (self.currentKeyboardHeight > 0.0) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [cell.chatView scrollToBottom]; // 修复:使用无参数的方法 + }); + } + } + } + + + NSLog(@"[KBAIHomeVC] 更新 ChatView bottomInset: %.2f (键盘高度: %.2f)", bottomInset, self.currentKeyboardHeight); for (NSIndexPath *indexPath in self.collectionView.indexPathsForVisibleItems) { KBPersonaChatCell *cell = (KBPersonaChatCell *)[self.collectionView cellForItemAtIndexPath:indexPath];