Fix KBAICommentInputView弹出位置
This commit is contained in:
@@ -167,6 +167,8 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
[super viewDidAppear:animated];
|
||||
[self kb_syncTextInputStateIfNeeded];
|
||||
[self kb_logInputLayoutWithTag:@"viewDidAppear"];
|
||||
KBPersonaChatCell *cell = [self currentPersonaCell];
|
||||
if (cell) {
|
||||
[cell onBecameCurrentPersonaCell];
|
||||
@@ -175,6 +177,17 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
// 离开页面时结束编辑并重置底部输入状态,避免返回时出现 hidden/firstResponder 错位
|
||||
[self.view endEditing:YES];
|
||||
self.voiceInputKeyboardActive = NO;
|
||||
self.currentKeyboardHeight = 0.0;
|
||||
self.isTextInputMode = NO;
|
||||
self.commentInputView.hidden = YES;
|
||||
[self.commentInputBottomConstraint setOffset:100];
|
||||
self.voiceInputBar.hidden = NO;
|
||||
[self.voiceInputBarBottomConstraint setOffset:-self.baseInputBarBottomSpacing];
|
||||
[self.view layoutIfNeeded];
|
||||
[self kb_logInputLayoutWithTag:@"viewWillDisappear"];
|
||||
for (NSIndexPath *indexPath in self.collectionView.indexPathsForVisibleItems) {
|
||||
KBPersonaChatCell *cell = (KBPersonaChatCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
|
||||
if (cell) {
|
||||
@@ -263,16 +276,26 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
self.isTextInputMode = YES;
|
||||
self.voiceInputBar.hidden = YES;
|
||||
self.commentInputView.hidden = NO;
|
||||
[self kb_logInputLayoutWithTag:@"showTextInputView-beforeAdjust"];
|
||||
// 键盘未弹起时先停在底部栏位置,随后由键盘通知动画抬起到键盘上方
|
||||
// 键盘已弹起时(如返回页面)直接使用当前键盘高度对齐
|
||||
CGFloat targetOffset = self.currentKeyboardHeight > 0.0 ? -self.currentKeyboardHeight : -self.baseInputBarBottomSpacing;
|
||||
[self.commentInputBottomConstraint setOffset:targetOffset];
|
||||
[self.view layoutIfNeeded];
|
||||
[self kb_logInputLayoutWithTag:@"showTextInputView-afterAdjust"];
|
||||
[self.commentInputView showKeyboard];
|
||||
}
|
||||
|
||||
/// 隐藏文本输入视图
|
||||
- (void)hideTextInputView {
|
||||
[self kb_logInputLayoutWithTag:@"hideTextInputView-before"];
|
||||
self.isTextInputMode = NO;
|
||||
[self.view endEditing:YES];
|
||||
[self.commentInputView clearText];
|
||||
self.commentInputView.hidden = YES;
|
||||
[self.commentInputBottomConstraint setOffset:100];
|
||||
self.voiceInputBar.hidden = NO;
|
||||
[self kb_logInputLayoutWithTag:@"hideTextInputView-after"];
|
||||
}
|
||||
|
||||
#pragma mark - 2:数据加载
|
||||
@@ -570,12 +593,32 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
|
||||
- (void)setupKeyboardNotifications {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleKeyboardWillChangeFrame:)
|
||||
selector:@selector(handleKeyboardNotification:)
|
||||
name:UIKeyboardWillChangeFrameNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleKeyboardNotification:)
|
||||
name:UIKeyboardDidChangeFrameNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleKeyboardNotification:)
|
||||
name:UIKeyboardWillShowNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleKeyboardNotification:)
|
||||
name:UIKeyboardDidShowNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleKeyboardNotification:)
|
||||
name:UIKeyboardWillHideNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleKeyboardNotification:)
|
||||
name:UIKeyboardDidHideNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)handleKeyboardWillChangeFrame:(NSNotification *)notification {
|
||||
- (void)handleKeyboardNotification:(NSNotification *)notification {
|
||||
NSDictionary *userInfo = notification.userInfo;
|
||||
CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
|
||||
@@ -583,17 +626,42 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
|
||||
CGRect convertedFrame = [self.view convertRect:endFrame fromView:nil];
|
||||
CGFloat keyboardHeight = MAX(0.0, CGRectGetMaxY(self.view.bounds) - CGRectGetMinY(convertedFrame));
|
||||
BOOL shouldHandle = YES;
|
||||
BOOL fromAllowedInput = [self kb_isKeyboardFromVoiceInputBar];
|
||||
|
||||
if (keyboardHeight > 0.0) {
|
||||
if (![self kb_isKeyboardFromVoiceInputBar]) {
|
||||
return;
|
||||
// 文本输入模式优先跟随键盘,避免返回页面后 firstResponder 瞬时不稳定导致被误过滤
|
||||
if (!self.isTextInputMode && !fromAllowedInput) {
|
||||
shouldHandle = NO;
|
||||
}
|
||||
self.voiceInputKeyboardActive = YES;
|
||||
} else {
|
||||
if (!self.voiceInputKeyboardActive) {
|
||||
return;
|
||||
if (!self.voiceInputKeyboardActive && !self.isTextInputMode) {
|
||||
shouldHandle = NO;
|
||||
}
|
||||
self.voiceInputKeyboardActive = NO;
|
||||
}
|
||||
|
||||
[self kb_logKeyboardNotification:notification
|
||||
keyboardHeight:keyboardHeight
|
||||
convertedFrame:convertedFrame
|
||||
fromAllowedInput:fromAllowedInput
|
||||
shouldHandle:shouldHandle];
|
||||
if (!shouldHandle) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIView *firstResponder = [self kb_findFirstResponderInView:self.view];
|
||||
BOOL firstInComment = firstResponder ? [firstResponder isDescendantOfView:self.commentInputView] : NO;
|
||||
if (keyboardHeight > 0.0 && firstInComment && !self.isTextInputMode) {
|
||||
// 防止出现「firstResponder 在 commentInput,但 textMode 仍为 NO」导致定位到底部
|
||||
self.isTextInputMode = YES;
|
||||
self.voiceInputBar.hidden = YES;
|
||||
self.commentInputView.hidden = NO;
|
||||
[self kb_logInputLayoutWithTag:@"keyboardSync-forceTextMode"];
|
||||
}
|
||||
|
||||
if (keyboardHeight <= 0.0) {
|
||||
// 键盘隐藏时,如果是文本输入模式,隐藏文本输入框并显示 VoiceInputBar
|
||||
if (self.isTextInputMode) {
|
||||
[self hideTextInputView];
|
||||
@@ -625,7 +693,9 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
animations:^{
|
||||
[self.view layoutIfNeeded];
|
||||
}
|
||||
completion:nil];
|
||||
completion:^(BOOL finished) {
|
||||
[self kb_logInputLayoutWithTag:@"handleKeyboardNotification-animComplete"];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - 7:键盘收起
|
||||
@@ -843,6 +913,7 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
}
|
||||
|
||||
- (void)chatLimitPopViewDidTapRecharge:(KBChatLimitPopView *)view {
|
||||
NSLog(@"[KBAIHomeVC][Pay] chatLimitPopViewDidTapRecharge");
|
||||
[self.chatLimitPopView dismiss];
|
||||
if (![KBUserSessionManager shared].isLoggedIn) {
|
||||
[[KBUserSessionManager shared] goLoginVC];
|
||||
@@ -961,6 +1032,74 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
[self showPersonaSidebar];
|
||||
}
|
||||
|
||||
#pragma mark - Debug Log
|
||||
|
||||
- (void)kb_syncTextInputStateIfNeeded {
|
||||
UIView *firstResponder = [self kb_findFirstResponderInView:self.view];
|
||||
BOOL firstInComment = firstResponder ? [firstResponder isDescendantOfView:self.commentInputView] : NO;
|
||||
if (!firstInComment) {
|
||||
return;
|
||||
}
|
||||
self.isTextInputMode = YES;
|
||||
self.voiceInputBar.hidden = YES;
|
||||
self.commentInputView.hidden = NO;
|
||||
if (self.currentKeyboardHeight > 0.0) {
|
||||
[self.commentInputBottomConstraint setOffset:-self.currentKeyboardHeight];
|
||||
[self.voiceInputBarBottomConstraint setOffset:-MAX(self.currentKeyboardHeight - 5.0, self.baseInputBarBottomSpacing)];
|
||||
} else {
|
||||
[self.commentInputBottomConstraint setOffset:-self.baseInputBarBottomSpacing];
|
||||
}
|
||||
[self.view layoutIfNeeded];
|
||||
[self kb_logInputLayoutWithTag:@"kb_syncTextInputStateIfNeeded"];
|
||||
}
|
||||
|
||||
- (void)kb_logInputLayoutWithTag:(NSString *)tag {
|
||||
[self.view layoutIfNeeded];
|
||||
UIView *firstResponder = [self kb_findFirstResponderInView:self.view];
|
||||
NSString *firstResponderInfo = firstResponder ? NSStringFromClass(firstResponder.class) : @"nil";
|
||||
NSLog(@"[KBAIHomeVC][Layout][%@] textMode=%d voiceHidden=%d commentHidden=%d currentKeyboardHeight=%.2f viewH=%.2f safeBottom=%.2f commentFrame=%@ voiceFrame=%@ firstResponder=%@",
|
||||
tag ?: @"-",
|
||||
self.isTextInputMode,
|
||||
self.voiceInputBar.hidden,
|
||||
self.commentInputView.hidden,
|
||||
self.currentKeyboardHeight,
|
||||
CGRectGetHeight(self.view.bounds),
|
||||
self.view.safeAreaInsets.bottom,
|
||||
NSStringFromCGRect(self.commentInputView.frame),
|
||||
NSStringFromCGRect(self.voiceInputBar.frame),
|
||||
firstResponderInfo);
|
||||
}
|
||||
|
||||
- (void)kb_logKeyboardNotification:(NSNotification *)notification
|
||||
keyboardHeight:(CGFloat)keyboardHeight
|
||||
convertedFrame:(CGRect)convertedFrame
|
||||
fromAllowedInput:(BOOL)fromAllowedInput
|
||||
shouldHandle:(BOOL)shouldHandle {
|
||||
NSDictionary *userInfo = notification.userInfo;
|
||||
CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
|
||||
NSInteger curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
|
||||
UIView *firstResponder = [self kb_findFirstResponderInView:self.view];
|
||||
NSString *firstResponderInfo = firstResponder ? NSStringFromClass(firstResponder.class) : @"nil";
|
||||
BOOL firstInComment = firstResponder ? [firstResponder isDescendantOfView:self.commentInputView] : NO;
|
||||
BOOL firstInVoice = firstResponder ? [firstResponder isDescendantOfView:self.voiceInputBar] : NO;
|
||||
NSLog(@"[KBAIHomeVC][Keyboard][%@] shouldHandle=%d textMode=%d voiceActive=%d fromAllowed=%d firstInComment=%d firstInVoice=%d firstResponder=%@ endFrame=%@ converted=%@ keyboardHeight=%.2f duration=%.2f curve=%ld viewWindow=%@",
|
||||
notification.name,
|
||||
shouldHandle,
|
||||
self.isTextInputMode,
|
||||
self.voiceInputKeyboardActive,
|
||||
fromAllowedInput,
|
||||
firstInComment,
|
||||
firstInVoice,
|
||||
firstResponderInfo,
|
||||
NSStringFromCGRect(endFrame),
|
||||
NSStringFromCGRect(convertedFrame),
|
||||
keyboardHeight,
|
||||
duration,
|
||||
(long)curve,
|
||||
self.view.window ? @"YES" : @"NO");
|
||||
}
|
||||
|
||||
- (void)showPersonaSidebar {
|
||||
if (!self.sidebarView) {
|
||||
CGFloat width = KB_SCREEN_WIDTH * 0.7;
|
||||
|
||||
Reference in New Issue
Block a user