如何以编程方式检查 iOS 应用程序中是否存在键盘?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1490573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:28:23  来源:igfitidea点击:

How can I programmatically check whether a keyboard is present in iOS app?

iosobjective-ckeyboard

提问by Jitendra Singh

I need to check the condition of keyboard visibility in my iOS app.

我需要在我的 iOS 应用程序中检查键盘可见性的条件。

Pseudocode:

伪代码:

if(keyboardIsPresentOnWindow) {
    //Do action 1
}
else if (keyboardIsNotPresentOnWindow) {
    //Do action 2
}

How can I check this condition?

我如何检查这种情况?

回答by thpitsch

…or take the easy way:

...或采取简单的方法:

When you enter a textField, it becomes first responderand the keyboard appears. You can check the status of the keyboard with [myTextField isFirstResponder]. If it returns YES, then the the keyboard is active.

当您输入 textField 时,它将成为第一响应者并出现键盘。您可以使用 来检查键盘的状态[myTextField isFirstResponder]。如果返回YES,则键盘处于活动状态。

回答by rpetrich

drawnonward's code is very close, but collides with UIKit's namespace and could be made easier to use.

drawonward 的代码非常接近,但与 UIKit 的命名空间发生冲突,可以使其更易于使用。

@interface KeyboardStateListener : NSObject {
    BOOL _isVisible;
}
+ (KeyboardStateListener *)sharedInstance;
@property (nonatomic, readonly, getter=isVisible) BOOL visible;
@end

static KeyboardStateListener *sharedInstance;

@implementation KeyboardStateListener

+ (KeyboardStateListener *)sharedInstance
{
    return sharedInstance;
}

+ (void)load
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    sharedInstance = [[self alloc] init];
    [pool release];
}

- (BOOL)isVisible
{
    return _isVisible;
}

- (void)didShow
{
    _isVisible = YES;
}

- (void)didHide
{
    _isVisible = NO;
}

- (id)init
{
    if ((self = [super init])) {
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(didShow) name:UIKeyboardDidShowNotification object:nil];
        [center addObserver:self selector:@selector(didHide) name:UIKeyboardWillHideNotification object:nil];
    }
    return self;
}

@end

回答by rpetrich

Create a UIKeyboardListenerwhen you know the keyboard is not visible, for example by calling [UIKeyboardListener shared]from applicationDidFinishLaunching.

UIKeyboardListener当您知道键盘不可见时创建一个,例如通过[UIKeyboardListener shared]从调用applicationDidFinishLaunching

@implementation UIKeyboardListener

+ (UIKeyboardListener) shared {
    static UIKeyboardListener sListener;    
    if ( nil == sListener ) sListener = [[UIKeyboardListener alloc] init];

    return sListener;
}

-(id) init {
    self = [super init];

    if ( self ) {
        NSNotificationCenter        *center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(noticeShowKeyboard:) name:UIKeyboardDidShowNotification object:nil];
        [center addObserver:self selector:@selector(noticeHideKeyboard:) name:UIKeyboardWillHideNotification object:nil];
    }

    return self;
}

-(void) noticeShowKeyboard:(NSNotification *)inNotification {
    _visible = true;
}

-(void) noticeHideKeyboard:(NSNotification *)inNotification {
    _visible = false;
}

-(BOOL) isVisible {
    return _visible;
}

@end

回答by beggs

I think you need to use the notifications that are provided about the keyboard:

我认为您需要使用提供的有关键盘的通知:

From: http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UITextField_Class/Reference/UITextField.html

来自:http: //developer.apple.com/iphone/library/documentation/UIKit/Reference/UITextField_Class/Reference/UITextField.html

Keyboard Notifications

When the system shows or hides the keyboard, it posts several keyboard notifications. These notifications contain information about the keyboard, including its size, which you can use for calculations that involve moving views. Registering for these notifications is the only way to get some types of information about the keyboard. The system delivers the following notifications for keyboard-related events:

* UIKeyboardWillShowNotification
* UIKeyboardDidShowNotification
* UIKeyboardWillHideNotification
* UIKeyboardDidHideNotification

For more information about these notifications, see their descriptions in UIWindow Class Reference. For information about how to show and hide the keyboard, see Text and Web.

键盘通知

