修改动画
This commit is contained in:
@@ -24,7 +24,7 @@ static const NSTimeInterval kTimestampInterval = 5 * 60; // 5 分钟
|
|||||||
|
|
||||||
@interface KBChatTableView () <UITableViewDataSource, UITableViewDelegate, KBChatAssistantMessageCellDelegate, AVAudioPlayerDelegate>
|
@interface KBChatTableView () <UITableViewDataSource, UITableViewDelegate, KBChatAssistantMessageCellDelegate, AVAudioPlayerDelegate>
|
||||||
|
|
||||||
@property (nonatomic, strong) UITableView *tableView;
|
@property (nonatomic, strong) BaseTableView *tableView;
|
||||||
@property (nonatomic, strong) NSMutableArray<KBAiChatMessage *> *messages;
|
@property (nonatomic, strong) NSMutableArray<KBAiChatMessage *> *messages;
|
||||||
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
|
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
|
||||||
@property (nonatomic, strong) NSIndexPath *playingCellIndexPath;
|
@property (nonatomic, strong) NSIndexPath *playingCellIndexPath;
|
||||||
@@ -58,8 +58,9 @@ static const NSTimeInterval kTimestampInterval = 5 * 60; // 5 分钟
|
|||||||
self.hasMoreData = YES;
|
self.hasMoreData = YES;
|
||||||
|
|
||||||
// 创建 TableView
|
// 创建 TableView
|
||||||
self.tableView = [[UITableView alloc] initWithFrame:self.bounds
|
self.tableView = [[BaseTableView alloc] initWithFrame:self.bounds
|
||||||
style:UITableViewStylePlain];
|
style:UITableViewStylePlain];
|
||||||
|
self.tableView.useEmptyDataSet = false;
|
||||||
self.tableView.dataSource = self;
|
self.tableView.dataSource = self;
|
||||||
self.tableView.delegate = self;
|
self.tableView.delegate = self;
|
||||||
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||||
|
|||||||
@@ -7,12 +7,14 @@
|
|||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import "KBPersonaModel.h"
|
#import "KBPersonaModel.h"
|
||||||
|
#import "KBChatTableView.h"
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
/// 人设聊天 Cell
|
/// 人设聊天 Cell
|
||||||
@interface KBPersonaChatCell : UICollectionViewCell
|
@interface KBPersonaChatCell : UICollectionViewCell
|
||||||
|
/// 聊天列表
|
||||||
|
@property (nonatomic, strong) KBChatTableView *chatView;
|
||||||
/// 人设数据
|
/// 人设数据
|
||||||
@property (nonatomic, strong) KBPersonaModel *persona;
|
@property (nonatomic, strong) KBPersonaModel *persona;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "KBPersonaChatCell.h"
|
#import "KBPersonaChatCell.h"
|
||||||
#import "KBChatTableView.h"
|
|
||||||
#import "KBAiChatMessage.h"
|
#import "KBAiChatMessage.h"
|
||||||
#import "KBChatHistoryPageModel.h"
|
#import "KBChatHistoryPageModel.h"
|
||||||
#import "AiVM.h"
|
#import "AiVM.h"
|
||||||
@@ -30,8 +29,7 @@
|
|||||||
/// 开场白
|
/// 开场白
|
||||||
@property (nonatomic, strong) UILabel *openingLabel;
|
@property (nonatomic, strong) UILabel *openingLabel;
|
||||||
|
|
||||||
/// 聊天列表
|
|
||||||
@property (nonatomic, strong) KBChatTableView *chatView;
|
|
||||||
|
|
||||||
/// 聊天消息
|
/// 聊天消息
|
||||||
@property (nonatomic, strong) NSMutableArray<KBAiChatMessage *> *messages;
|
@property (nonatomic, strong) NSMutableArray<KBAiChatMessage *> *messages;
|
||||||
|
|||||||
@@ -86,11 +86,11 @@
|
|||||||
// 输入区域容器
|
// 输入区域容器
|
||||||
[self addSubview:self.inputContainer];
|
[self addSubview:self.inputContainer];
|
||||||
[self.inputContainer mas_makeConstraints:^(MASConstraintMaker *make) {
|
[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.left.equalTo(self).offset(20);
|
||||||
make.right.equalTo(self).offset(-20);
|
make.right.equalTo(self).offset(-20);
|
||||||
make.height.mas_equalTo(50);
|
make.height.mas_equalTo(50);
|
||||||
make.bottom.lessThanOrEqualTo(self).offset(-16);
|
make.bottom.lessThanOrEqualTo(self).offset(-10);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
UILongPressGestureRecognizer *longPress =
|
UILongPressGestureRecognizer *longPress =
|
||||||
|
|||||||
@@ -110,8 +110,8 @@
|
|||||||
#pragma mark - 1:控件初始化
|
#pragma mark - 1:控件初始化
|
||||||
|
|
||||||
- (void)setupUI {
|
- (void)setupUI {
|
||||||
self.voiceInputBarHeight = 150.0;
|
self.voiceInputBarHeight = 120.0;
|
||||||
self.baseInputBarBottomSpacing = 20.0;
|
self.baseInputBarBottomSpacing = KB_TABBAR_HEIGHT;
|
||||||
[self.view addSubview:self.collectionView];
|
[self.view addSubview:self.collectionView];
|
||||||
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.edges.equalTo(self.view);
|
make.edges.equalTo(self.view);
|
||||||
@@ -350,12 +350,30 @@
|
|||||||
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
|
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
|
||||||
UIViewAnimationOptions options = ([userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16);
|
UIViewAnimationOptions options = ([userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16);
|
||||||
|
|
||||||
|
// 将键盘的 frame 转换到当前 view 的坐标系
|
||||||
CGRect convertedFrame = [self.view convertRect:endFrame fromView:nil];
|
CGRect convertedFrame = [self.view convertRect:endFrame fromView:nil];
|
||||||
CGFloat keyboardHeight = MAX(0.0, CGRectGetMaxY(self.view.bounds) - CGRectGetMinY(convertedFrame));
|
CGFloat keyboardHeight = MAX(0.0, CGRectGetMaxY(self.view.bounds) - CGRectGetMinY(convertedFrame));
|
||||||
self.currentKeyboardHeight = keyboardHeight;
|
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];
|
[self.voiceInputBarBottomConstraint setOffset:-bottomSpacing];
|
||||||
|
|
||||||
|
// 问题2修复:键盘弹起时更新 ChatView 的 bottomInset
|
||||||
[self updateChatViewBottomInset];
|
[self updateChatViewBottomInset];
|
||||||
|
|
||||||
[UIView animateWithDuration:duration
|
[UIView animateWithDuration:duration
|
||||||
@@ -433,13 +451,49 @@
|
|||||||
#pragma mark - Private
|
#pragma mark - Private
|
||||||
|
|
||||||
- (void)updateChatViewBottomInset {
|
- (void)updateChatViewBottomInset {
|
||||||
CGFloat bottomSpacing = (self.currentKeyboardHeight > 0.0) ? (self.currentKeyboardHeight + 8.0) : self.baseInputBarBottomSpacing;
|
// 问题2修复:键盘弹起时,增加 bottomInset 让最后一条消息显示在 VoiceInputBar 上方
|
||||||
|
CGFloat bottomInset;
|
||||||
|
|
||||||
// 关键修复:减少 bottomInset,因为 chatView 已经通过约束避开了底部的 avatar 区域
|
if (self.currentKeyboardHeight > 0.0) {
|
||||||
// 只需要留出一点空间(比如20)让最后一条消息不紧贴 chatView 底部即可
|
// 键盘弹起时:
|
||||||
CGFloat bottomInset = 20; // 简单的缓冲空间
|
// avatarImageView 距离屏幕底部的距离 = KB_TABBAR_HEIGHT + 50 + 20
|
||||||
|
// chatView 物理底部到屏幕底部 = KB_TABBAR_HEIGHT + 50 + 20 + 54(头像) + 10(间距) ≈ 153
|
||||||
|
// 但是 VoiceInputBar 和键盘会遮挡 chatView
|
||||||
|
// 需要的 bottomInset = 键盘高度 + VoiceInputBar 高度 - chatView 已经避开的底部区域
|
||||||
|
|
||||||
NSLog(@"[KBAIHomeVC] 更新 ChatView bottomInset: %.2f", bottomInset);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
for (NSIndexPath *indexPath in self.collectionView.indexPathsForVisibleItems) {
|
||||||
KBPersonaChatCell *cell = (KBPersonaChatCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
|
KBPersonaChatCell *cell = (KBPersonaChatCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
|
||||||
|
|||||||
Reference in New Issue
Block a user