按下听写(语音到文本)按钮时不会触发UIKeyboardWillChangeFrameNotification

时间:2018-10-24 14:21:37

标签: ios objective-c keyboard speech-to-text iphone-x

我正在开发具有聊天功能的应用程序,因此我的要求是在键盘顶部显示文本字段。由于需要不使用滚动视图,因此我在UIView上获取了一个文本字段,并且我正在使用键盘通知(UIKeyboardWillChangeFrameNotification和UIKeyboardWillHideNotification)来相应地滚动文本字段。

当“预测文本”打开并且用户按下听写按钮时,我面临iPhone x设备的问题,因为听写不需要“预测文本”,因此文本字段和键盘之间会有间隙。

我正在尝试通过UIKeyboardWillChangeFrameNotification检测键盘高度,但在按下听写按钮时不会触发。

在下面添加我的示例代码。

@interface ViewController ()
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomConstraints;
@property (weak, nonatomic) IBOutlet UITextField *chatTextField;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardFrameChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keywindowResign:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:YES];
}

- (void)keyboardFrameChange:(NSNotification *)notification
{
    NSDictionary * userInfo = [notification userInfo];
    CGRect keyboardRect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    double duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    // Anchor the bottom of the message view to the top of the keyboard.
    [UIView animateWithDuration:duration animations:^{
        self.bottomConstraints.constant = 0 - CGRectGetHeight(keyboardRect) + self.view.safeAreaInsets.bottom;
        [self.view layoutIfNeeded];
    }];
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    NSDictionary * userInfo = [notification userInfo];
    double duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    // Anchor the bottom of the message view to the bottom of the screen.
    [UIView animateWithDuration:duration animations:^{
        self.bottomConstraints.constant = 0;
        [self.view layoutIfNeeded];
    }];
}

- (void)keywindowResign:(NSNotification *)notification
{
    NSLog(@"%s","Key window resign");
}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:true];
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

请查看屏幕截图以了解更多信息。

enter image description here enter image description here

1 个答案:

答案 0 :(得分:0)

我刚刚创建了一个快速测试项目,当我按下听写按钮时,通知似乎结束了。我只能推测出您可能会遇到什么问题,因为您根本不包含任何代码,但是有两个猜测:

  • 通知已通过,但调整键盘高度的计算不正确(也许未考虑safeAreaInsets.bottom?)
  • 您将在某个时候改变键盘命令的通知通过之前,将自己退出为键盘通知的观察者。

这是对我有用的示例代码:

#import "ViewController.h"

@interface ViewController ()
@property (strong, nullable) IBOutlet UITextField *tf;
@property (strong, nullable) IBOutlet UIView *redView;
@property (strong, nullable) IBOutlet NSLayoutConstraint *redViewBottomConstraint;
- (IBAction)resignActiveOnTF:(id)sender;
- (void)keyboardWillChangeFrame:(NSNotification *)notification;
- (void)keyboardWillHide:(NSNotification *)notification;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // put the redView off the bottom of the screen initially (include safe area insets on the bottom
    self.redViewBottomConstraint.constant = -(self.redView.frame.size.height + self.view.safeAreaInsets.bottom);
}

- (void)keyboardWillChangeFrame:(NSNotification *)notification {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        CGFloat keyboardHeight = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
        [self.view layoutIfNeeded];
        // adjust the constraint by the keyboard height and account for the safe area insets on the bottom as well
        self.redViewBottomConstraint.constant = keyboardHeight - self.view.safeAreaInsets.bottom;
        [UIView animateWithDuration:0.4f animations:^{
            self.redView.alpha = 1.0f;
            [self.view layoutIfNeeded];
        }];
    }];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self.view layoutIfNeeded];
            self.redViewBottomConstraint.constant = -(self.redView.frame.size.height + self.view.safeAreaInsets.bottom);
        [UIView animateWithDuration:0.25f animations:^{
            self.redView.alpha = 0.0f;
            [self.view layoutIfNeeded];
        }];
    }];
}

- (IBAction)resignActiveOnTF:(id)sender {
    [self.tf resignFirstResponder];
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


@end

在模拟器上执行操作的示例:

Keyboard_Notification_Example

如果这些都不对您有帮助,我强烈建议您尝试在一个非常简单的示例中重现此内容,并发布您的代码,以便其他人可以提供帮助。

编辑:

我将您的示例代码复制到一个新的视图控制器中,对我来说似乎运行良好。我确实对约束常数的计算做了一个小小的修改(我的底部约束是从键盘向下一直到安全区域底部的视图的底部):

- (void)keyboardFrameChange:(NSNotification *)notification
{
    NSDictionary * userInfo = [notification userInfo];
    CGRect keyboardRect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    double duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    // Anchor the bottom of the message view to the top of the keyboard.
    [UIView animateWithDuration:duration animations:^{
        self.bottomConstraints.constant = (CGRectGetHeight(keyboardRect) - self.view.safeAreaInsets.bottom);
        [self.view layoutIfNeeded];
    }];
}

尽管我认为您在xib中的约束不同?

我已经尝试直接在iPhone 6s上运行它,并且在那里也可以正常运行。我没有方便使用的iPhone X物理设备。