当系统显示或隐藏键盘时,它会发布多个键盘通知。这些通知包含有关键盘的信息,包括其大小,可用于涉及移动视图的计算。注册这些通知是获取有关键盘的某些类型信息的唯一方法。系统为键盘相关事件提供以下通知:

* UIKeyboardWillShowNotification
* UIKeyboardDidShowNotification
* UIKeyboardWillHideNotification
* UIKeyboardDidHideNotification

有关这些通知的更多信息,请参阅 UIWindow 类参考中的说明。有关如何显示和隐藏键盘的信息,请参阅文本和 Web。

回答by Christos Chadjikyriacou

Swift 3 Implementation

Swift 3 实现

    import Foundation
class KeyboardStateListener: NSObject
{
    static let shared = KeyboardStateListener()
    var isVisible = false

    func start() {
        NotificationCenter.default.addObserver(self, selector: #selector(didShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(didHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    func didShow()
    {
        isVisible = true
    }

    func didHide()
    {
        isVisible = false
    } 
}

回答by Vlad

Using the window subview hierarchy as indication for keyboard showing is a hack. If Apple changers their underlying implementation all these answers would break.

使用窗口子视图层次结构作为键盘显示的指示是一种技巧。如果 Apple 改变他们的底层实现,所有这些答案都会失效。

The correct way would be to monitor Keyboard show and hide notifications application wide such as inside your App Delegate:

正确的方法是监视键盘显示和隐藏应用程序范围内的通知,例如在您的 App Delegate 内:

In AppDelegate.h:

在 AppDelegate.h 中:

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (assign, nonatomic) BOOL keyboardIsShowing;

@end

In AppDelegate.m:

在 AppDelegate.m 中:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    // Monitor keyboard status application wide
    self.keyboardIsShowing = NO;
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
                                             name:UIKeyboardWillHideNotification object:nil];

    return YES;
}

- (void)keyboardWillShow:(NSNotification*)aNotification
{
    self.keyboardIsShowing = YES;
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    self.keyboardIsShowing = NO;
}

Then you can check using:

然后您可以使用以下方法进行检查:

BOOL keyboardIsShowing = ((AppDelegate*)[UIApplication sharedApplication].delegate).keyboardIsShowing;

It should be noted the keyboard show/hide notifications will not fire when user is using a bluetooth or external keyboard.

应该注意的是,当用户使用蓝牙或外部键盘时,键盘显示/隐藏通知不会触发。

回答by Kay Cee

Add an extension

添加扩展

extension UIApplication {
    /// Checks if view hierarchy of application contains `UIRemoteKeyboardWindow` if it does, keyboard is presented
    var isKeyboardPresented: Bool {
        if let keyboardWindowClass = NSClassFromString("UIRemoteKeyboardWindow"),
            self.windows.contains(where: { 
if UIApplication.shared.isKeyboardPresented {
     print("Keyboard presented")
} else { 
     print("Keyboard is not presented")
}
.isKind(of: keyboardWindowClass) }) { return true } else { return false } } }

Then check if keyboard is present,

然后检查键盘是否存在,

// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
}

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification {
    NSLog(@"Keyboard is active.");
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;

    // If active text field is hidden by keyboard, scroll it so it's visible
    // Your app might not need or want this behavior.
    CGRect aRect = self.view.frame;
    aRect.size.height -= kbSize.height;
    if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
        [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
    }
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification {
    NSLog(@"Keyboard is hidden");
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;
}

回答by Scuttle

This is from the iOS Text Programming Guide published by Apple here: https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

这是来自 Apple 在此处发布的 iOS 文本编程指南:https: //developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

Basically call "registerForKeyBoardNotifications" in your ViewDidLoad. Then every time the keyboard becomes active, "keyboardWasShown" is called. And every time the keyboard disappears, "keyboardWillBeHidden" is called.

基本上在您的 ViewDidLoad 中调用“registerForKeyBoardNotifications”。然后每次键盘激活时,都会调用“keyboardWasShown”。每次键盘消失时,都会调用“keyboardWillBeHidden”。

- (BOOL) isKeyboardOnScreen 
{
    BOOL isKeyboardShown = NO;

    NSArray *windows = [UIApplication sharedApplication].windows;
    if (windows.count > 1) {
        NSArray *wSubviews =  [windows[1]  subviews];
        if (wSubviews.count) {
            CGRect keyboardFrame = [wSubviews[0] frame];
            CGRect screenFrame = [windows[1] frame];
            if (keyboardFrame.origin.y+keyboardFrame.size.height == screenFrame.size.height) {
                isKeyboardShown = YES;
            }
        }
    }

    return isKeyboardShown;
}

回答by malex

Now in iOS8 this solution of course doesn't work. It was written initially for IOS4/5.

现在在 iOS8 中,这个解决方案当然不起作用。它最初是为 IOS4/5 编写的。

Try this solution:

试试这个解决方案:

+ (KeyboardStateListener *)sharedInstance
{
    static KeyboardStateListener* shared;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shared = [[KeyboardStateListener alloc] init];
        // Other initialisations
    });

    return shared;
}

