【问题标题】:UIKeyboardWillChangeFrameNotification doesn't get fired while dictation (Speech to text) button pressed按下听写(语音转文本)按钮时不会触发 UIKeyboardWillChangeFrameNotification
【发布时间】:2019-03-29 00:14:01
【问题描述】:

我正在开发一个具有聊天功能的应用程序,所以我的要求是在键盘顶部显示文本字段。由于需要不使用滚动视图,我在 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];
}

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

【问题讨论】:

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


    【解决方案1】:

    我刚刚创建了一个快速测试项目,当我点击听写按钮时,通知似乎在我的末端通过。我只能推测您可能出了什么问题,因为您根本没有包含任何代码,但有几个猜测是:

    • 通知已通过,但针对键盘高度调整的计算不正确(可能没有考虑到 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
    

    还有一个例子是模拟器上的动作:

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

    编辑:

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

    - (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 物理设备来测试它。

    【讨论】:

    • 感谢您的帮助。我已经在上面添加了我的示例代码,请检查它。另外,只是想知道您是否在设备上测试过您的代码?
    • 是的,它在除全屏(iPhone X 及更高版本)之外的所有设备上都能正常工作。
    • 我很好奇您是否覆盖 - (void)viewSafeAreaInsetsDidChange { [super viewSafeAreaInsetsDidChange]; } 是否收到该通知(即,安全区域插图可能正在更改,但设备上的键盘高度保持不变)
    猜你喜欢
    • 2020-03-12
    • 2018-11-21
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    • 2011-07-06
    • 2019-11-29
    • 2018-08-24
    相关资源
    最近更新 更多