web-dev-qa-db-ja.com

iOSアプリにキーボードが存在するかどうかをプログラムで確認するにはどうすればよいですか?

IOSアプリでキーボードの可視性の状態を確認する必要があります。

擬似コード:

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

この状態を確認するにはどうすればよいですか?

104
Jitendra Singh

…または簡単な方法を使用します。

TextFieldを入力すると、first responderになり、キーボードが表示されます。 [myTextField isFirstResponder]を使用してキーボードのステータスを確認できます。 YESを返す場合、キーボードはアクティブです。

64
thpitsch

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
63
rpetrich

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
31
drawnonward

キーボードについて提供されている通知を使用する必要があると思います。

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

キーボード通知

システムがキーボードを表示または非表示にすると、キーボード通知がいくつか投稿されます。これらの通知には、サイズを含むキーボードに関する情報が含まれており、ビューの移動を伴う計算に使用できます。これらの通知の登録は、キーボードに関するいくつかのタイプの情報を取得する唯一の方法です。システムは、キーボード関連のイベントについて次の通知を配信します。

* UIKeyboardWillShowNotification
* UIKeyboardDidShowNotification
* UIKeyboardWillHideNotification
* UIKeyboardDidHideNotification

これらの通知の詳細については、UIWindowクラスリファレンスの説明を参照してください。キーボードを表示および非表示にする方法については、「テキストとWeb」を参照してください。

29
beggs

ウィンドウサブビュー階層をキーボード表示の指標として使用するのはハッキングです。 Appleが基礎となる実装を変更すると、これらすべての答えが壊れます。

正しい方法は、アプリのデリゲート内など、アプリケーション全体でキーボードの表示と非表示を監視することです。

AppDelegate.hで:

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (assign, nonatomic) BOOL keyboardIsShowing;

@end

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

次に、以下を使用して確認できます。

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

ユーザーがbluetoothまたは外部キーボードを使用している場合、キーボードの表示/非表示通知は起動しません。

11
Vlad

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

これは、Appleが公開しているiOS Text Programming Guideからのものです。 https://developer.Apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

基本的に、ViewDidLoadで「registerForKeyBoardNotifications」を呼び出します。その後、キーボードがアクティブになるたびに、「keyboardWasShown」が呼び出されます。そして、キーボードが消えるたびに、「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;
}
5
Scuttle

IOS8では、このソリューションはもちろん機能しません。 IOS4/5向けに最初に書かれました。

この解決策を試してください:

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

いくつかの観察:

シングルトンオブジェクトの推奨パターンは次のとおりです。 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;
}

通常、キーボードが表示されているかどうかだけを知りたくはありませんが、大きさは知りたいです。キーボードはすべて同じサイズではありません。 iPhoneキーボードはiPadキーボードよりも小さいです。したがって、次のようなnoticeShowKeyboard:メソッドで設定される別のプロパティ@property (readonly, nonatomic) CGRect keyboardRect;が必要になります。

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

四角形はUIWindow座標にあり、画面の回転を考慮しないことに注意してください。したがって、呼び出し元は、次の呼び出しによってその長方形を変換します

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

キーボードが表示されているときにユーザーが画面を回転させると、キーボードが非表示になったことがアプリに通知され、再び表示されます。表示されるとき、他のビューはまだ回転していない可能性が高いです。したがって、キーボードの非表示/表示イベントを自分で観察する場合は、通知ではなく、実際に必要なときに座標を変換してください。

ユーザーがキーボードを分割または取り外した場合、またはハードウェアキーボードを使用した場合、通知には常にキーボードが非表示として表示されます。キーボードをドッキング解除またはマージすると、「キーボード表示」通知が送信されます。

キーボードが非表示のときにリスナーを初期化する必要があります。そうしないと、最初の通知が失われ、キーボードが非表示のときに非表示になると想定されます。

