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

时间:2023-01-24 21:22:31

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?

我如何检查这个条件?

17 个解决方案

#1


62  

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

drawnonward的代码非常接近,但是与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

#2


62  

…or take the easy way:

或者走捷径:

When you enter a textField, it becomes first responder and 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时,它就会变成第一个responder,然后键盘就出现了。您可以使用[myTextField isFirstResponder]检查键盘的状态。如果返回YES,则键盘是活动的。

#3


29  

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.

有关这些通知的更多信息,请参阅它们在UIWindow类引用中的描述。有关如何显示和隐藏键盘的信息,请参见文本和Web。

#4


29  

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

当您知道键盘不可见时,创建一个UIKeyboardListener,例如通过调用[UIKeyboardListener共享]从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

#5


11  

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

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

The correct way would be to monitor Keyboard show and hide notifications application wide such as inside your 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.

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

#6


9  

Swift 3 Implementation

迅速实现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
    } 
}

#7


5  

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

这来自苹果发布的iOS文本编程指南:https://developer.apple.com/library/ios/documentation/stringstextfonts/conceptual/textandwebiphoneos/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”。然后,每当键盘激活时,就会调用“keyboardwasshow”。每次键盘消失,“keyboardWillBeHidden”就会被调用。

// 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;
}

#8


5  

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

在iOS8中,这个解是行不通的。它最初是为IOS4/5编写的。

Try this solution:

试试这个解决方案:

- (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;
}

#9


4  

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的底层细节。

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

    return shared;
}

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;键盘:方法如下:

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

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坐标中,与屏幕旋转无关。调用者通过调用来转换矩形

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

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.

所以知道你真正想要什么是很重要的。这段代码对于把东西从键盘上移开是很有用的(如果键盘是分开的或者是不停靠的,那是用户的责任)。它不会告诉您用户是否可以在屏幕上看到键盘(如果是分开的键盘)。它不会告诉您用户是否可以输入(例如当有硬件键盘时)。如果应用程序自己创建了其他窗口,那么查看其他窗口是行不通的。

#10


3  

And here's how to do it in Swift:

以下是如何用Swift操作的方法:

 func registerForKeyboardNotifications() {
    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "keyboardWasShown:",
        name: UIKeyboardDidShowNotification,
        object: nil)

    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "keyboardWillBeHidden:",
        name: UIKeyboardWillHideNotification,
        object: nil)
}

func keyboardWasShown(notification: NSNotification) {
    println("Keyboard was shown");
}

func keyboardWillBeHidden(notification: NSNotification) {
    println("Keyboard was dismissed");
}

Don't forget to unregister:

别忘了注销:

 override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self,
        name: UIKeyboardDidShowNotification,
        object: nil)

    NSNotificationCenter.defaultCenter().removeObserver(self,
        name: UIKeyboardWillHideNotification,
        object: nil)
}

And if you want to dismiss keyboard on pressing the "Return" button:

如果你想在按下“返回”键时关闭键盘:

class ViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var yourTextField: UITextField!

override func viewDidLoad() {
    super.viewDidLoad()
    registerForKeyboardNotifications()
    yourTextField.delegate = self
}

func textFieldShouldReturn(textField: UITextField!) -> Bool {
    self.view.endEditing(true);
    return false;
}

}

#11


2  

Swift implementation:

迅速实现:

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

  func start() {
    let nc = NSNotificationCenter.defaultCenter()
    nc.addObserver(self, selector: #selector(didShow), name: UIKeyboardDidShowNotification, object: nil)
    nc.addObserver(self, selector: #selector(didHide), name: UIKeyboardDidHideNotification, object: nil)
  }

  func didShow()
  {
    isVisible = true
  }

  func didHide()
  {
    isVisible = false
  } 
}

Because swift doesn't execute class load method on startup it is important to start this service on app launch:

由于swift在启动时不执行类加载方法,所以在app启动时启动该服务是非常重要的:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
{
  ...    
  KeyboardStateListener.shared.start() 
}

#12


1  

Try this function

试试这个功能

BOOL UIKeyboardIsVisible(){

BOOL keyboardVisible=NO;
// Locate non-UIWindow.
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
    if (![[testWindow class] isEqual:[UIWindow class]]) {
        keyboardWindow = testWindow;
        break;
    }
}
// Locate UIKeyboard.
for (UIView *possibleKeyboard in [keyboardWindow subviews]) {
    // iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
    if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) {
        keyboardVisible=YES;
    }
    if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) {
        keyboardVisible=YES;
        break;
    }
}
return keyboardVisible;

}

}