回答by Chris

A few observations:

一些观察:

The recommended pattern for a singleton object would be as follows. dispatch_once makes sure the class is initialised once in a thread-safe way, and the static variable isn't visible outside. And it's standard GCD, so no need to know about low level details of Objective-C.

单例对象的推荐模式如下。dispatch_once 确保类以线程安全的方式初始化一次,并且静态变量在外部不可见。而且它是标准的 GCD,因此无需了解 Objective-C 的底层细节。

NSValue* value = notification.userInfo [UIKeyboardFrameEndUserInfoKey];
_keyboardRect = value.CGRectValue;

Usually you don't want to know just whether the keyboard is visible or not, but how big it is. Keyboards don't all have the same size. iPhone keyboards are smaller than iPad keyboards. So you'd want another property @property (readonly, nonatomic) CGRect keyboardRect;which is set in the noticeShowKeyboard: method like this:

通常你不想知道键盘是否可见,而是它有多大。并非所有键盘都具有相同的尺寸。iPhone 键盘比 iPad 键盘小。因此,您需要@property (readonly, nonatomic) CGRect keyboardRect;在 noticeShowKeyboard: 方法中设置另一个属性,如下所示:

KeyboardStateListener* listener = [KeyboardStateListener sharedInstance];
CGRect windowRect = listener.keyboardRect;
CGRect viewRect = [myView convertRect:windowRect fromView:self.window];

Important to notice that the rectangle is in UIWindow coordinates and doesn't respect screen rotation. So the caller would convert that rectangle by calling

重要的是要注意矩形在 UIWindow 坐标中并且不考虑屏幕旋转。所以调用者会通过调用来转换那个矩形

##代码##

If the user rotates the screen while the keyboard is visible, the app will be told that the keyboard is hidden, then shown again. When it is shown, other views are most likely not rotated yet. So if you observe keyboard hide/show events yourself, convert the coordinates when you actually need them, not in the notification.

如果用户在键盘可见时旋转屏幕,应用程序将被告知键盘已隐藏,然后再次显示。显示时,其他视图很可能尚未旋转。因此,如果您自己观察键盘隐藏/显示事件,请在实际需要时转换坐标,而不是在通知中。

If the user splits or undocks the keyboard, or uses a hardware keyboard, the notifications will always show the keyboard as hidden. Undocking or merging the keyboard will send a "keyboard shown" notification.

如果用户拆分或取消键盘,或使用硬件键盘,通知将始终显示键盘为隐藏。取消对接或合并键盘将发送“显示键盘”通知。

The listener must be initialised while the keyboard is hidden, otherwise the first notification will be missed, and it will be assumed that the keyboard is hidden when it's not.

必须在键盘隐藏时初始化侦听器,否则将错过第一个通知,并假设键盘隐藏时隐藏。

So it is quite important to know what you actually want. This code is useful to move things out of the way of the keyboard (with a split or undocked keyboard, that's the responsibility of the user). It doesn't tell you whether the user can see a keyboard on the screen (in case of a split keyboard). It doesn't tell you whether the user can type (for example when there is a hardware keyboard). Looking at other windows doesn't work if the app creates other windows itself.

因此,了解自己真正想要什么非常重要。此代码对于将东西移出键盘很有用(对于拆分或未对接的键盘,这是用户的责任)。它不会告诉您用户是否可以在屏幕上看到键盘(在拆分键盘的情况下)。它不会告诉您用户是否可以键入(例如,当有硬件键盘时)。如果应用程序本身创建了其他窗口,则查看其他窗口不起作用。