そのため、実際に何を望んでいるかを知ることが非常に重要です。このコードは、キーボードの邪魔にならないように移動するのに便利です(分割またはドッキングされていないキーボードの場合、ユーザーの責任です)。ユーザーが画面にキーボードを表示できるかどうかはわかりません(分割キーボードの場合)。ユーザーが入力できるかどうかはわかりません(たとえば、ハードウェアキーボードがある場合)。アプリが他のウィンドウ自体を作成する場合、他のウィンドウを表示しても機能しません。

4
Chris

拡張子を追加

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: { $0.isKind(of: keyboardWindowClass) }) {
        return true
    } else {
        return false
    }
}

}

その後、キーボードが存在するかどうかを確認します

if UIApplication.shared.isKeyboardPresented {
     print("Keyboard presented")
} else { 
     print("Keyboard is not presented")
}
4
Kay Cee

そして、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");
}

登録解除を忘れないでください:

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

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

また、「戻る」ボタンを押してキーボードを閉じる場合:

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

}
3
Teodor Ciuraru

Swift実装:

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

Swiftは起動時にクラスloadメソッドを実行しないため、アプリの起動時にこのサービスを開始することが重要です。

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

これは私の解決策であり、すべてを単一の静的メソッドにカプセル化し、どこでも呼び出すことができます:

+(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;
}
2
pthr

Swift 4

extension UIViewController {
    func registerKeyboardNotifications() {
        let center = NotificationCenter.default
        center.addObserver(self, selector: #selector(keyboardWillBeShown(note:)), name: Notification.Name.UIKeyboardWillShow, object: nil)
        center.addObserver(self, selector: #selector(keyboardWillBeHidden(note:)), name: Notification.Name.UIKeyboardWillHide, object: nil)
    }

    func removeKeyboardNotifications() {
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)

    }

    @objc
    func keyboardWillBeShown(note: Notification) {}

    @objc
    func keyboardWillBeHidden(note: Notification) {}

}

final class MyViewController: UIViewController {

    // MARK: - Properties
    var isKeyboardVisible = false

    // MARK: - Life Cycle
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        registerKeyboardNotifications()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        removeKeyboardNotifications()
    }

    // MARK: - Keyboard Handling
    override func keyboardWillBeShown(note: Notification) {
        isKeyboardVisible = true
        let userInfo = note.userInfo
        let keyboardFrame = userInfo?[UIKeyboardFrameEndUserInfoKey] as! CGRect
        let contentInset = UIEdgeInsetsMake(0.0, 0.0, keyboardFrame.height, 0.0)
        tableView.contentInset = contentInset
    }

   override func keyboardWillBeHidden(note: Notification) {
        tableView.contentInset = .zero
        isKeyboardVisible = false
   }

   // MARK: - Test
   fileprivate func test() {
        if isKeyboardVisible { // do something
        }
   }
}
2
Amber K

BOOL isTxtOpen = [txtfieldObjct isFirstReponder]。 YESが返される場合、キーボードはアクティブです。

1
Hardik Mamtora

Swift 4.2/Swift 5

class Listener {
   public static let shared = Listener()
   var isVisible = false

   // Start this listener if you want to present the toast above the keyboard.
   public func startKeyboardListener() {
      NotificationCenter.default.addObserver(self, selector: #selector(didShow), name: UIResponder.keyboardWillShowNotification, object: nil)
      NotificationCenter.default.addObserver(self, selector: #selector(didHide), name: UIResponder.keyboardWillHideNotification, object: nil)
   }

   @objc func didShow() {
     isVisible = true
   }

    @objc func didHide(){
       isVisible = false
    }
}
1
Amrit Sidhu

天気キーボードが表示されることを確認するには、キーボードの事前定義通知を使用できます。

UIKeyboardDidShowNotification、UIKeyboardDidHideNotification

たとえば、次のコードを使用してキーボード通知を聞くことができます

//キーボードの出現と消失をリッスンします

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

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

メソッドで通知を取得できます

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

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

この機能を試してください

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:「UIKeyboard」へのアクセス方法

1
Vanguarder

親ビューのサブビュー内のすべてのテキストビュー、テキストフィールド、ラベルを繰り返し確認して、次のような最初のレスポンダーがあるかどうかを確認できます。

-(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;
}
0
Albert Renshaw