from: iOS: How to access the `UIKeyboard`?

从:iOS:如何访问“UIKeyboard”?

#13


1  

BOOL isTxtOpen = [txtfieldObjct isFirstReponder]. If it returns YES, then the the keyboard is active.

BOOL isTxtOpen = [txtfieldObjct isfirthought]。如果返回YES,则键盘是活动的。

#14


1  

To check weather keyboard is appeared, we can use the Keyboard predefined notifications.

要检查天气键盘出现,我们可以使用键盘预定义的通知。

UIKeyboardDidShowNotification ,UIKeyboardDidHideNotification

UIKeyboardDidShowNotification,UIKeyboardDidHideNotification

For example I can use the following code to listen the keyboard notification

例如,我可以使用以下代码监听键盘通知

// Listen for keyboard appearances and disappearances

//聆听键盘的出现和消失

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(keyboardDidShow:)
                                             name:UIKeyboardDidShowNotification
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardDidHide:)
                                             name:UIKeyboardDidHideNotification
                                           object:nil];

in the methods I can get notifications

在这些方法中,我可以获得通知

- (void)keyboardDidShow: (NSNotification *) notifyKeyBoardShow{
    // key board is closed
}

- (void)keyboardDidHide: (NSNotification *) notifyKeyBoardHide{
    // key board is opened
}

#15


1  

This is my solution, it encapsulates everything into a single static method, and you can call it anywhere to check:

这是我的解决方案,它将所有内容封装到一个静态方法中,您可以在任何地方调用它来检查:

+(BOOL)isKeyboardVisible{
    static id tokenKeyboardWillShow = nil;
    static id tokenKeyboardWillHide = nil;
    static BOOL isKbVisible = NO;
    @synchronized (self) {
        if (tokenKeyboardWillShow == nil){
            tokenKeyboardWillShow = [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
                @synchronized (self) {
                    isKbVisible = YES;
                }
            }];
        }

        if (tokenKeyboardWillHide == nil){
            tokenKeyboardWillHide = [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillHideNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
                @synchronized (self) {
                    isKbVisible = NO;
                }
            }];
        }
    }

    return isKbVisible;
}

#16


0  

You can iteratively check all textviews, textfields, and labels in the subviews of a parent view to see if any are the first responder with something like this:

可以反复检查父视图的子视图中的所有textview、textfields和label,看看是否有这样的第一个responder:

-(BOOL)isKeyboardActiveInView:(UIView *)view {
    for (UIView *anyView in [view subviews]) {
        if ([anyView isKindOfClass:[UITextField class]]) {
            if (((UITextField *)anyView).isFirstResponder) {
                return YES;
            }
        } else if ([anyView isKindOfClass:[UILabel class]]) {
            if (((UILabel *)anyView).isFirstResponder) {
                return YES;
            }
        } else if ([anyView isKindOfClass:[UITextView class]]) {
            if (((UITextView *)anyView).isFirstResponder) {
                return YES;
            }
        } else {
            if ([self isKeyboardActiveInView:anyView]) {
                return YES;
            }
        }
    }
    return NO;
}

#17


-4  

I think this may help u,

我想这可能对你有帮助,

+(BOOL)isKeyBoardInDisplay  {

    BOOL isExists = NO;
    for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows])   {
        if ([[keyboardWindow description] hasPrefix:@"<UITextEffectsWindow"] == YES) {
            isExists = YES;
        }  
    }

    return isExists;
}

thanks,

