İOS uygulamamda klavye görünürlüğü durumunu kontrol etmem gerekiyor.
pseudocode:
if(keyboardIsPresentOnWindow) {
//Do action 1
}
else if (keyboardIsNotPresentOnWindow) {
//Do action 2
}
Bu durumu nasıl kontrol edebilirim?
İOS uygulamamda klavye görünürlüğü durumunu kontrol etmem gerekiyor.
pseudocode:
if(keyboardIsPresentOnWindow) {
//Do action 1
}
else if (keyboardIsNotPresentOnWindow) {
//Do action 2
}
Bu durumu nasıl kontrol edebilirim?
Yanıtlar:
… Veya kolay yoldan gidin:
Bir textField girdiğinizde, ilk yanıt veren olur ve klavye görünür. İle klavyenin durumunu kontrol edebilirsiniz [myTextField isFirstResponder]. Dönerse YES, klavye etkindir.
drawonward'ın kodu çok yakındır, ancak UIKit'in ad alanıyla çakışır ve kullanımı daha kolay hale getirilebilir.
@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
+loadObjective-C çalışma zamanı tarafından çağrılan özel bir yöntemdir. Her sınıf için uygulama ikili yüklendikten sonra, ancak main()fonksiyon girilmeden önce çağrılır . Otomatik yayın havuzunun aktif olacağına dair bir garanti yoktur.
NSAutoreleasePool alloc/ releaseşimdi kodunu çevreleyen ile değiştirilebilir@autoreleasepool { }
Bir oluşturun UIKeyboardListenerKlavye arayarak örneğin görünmüyorsa bile bile [UIKeyboardListener shared]gelen 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)loadBu dinleyici sınıfında init'i çağırmak için kullanabilirsiniz , böylece herhangi bir projeye sürükle ve bırak işlevi görür ve onu herhangi bir yerde başlatmayı hatırlamanız yerine ikinci uygulama başlatmalarından başlar.
Klavye ile ilgili verilen bildirimleri kullanmanız gerektiğini düşünüyorum:
Klavye Bildirimleri
Sistem klavyeyi gösterdiğinde veya gizlediğinde, birkaç klavye bildirimi yayınlar. Bu bildirimler, klavye hakkında boyutu da dahil olmak üzere, hareketli görünümleri içeren hesaplamalar için kullanabileceğiniz bilgiler içerir. Bu bildirimlere kaydolmak, klavye hakkında bazı bilgi türlerini almanın tek yoludur. Sistem, klavye ile ilgili olaylar için aşağıdaki bildirimleri sunar:
* UIKeyboardWillShowNotification * UIKeyboardDidShowNotification * UIKeyboardWillHideNotification * UIKeyboardDidHideNotificationBu bildirimler hakkında daha fazla bilgi için, UIWindow Sınıf Başvurusu içindeki açıklamalarına bakın. Klavyenin nasıl gösterileceği ve gizleneceği hakkında bilgi için bkz. Metin ve Web.
Swift 3 Uygulaması
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
}
}
Pencere alt görünüm hiyerarşisini klavye gösteriminin göstergesi olarak kullanmak bir hack'tir. Apple, temeldeki uygulamasını değiştirirse, tüm bu yanıtlar kırılır.
Doğru yol, Klavye gösterisini izlemek ve Uygulama Temsilciniz gibi uygulama genelinde bildirimleri gizlemektir:
AppDelegate.h'de:
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (assign, nonatomic) BOOL keyboardIsShowing;
@end
AppDelegate.m'de:
- (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;
}
Ardından şunları kullanarak kontrol edebilirsiniz:
BOOL keyboardIsShowing = ((AppDelegate*)[UIApplication sharedApplication].delegate).keyboardIsShowing;
Kullanıcı bir bluetooth veya harici klavye kullanırken klavye göster / gizle bildirimlerinin çalışmayacağına dikkat edilmelidir.
Bir uzantı ekleyin
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
}
}
}
Ardından klavyenin mevcut olup olmadığını kontrol edin,
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) })
Bu, Apple tarafından burada yayınlanan iOS Metin Programlama Kılavuzundan alınmıştır: https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
Temel olarak ViewDidLoad'unuzda "registerForKeyBoardNotifications" çağırın. Daha sonra klavye her etkin olduğunda "keyboardWasShown" çağrılır. Ve klavye her kaybolduğunda, "keyboardWillBeHidden" çağrılır.
// 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;
}
Şimdi iOS8'de bu çözüm elbette çalışmıyor. Başlangıçta IOS4 / 5 için yazılmıştır.
Bu çözümü deneyin:
- (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;
}
Birkaç gözlem:
Tekil nesne için önerilen model aşağıdaki gibi olacaktır. dispatch_once, sınıfın bir kez iş parçacığı güvenli bir şekilde başlatıldığından ve statik değişkenin dışarıda görünmediğinden emin olur. Ve bu standart GCD'dir, bu nedenle Objective-C'nin düşük seviyeli ayrıntılarını bilmenize gerek yoktur.
+ (KeyboardStateListener *)sharedInstance
{
static KeyboardStateListener* shared;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[KeyboardStateListener alloc] init];
// Other initialisations
});
return shared;
}
Genellikle klavyenin görünür olup olmadığını değil, ne kadar büyük olduğunu bilmek istemezsiniz. Klavyelerin hepsi aynı boyutta değil. iPhone klavyeleri, iPad klavyelerinden daha küçüktür. Bu nedenle @property (readonly, nonatomic) CGRect keyboardRect;, noticeShowKeyboard: yönteminde şu şekilde ayarlanan başka bir özellik istersiniz:
NSValue* value = notification.userInfo [UIKeyboardFrameEndUserInfoKey];
_keyboardRect = value.CGRectValue;
Dikdörtgenin UIWindow koordinatlarında olduğuna ve ekran dönüşüne uymadığına dikkat etmek önemlidir. Böylece arayan, bu dikdörtgeni arayarak dönüştürür.
KeyboardStateListener* listener = [KeyboardStateListener sharedInstance];
CGRect windowRect = listener.keyboardRect;
CGRect viewRect = [myView convertRect:windowRect fromView:self.window];
Kullanıcı klavye görünür durumdayken ekranı döndürürse, uygulamaya klavyenin gizli olduğu söylenecek ve ardından tekrar gösterilecektir. Gösterildiğinde, diğer görünümler büyük olasılıkla henüz döndürülmemiştir. Dolayısıyla, klavye gizleme / gösterme olaylarını kendiniz gözlemlerseniz, koordinatları bildirimde değil, gerçekten ihtiyacınız olduğunda dönüştürün.
Kullanıcı klavyeyi böler veya çıkarırsa veya bir donanım klavyesi kullanırsa, bildirimler her zaman klavyeyi gizli olarak gösterir. Klavyeyi sökmek veya birleştirmek, bir "klavye gösterildi" bildirimi gönderecektir.
Dinleyici, klavye gizliyken başlatılmalıdır, aksi takdirde ilk bildirim kaçırılır ve klavyenin gizli olduğu varsayılır.
Bu yüzden gerçekte ne istediğinizi bilmek oldukça önemlidir. Bu kod, nesneleri klavyenin yolundan çıkarmak için kullanışlıdır (bölünmüş veya kilitlenmemiş klavye ile bu kullanıcının sorumluluğundadır). Kullanıcının ekranda bir klavye görüp görmediğini size söylemez (bölünmüş klavye olması durumunda). Size kullanıcının yazıp yazamayacağını söylemez (örneğin bir donanım klavyesi olduğunda). Uygulama başka pencereleri oluşturuyorsa diğer pencerelere bakmak işe yaramaz.
Hızlı uygulama:
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, başlangıçta sınıf yükleme yöntemini yürütmediğinden, bu hizmeti uygulama başlatıldığında başlatmak önemlidir:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
{
...
KeyboardStateListener.shared.start()
}
Bu benim çözümüm, her şeyi tek bir statik yöntemde kapsıyor ve kontrol etmek için herhangi bir yerde arayabilirsin:
+(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;
}
Ve işte Swift'de bunu nasıl yapacağınız:
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");
}
Kaydı iptal etmeyi unutmayın:
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self,
name: UIKeyboardDidShowNotification,
object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self,
name: UIKeyboardWillHideNotification,
object: nil)
}
Ve "Geri Dön" düğmesine bastığınızda klavyeyi kapatmak istiyorsanız:
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;
}
}
Bu işlevi deneyin
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]. EVET döndürürse, klavye etkindir.
Hava durumu klavyesinin göründüğünü kontrol etmek için Klavye önceden tanımlanmış bildirimleri kullanabiliriz.
UIKeyboardDidShowNotification, UIKeyboardDidHideNotification
Örneğin, klavye bildirimini dinlemek için aşağıdaki kodu kullanabilirim
// Klavye görünümlerini ve kaybolmalarını dinleyin
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
yöntemlerde bildirim alabilirim
- (void)keyboardDidShow: (NSNotification *) notifyKeyBoardShow{
// key board is closed
}
- (void)keyboardDidHide: (NSNotification *) notifyKeyBoardHide{
// key board is opened
}
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
}
}
}
Aşağıdaki gibi bir şeye sahip ilk yanıt verenlerin olup olmadığını görmek için üst görünümün alt görünümlerindeki tüm metin görünümlerini, metin alanlarını ve etiketleri yinelemeli olarak kontrol edebilirsiniz:
-(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
}
}
Sanırım bu sana yardımcı olabilir
+(BOOL)isKeyBoardInDisplay {
BOOL isExists = NO;
for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) {
if ([[keyboardWindow description] hasPrefix:@"<UITextEffectsWindow"] == YES) {
isExists = YES;
}
}
return isExists;
}
Teşekkürler,
Naveen Shan