Fix KBAICommentInputView弹出位置

This commit is contained in:
2026-02-25 17:13:25 +08:00
parent 851c0d9531
commit 92ca5c6180
3 changed files with 156 additions and 8 deletions

Submodule _spm/checkouts/swift-collections added at 7b847a3b70

View File

@@ -92,7 +92,9 @@
} }
- (void)showKeyboard { - (void)showKeyboard {
[self.textField becomeFirstResponder]; BOOL before = self.textField.isFirstResponder;
BOOL become = [self.textField becomeFirstResponder];
NSLog(@"[KBAICommentInputView] showKeyboard before=%d become=%d after=%d", before, become, self.textField.isFirstResponder);
} }
#pragma mark - Actions #pragma mark - Actions
@@ -129,11 +131,17 @@
} }
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(@"[KBAICommentInputView] textFieldShouldBeginEditing");
[self updatePlaceholderVisibility]; [self updatePlaceholderVisibility];
return YES; return YES;
} }
- (void)textFieldDidBeginEditing:(UITextField *)textField {
NSLog(@"[KBAICommentInputView] textFieldDidBeginEditing firstResponder=%d", textField.isFirstResponder);
}
- (void)textFieldDidEndEditing:(UITextField *)textField { - (void)textFieldDidEndEditing:(UITextField *)textField {
NSLog(@"[KBAICommentInputView] textFieldDidEndEditing");
[self updatePlaceholderVisibility]; [self updatePlaceholderVisibility];
} }

View File

@@ -167,6 +167,8 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
- (void)viewDidAppear:(BOOL)animated { - (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated]; [super viewDidAppear:animated];
[self kb_syncTextInputStateIfNeeded];
[self kb_logInputLayoutWithTag:@"viewDidAppear"];
KBPersonaChatCell *cell = [self currentPersonaCell]; KBPersonaChatCell *cell = [self currentPersonaCell];
if (cell) { if (cell) {
[cell onBecameCurrentPersonaCell]; [cell onBecameCurrentPersonaCell];
@@ -175,6 +177,17 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
- (void)viewWillDisappear:(BOOL)animated { - (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear: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) { for (NSIndexPath *indexPath in self.collectionView.indexPathsForVisibleItems) {
KBPersonaChatCell *cell = (KBPersonaChatCell *)[self.collectionView cellForItemAtIndexPath:indexPath]; KBPersonaChatCell *cell = (KBPersonaChatCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
if (cell) { if (cell) {
@@ -263,16 +276,26 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
self.isTextInputMode = YES; self.isTextInputMode = YES;
self.voiceInputBar.hidden = YES; self.voiceInputBar.hidden = YES;
self.commentInputView.hidden = NO; 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]; [self.commentInputView showKeyboard];
} }
/// ///
- (void)hideTextInputView { - (void)hideTextInputView {
[self kb_logInputLayoutWithTag:@"hideTextInputView-before"];
self.isTextInputMode = NO; self.isTextInputMode = NO;
[self.view endEditing:YES]; [self.view endEditing:YES];
[self.commentInputView clearText]; [self.commentInputView clearText];
self.commentInputView.hidden = YES; self.commentInputView.hidden = YES;
[self.commentInputBottomConstraint setOffset:100];
self.voiceInputBar.hidden = NO; self.voiceInputBar.hidden = NO;
[self kb_logInputLayoutWithTag:@"hideTextInputView-after"];
} }
#pragma mark - 2 #pragma mark - 2
@@ -570,12 +593,32 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
- (void)setupKeyboardNotifications { - (void)setupKeyboardNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleKeyboardWillChangeFrame:) selector:@selector(handleKeyboardNotification:)
name:UIKeyboardWillChangeFrameNotification name:UIKeyboardWillChangeFrameNotification
object:nil]; 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; NSDictionary *userInfo = notification.userInfo;
CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
@@ -583,17 +626,42 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
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));
BOOL shouldHandle = YES;
BOOL fromAllowedInput = [self kb_isKeyboardFromVoiceInputBar];
if (keyboardHeight > 0.0) { if (keyboardHeight > 0.0) {
if (![self kb_isKeyboardFromVoiceInputBar]) { // firstResponder
return; if (!self.isTextInputMode && !fromAllowedInput) {
shouldHandle = NO;
} }
self.voiceInputKeyboardActive = YES; self.voiceInputKeyboardActive = YES;
} else { } else {
if (!self.voiceInputKeyboardActive) { if (!self.voiceInputKeyboardActive && !self.isTextInputMode) {
return; shouldHandle = NO;
} }
self.voiceInputKeyboardActive = 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 // VoiceInputBar
if (self.isTextInputMode) { if (self.isTextInputMode) {
[self hideTextInputView]; [self hideTextInputView];
@@ -625,7 +693,9 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
animations:^{ animations:^{
[self.view layoutIfNeeded]; [self.view layoutIfNeeded];
} }
completion:nil]; completion:^(BOOL finished) {
[self kb_logInputLayoutWithTag:@"handleKeyboardNotification-animComplete"];
}];
} }
#pragma mark - 7 #pragma mark - 7
@@ -843,6 +913,7 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
} }
- (void)chatLimitPopViewDidTapRecharge:(KBChatLimitPopView *)view { - (void)chatLimitPopViewDidTapRecharge:(KBChatLimitPopView *)view {
NSLog(@"[KBAIHomeVC][Pay] chatLimitPopViewDidTapRecharge");
[self.chatLimitPopView dismiss]; [self.chatLimitPopView dismiss];
if (![KBUserSessionManager shared].isLoggedIn) { if (![KBUserSessionManager shared].isLoggedIn) {
[[KBUserSessionManager shared] goLoginVC]; [[KBUserSessionManager shared] goLoginVC];
@@ -961,6 +1032,74 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
[self showPersonaSidebar]; [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 { - (void)showPersonaSidebar {
if (!self.sidebarView) { if (!self.sidebarView) {
CGFloat width = KB_SCREEN_WIDTH * 0.7; CGFloat width = KB_SCREEN_WIDTH * 0.7;