谢谢,

Naveen Shan

Naveen山

#1


62  

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

drawnonward的代码非常接近,但是与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

#2


62  

…or take the easy way:

或者走捷径:

When you enter a textField, it becomes first responder and 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时,它就会变成第一个responder,然后键盘就出现了。您可以使用[myTextField isFirstResponder]检查键盘的状态。如果返回YES,则键盘是活动的。

#3


29  

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.

有关这些通知的更多信息,请参阅它们在UIWindow类引用中的描述。有关如何显示和隐藏键盘的信息,请参见文本和Web。

#4


29  

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

当您知道键盘不可见时,创建一个UIKeyboardListener,例如通过调用[UIKeyboardListener共享]从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

#5


11  

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

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

The correct way would be to monitor Keyboard show and hide notifications application wide such as inside your 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.

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

#6


9  

Swift 3 Implementation

迅速实现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
    } 
}

#7


5  

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

这来自苹果发布的iOS文本编程指南:https://developer.apple.com/library/ios/documentation/stringstextfonts/conceptual/textandwebiphoneos/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”。然后,每当键盘激活时,就会调用“keyboardwasshow”。每次键盘消失,“keyboardWillBeHidden”就会被调用。

// 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;
}

#8


5  

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

在iOS8中,这个解是行不通的。它最初是为IOS4/5编写的。

Try this solution:

试试这个解决方案:

- (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;
}

#9


4  

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的底层细节。

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

    return shared;
}

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;键盘:方法如下:

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

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坐标中,与屏幕旋转无关。调用者通过调用来转换矩形

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

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.

所以知道你真正想要什么是很重要的。这段代码对于把东西从键盘上移开是很有用的(如果键盘是分开的或者是不停靠的,那是用户的责任)。它不会告诉您用户是否可以在屏幕上看到键盘(如果是分开的键盘)。它不会告诉您用户是否可以输入(例如当有硬件键盘时)。如果应用程序自己创建了其他窗口,那么查看其他窗口是行不通的。

#10


3  

And here's how to do it in Swift:

以下是如何用Swift操作的方法:

 func registerForKeyboardNotifications() {
    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "keyboardWasShown:",
        name: UIKeyboardDidShowNotification,
        object: nil)

    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "keyboardWillBeHidden:",
        name: UIKeyboardWillHideNotification,
        object: nil)
}

func keyboardWasShown(notification: NSNotification) {
    println("Keyboard was shown");
}

func keyboardWillBeHidden(notification: NSNotification) {
    println("Keyboard was dismissed");
}

Don't forget to unregister:

别忘了注销:

 override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self,
        name: UIKeyboardDidShowNotification,
        object: nil)

    NSNotificationCenter.defaultCenter().removeObserver(self,
        name: UIKeyboardWillHideNotification,
        object: nil)
}

And if you want to dismiss keyboard on pressing the "Return" button:

如果你想在按下“返回”键时关闭键盘:

class ViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var yourTextField: UITextField!

override func viewDidLoad() {
    super.viewDidLoad()
    registerForKeyboardNotifications()
    yourTextField.delegate = self
}

func textFieldShouldReturn(textField: UITextField!) -> Bool {
    self.view.endEditing(true);
    return false;
}

}

#11


2  

Swift implementation:

迅速实现:

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

  func start() {
    let nc = NSNotificationCenter.defaultCenter()
    nc.addObserver(self, selector: #selector(didShow), name: UIKeyboardDidShowNotification, object: nil)
    nc.addObserver(self, selector: #selector(didHide), name: UIKeyboardDidHideNotification, object: nil)
  }

  func didShow()
  {
    isVisible = true
  }

  func didHide()
  {
    isVisible = false
  } 
}

Because swift doesn't execute class load method on startup it is important to start this service on app launch:

由于swift在启动时不执行类加载方法,所以在app启动时启动该服务是非常重要的:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
{
  ...    
  KeyboardStateListener.shared.start() 
}

#12


1  

Try this function

试试这个功能

BOOL UIKeyboardIsVisible(){

BOOL keyboardVisible=NO;
// Locate non-UIWindow.
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
    if (![[testWindow class] isEqual:[UIWindow class]]) {
        keyboardWindow = testWindow;
        break;
    }
}
// Locate UIKeyboard.
for (UIView *possibleKeyboard in [keyboardWindow subviews]) {
    // iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
    if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) {
        keyboardVisible=YES;
    }
    if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) {
        keyboardVisible=YES;
        break;
    }
}
return keyboardVisible;

}

}

