Мені потрібно перевірити стан видимості клавіатури в моєму додатку iOS.
Псевдокод:
if(keyboardIsPresentOnWindow) {
//Do action 1
}
else if (keyboardIsNotPresentOnWindow) {
//Do action 2
}
Як я можу перевірити цей стан?
Мені потрібно перевірити стан видимості клавіатури в моєму додатку iOS.
Псевдокод:
if(keyboardIsPresentOnWindow) {
//Do action 1
}
else if (keyboardIsNotPresentOnWindow) {
//Do action 2
}
Як я можу перевірити цей стан?
Відповіді:
… Або скористайтеся простим способом:
Коли ви вводите текстове поле, воно стає першим відповіддю і з'являється клавіатура. Ви можете перевірити стан клавіатури за допомогою [myTextField isFirstResponder]
. Якщо він повертається YES
, клавіатура активна.
Код 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
+load
- це спеціальний метод, який називається об'єктом виконання C. Він викликається для кожного класу після бінарних завантажень програми, але перед введенням main()
функції. Немає гарантії, що пул автоматичного випуску буде живим.
NSAutoreleasePool
alloc
/ release
зараз його можна замінити оточуючим кодом@autoreleasepool { }
Створіть, 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
+(void)load
для виклику init у цьому класі слухачів, щоб він загалом працював як перетягування будь-якого проекту та ініціалізація з другого запуску програми, а не вам потрібно пам’ятати, щоб запустити його де завгодно.
Я думаю, вам потрібно використовувати сповіщення про клавіатуру:
Сповіщення про клавіатуру
Коли система показує або приховує клавіатуру, вона розміщує кілька сповіщень на клавіатурі. Ці сповіщення містять інформацію про клавіатуру, включаючи її розмір, яку ви можете використовувати для розрахунків, що передбачають переміщення подань. Реєстрація для цих сповіщень - єдиний спосіб отримати деякі типи інформації про клавіатуру. Система доставляє такі сповіщення про події, пов’язані з клавіатурою:
* UIKeyboardWillShowNotification * UIKeyboardDidShowNotification * UIKeyboardWillHideNotification * UIKeyboardDidHideNotification
Для отримання додаткової інформації про ці сповіщення див. Їх описи в довідці про клас UIWindow. Для отримання інформації про те, як відобразити та приховати клавіатуру, див. Текст та Інтернет.
Швидке виконання 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 змінить їх основну реалізацію, всі ці відповіді будуть порушені.
Правильним способом було б відстежувати показ клавіатури та приховувати додатки для сповіщень, наприклад, всередині вашого делегата додатків:
В 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 або зовнішню клавіатуру.
Додати розширення
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")
}
guard let keyboardWindowClass = NSClassFromString("UIRemoteKeyboardWindow") else { return false }; return UIApplication.shared.windows.contains(where: { $0.isKind(of: keyboardWindowClass) })
Це з посібника з програмування тексту iOS, опублікованого компанією Apple тут: https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
В основному зателефонуйте "registerForKeyBoardNotifications" у своїй ViewDidLoad. Потім кожного разу, коли клавіатура стає активною, викликається "клавіатураWasShown". І кожного разу, коли клавіатура зникає, викликається "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 гарантує, що клас ініціалізується один раз безпечним потоком, а статична змінна не видно зовні. І це стандартний 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;
, встановлену в notiShowKeyboard: метод таким:
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];
Якщо користувач обертає екран, поки клавіатура видна, додатку буде сказано, що клавіатура прихована, а потім знову показана. Коли це відображається, інші види, швидше за все, ще не повернені. Тож якщо ви самі спостерігаєте за захованням / показом подій на клавіатурі, конвертуйте координати, коли вони вам справді потрібні, а не в повідомленні.
Якщо користувач розбиває або скасовує клавіатуру або використовує апаратну клавіатуру, сповіщення завжди відображатимуть клавіатуру як приховану. Якщо розблокувати або об'єднати клавіатуру, буде надіслано сповіщення "показано клавіатурою".
Слухач повинен бути ініціалізований, коли клавіатура прихована, інакше перше повідомлення буде пропущено, і вважатиметься, що клавіатура прихована, коли її немає.
Тому досить важливо знати, чого ви насправді хочете. Цей код корисний для того, щоб висувати речі з клавіатури (з роз'єднаною або незамкненою клавіатурою, це відповідальність користувача). Це не говорить про те, чи може користувач бачити клавіатуру на екрані (у випадку роздільної клавіатури). Це не говорить про те, чи може користувач вводити текст (наприклад, коли є апаратна клавіатура). Перегляд інших вікон не працює, якщо програма сама створює інші вікна.
Швидка реалізація:
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 не виконує метод завантаження класу при запуску, важливо запустити цю послугу при запуску програми:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
{
...
KeyboardStateListener.shared.start()
}
Це моє рішення, воно інкапсулює все в один статичний метод, і ви можете викликати його куди завгодно, щоб перевірити:
+(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;
}
А ось як це зробити в 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;
}
}
Спробуйте цю функцію
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;
}
BOOL isTxtOpen = [txtfieldObjct isFirstReponder]. Якщо він повертає ТАК, клавіатура активна.
Щоб перевірити, чи з’явилася клавіатура погоди, ми можемо використовувати попередньо визначені сповіщення клавіатури.
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
}
Швидкий 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
}
}
}
Ви можете ітеративно перевірити всі текстові огляди, текстові поля та мітки в підпогляді батьківського подання, щоб побачити, чи є хто-небудь першим відповіддю чимось подібним:
-(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;
}
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
}
}
Я думаю, що це може допомогти вам,
+(BOOL)isKeyBoardInDisplay {
BOOL isExists = NO;
for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) {
if ([[keyboardWindow description] hasPrefix:@"<UITextEffectsWindow"] == YES) {
isExists = YES;
}
}
return isExists;
}
Дякую,
Naveen Shan