Как я могу программно проверить, присутствует ли клавиатура в приложении iOS?
Мне нужно проверить состояние видимости клавиатуры в приложении iOS.
псевдокод:
if(keyboardIsPresentOnWindow) { //Do action 1 } else if (keyboardIsNotPresentOnWindow) { //Do action 2 }
Как я могу проверить это условие?
- Как использовать NSTimer?
- Выполнение команд оболочки с помощью NSTask - Objective-C Cocoa
- Сортировка NSArray пользовательских объектов по их свойствам NSDate
- Класс размера для iPad-портрета и ландшафтных режимов
- установить фоновое изображение для всего приложения iPhone / iPad
- Как отслеживать причину SIGABRT
- Измените первый символ в каждом слове строки на верхний регистр.
- Как сделать естественный вид на NSArray?
- Сохранение UIColor и загрузка из NSUserDefaults
- Как я могу отложить вызов метода на 1 секунду?
- Как сделать ui отзывчивым все время и делать обновление фона?
- Скрытые особенности Xcode
- Objective-c iPhone-процент кодирует строку?
Код 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
… или взять простой способ:
Когда вы вводите textField, он становится первым ответчиком и появляется клавиатура. Вы можете проверить статус клавиатуры с помощью [myTextField isFirstResponder]
. Если он вернет YES
, клавиатура будет активна.
Я думаю, вам нужно использовать уведомления о клавиатуре:
Уведомления о клавиатуре
Когда система показывает или скрывает клавиатуру, она публикует несколько уведомлений о клавиатуре. Эти уведомления содержат информацию о клавиатуре, включая ее размер, которые вы можете использовать для расчетов, которые include в себя перемещение видов. Регистрация этих уведомлений – единственный способ получить информацию о клавиатуре. Система предоставляет следующие уведомления о событиях, связанных с клавиатурой:
* UIKeyboardWillShowNotification * UIKeyboardDidShowNotification * UIKeyboardWillHideNotification * UIKeyboardDidHideNotification
Для получения дополнительной информации об этих уведомлениях см. Их описания в UIWindow Class Reference. Информацию о том, как показывать и скрывать клавиатуру, см. В разделе «Текст и Интернет».
Создайте 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
Использование иерархии подвешенного windows в качестве индикатора для показа клавиатуры – это взломать. Если Apple сменяет свою базовую реализацию, все эти ответы нарушатся.
Правильный способ – следить за отображением клавиатуры и скрывать приложение уведомлений, например, внутри вашего делегата приложения:
В AppDelegate.h:
@interface AppDelegate : UIResponder @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 или внешнюю клавиатуру.
Быстрая реализация 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 } }
Это из руководства по программированию текста iOS, опубликованного Apple здесь: https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
В основном вызывается «registerForKeyBoardNotifications» в вашем ViewDidLoad. Затем каждый раз, когда клавиатура становится активной, вызывается «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; }
Теперь в 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; }
Несколько замечаний:
Рекомендуемый шаблон для одноэлементного объекта будет следующим. dispatch_once гарантирует, что class инициализируется один раз поточно-безопасным способом, а статическая переменная не видна снаружи. И это стандартный 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. Поэтому вам нужно другое свойство @property (readonly, nonatomic) CGRect keyboardRect;
который установлен в методе уведомленияShowKeyboard: следующим образом:
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];
Если пользователь поворачивает экран, пока клавиатура видна, приложению сообщается, что клавиатура скрыта, а затем снова показана. Когда это показано, другие виды, скорее всего, еще не вращаются. Поэтому, если вы сами наблюдаете за событиями, связанными с клавиатурой или шоу, конвертируйте координаты, когда они вам действительно нужны, а не в уведомлении.
Если пользователь разбивает или отстыкует клавиатуру или использует аппаратную клавиатуру, уведомления всегда будут показывать клавиатуру как скрытую. Отмена или слияние клавиатуры отправит уведомление с клавиатуры.
Слушатель должен быть инициализирован, пока клавиатура скрыта, в противном случае первое уведомление будет пропущено, и предполагается, что клавиатура скрыта, когда это не так.
Поэтому очень важно знать, чего вы на самом деле хотите. Этот код полезен для перемещения вещей с клавиатуры (с разделенной или открепленной клавиатурой, это ответственность пользователя). Он не говорит вам, может ли пользователь видеть клавиатуру на экране (в случае разделенной клавиатуры). Он не говорит вам, может ли пользователь печатать (например, когда есть аппаратная клавиатура). Просмотр других окон не работает, если приложение создает другие windows.
И вот как это сделать в 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; } }
Быстрая реализация:
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 не запускает метод загрузки classа при запуске, важно запустить эту службу при запуске приложения:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool { ... KeyboardStateListener.shared.start() }
Попробуйте эту функцию
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:@"
}
from: iOS: Как получить доступ к `UIKeyboard`?
BOOL isTxtOpen = [txtfieldObjct isFirstReponder]. Если он вернет YES, клавиатура будет активна.
Чтобы проверить погодную клавиатуру, мы можем использовать предопределенные уведомления на клавиатуре.
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 }
Это мое решение, оно инкапсулирует все в один статический метод, и вы можете позвонить ему где угодно, чтобы проверить:
+(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; }
Вы можете итеративно проверять все текстовые поля, текстовые поля и метки в подзонах родительского представления, чтобы увидеть, являются ли они первыми ответчиками с чем-то вроде этого:
-(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; }
Я думаю, это может помочь вам,
+(BOOL)isKeyBoardInDisplay { BOOL isExists = NO; for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) { if ([[keyboardWindow description] hasPrefix:@"
благодаря,
Навен Шань