from: iOS: How to access the `UIKeyboard`?

从:iOS:如何访问“UIKeyboard”?

#13


1  

BOOL isTxtOpen = [txtfieldObjct isFirstReponder]. If it returns YES, then the the keyboard is active.

BOOL isTxtOpen = [txtfieldObjct isfirthought]。如果返回YES,则键盘是活动的。

#14


1  

To check weather keyboard is appeared, we can use the Keyboard predefined notifications.

要检查天气键盘出现,我们可以使用键盘预定义的通知。

UIKeyboardDidShowNotification ,UIKeyboardDidHideNotification

UIKeyboardDidShowNotification,UIKeyboardDidHideNotification

For example I can use the following code to listen the keyboard notification

例如,我可以使用以下代码监听键盘通知

// Listen for keyboard appearances and disappearances

//聆听键盘的出现和消失

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(keyboardDidShow:)
                                             name:UIKeyboardDidShowNotification
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardDidHide:)
                                             name:UIKeyboardDidHideNotification
                                           object:nil];

in the methods I can get notifications

在这些方法中,我可以获得通知

- (void)keyboardDidShow: (NSNotification *) notifyKeyBoardShow{
    // key board is closed
}

- (void)keyboardDidHide: (NSNotification *) notifyKeyBoardHide{
    // key board is opened
}

#15


1  

This is my solution, it encapsulates everything into a single static method, and you can call it anywhere to check:

这是我的解决方案,它将所有内容封装到一个静态方法中,您可以在任何地方调用它来检查:

+(BOOL)isKeyboardVisible{
    static id tokenKeyboardWillShow = nil;
    static id tokenKeyboardWillHide = nil;
    static BOOL isKbVisible = NO;
    @synchronized (self) {
        if (tokenKeyboardWillShow == nil){
            tokenKeyboardWillShow = [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
                @synchronized (self) {
                    isKbVisible = YES;
                }
            }];
        }

        if (tokenKeyboardWillHide == nil){
            tokenKeyboardWillHide = [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillHideNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
                @synchronized (self) {
                    isKbVisible = NO;
                }
            }];
        }
    }

    return isKbVisible;
}

#16


0  

You can iteratively check all textviews, textfields, and labels in the subviews of a parent view to see if any are the first responder with something like this:

可以反复检查父视图的子视图中的所有textview、textfields和label,看看是否有这样的第一个responder:

-(BOOL)isKeyboardActiveInView:(UIView *)view {
    for (UIView *anyView in [view subviews]) {
        if ([anyView isKindOfClass:[UITextField class]]) {
            if (((UITextField *)anyView).isFirstResponder) {
                return YES;
            }
        } else if ([anyView isKindOfClass:[UILabel class]]) {
            if (((UILabel *)anyView).isFirstResponder) {
                return YES;
            }
        } else if ([anyView isKindOfClass:[UITextView class]]) {
            if (((UITextView *)anyView).isFirstResponder) {
                return YES;
            }
        } else {
            if ([self isKeyboardActiveInView:anyView]) {
                return YES;
            }
        }
    }
    return NO;
}

#17


-4  

I think this may help u,

我想这可能对你有帮助,

+(BOOL)isKeyBoardInDisplay  {

    BOOL isExists = NO;
    for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows])   {
        if ([[keyboardWindow description] hasPrefix:@"<UITextEffectsWindow"] == YES) {
            isExists = YES;
        }  
    }

    return isExists;
}

thanks,

谢谢,

Naveen Shan

Naveen山