ฉันจะตรวจสอบโดยทางโปรแกรมได้อย่างไรว่ามีแป้นพิมพ์อยู่ในแอป iOS หรือไม่


111

ฉันต้องการตรวจสอบสภาพการมองเห็นแป้นพิมพ์ในแอป iOS ของฉัน

รหัสเทียม:

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

ฉันจะตรวจสอบเงื่อนไขนี้ได้อย่างไร?


แอพอะไร? ภาษาอะไร? แพลตฟอร์มอะไร ฉันเดาได้ดีที่สุดคือ iPhone?
Nick Bedford

4
คำถามได้รับการแก้ไข เริ่มเกมกันเลย!
Robert Harvey

บางทีนี่
Peter Wong

คำตอบ:


68

... หรือใช้วิธีง่ายๆ:

เมื่อคุณป้อน textField จะเป็นตัวตอบกลับก่อนและแป้นพิมพ์จะปรากฏขึ้น [myTextField isFirstResponder]คุณสามารถตรวจสอบสถานะของแป้นพิมพ์ที่มี หากกลับYESมาแสดงว่าแป้นพิมพ์ทำงานอยู่


21
วิธีแก้ปัญหาที่ดีอย่างไรก็ตามจะไม่ได้ผลหากใช้แป้นพิมพ์ฮาร์ดแวร์ (ไม่ใช่เรื่องผิดปกติบน iPad)
Andrei Herford

4
สิ่งนี้ไม่ตอบคำถาม สิ่งนี้จะบอกคุณว่าช่องข้อความเป็นตัวตอบแรกหรือไม่ ฉันมีตัวควบคุมมุมมองที่มีตัวควบคุมมุมมองเด็กหลายตัวซึ่งทั้งหมดนี้มี UITextFields เมื่อใช้วิธีนี้ฉันไม่สามารถบอกได้จากตัวควบคุมมุมมองหลักของฉันว่าแป้นพิมพ์แสดงอยู่หรือไม่ วิธีเดียวที่เชื่อถือได้คือใช้วิธีการแจ้งเตือนที่อธิบายไว้ในคำตอบอื่น ๆ
TimWhiting

63

รหัสของ 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

4
ทำไมต้องมีสระว่ายน้ำของตัวเอง?
Dan Rosenstark

18
+loadเป็นวิธีการพิเศษที่เรียกโดยรันไทม์ Objective-C มันถูกเรียกสำหรับแต่ละคลาสหลังจากโหลดไบนารีของแอป แต่ก่อนที่main()จะป้อนฟังก์ชัน ไม่มีการรับประกันว่าพูลการเปิดตัวอัตโนมัติจะพร้อมใช้งาน
rpetrich

1
MattDiPasquale: หากลบเมธอด + load แล้ว sharedInstance จะไม่ถูกเตรียมใช้งาน เนื่องจากไม่มีการรับประกันว่ากลุ่มการปล่อยอัตโนมัติจะแอ็คทีฟเมื่อรันไทม์เรียกใช้เมธอด + โหลดดังนั้นจึงจำเป็นต้องตัดการเรียกทั้งหมดไปยังคลาสที่ระบบจัดเตรียมไว้ในกรณีที่เรียกการปล่อยอัตโนมัติ
rpetrich

3
คำตอบที่ดี! ฉันรู้ว่านี่เป็นเวลาหลายปีแล้ว แต่ตอนนี้NSAutoreleasePool alloc/ releaseสามารถแทนที่ด้วยรหัสรอบ ๆ ใน@autoreleasepool { }
chown

3
อย่าลืมเอา Observer ออกอาจอยู่ใน dealloc ของ KeyboardStateListener
SushiGrass Jacob

32

สร้าง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 ในคลาสผู้ฟังนี้เพื่อให้มันทำงานโดยทั่วไปเป็นการลากแล้ววางในโปรเจ็กต์ใด ๆ และเริ่มต้นจากการเปิดแอพที่สองแทนที่จะต้องจำว่าจะเริ่มต้นที่ใดก็ได้
Albert Renshaw

30

ฉันคิดว่าคุณต้องใช้การแจ้งเตือนที่มีให้เกี่ยวกับแป้นพิมพ์:

จาก: http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UITextField_Class/Reference/UITextField.html

การแจ้งเตือนแป้นพิมพ์

เมื่อระบบแสดงหรือซ่อนแป้นพิมพ์ระบบจะโพสต์การแจ้งเตือนแป้นพิมพ์หลายรายการ การแจ้งเตือนเหล่านี้มีข้อมูลเกี่ยวกับแป้นพิมพ์รวมถึงขนาดซึ่งคุณสามารถใช้สำหรับการคำนวณที่เกี่ยวข้องกับการย้ายมุมมอง การลงทะเบียนสำหรับการแจ้งเตือนเหล่านี้เป็นวิธีเดียวในการรับข้อมูลบางประเภทเกี่ยวกับแป้นพิมพ์ ระบบส่งการแจ้งเตือนต่อไปนี้สำหรับเหตุการณ์ที่เกี่ยวข้องกับแป้นพิมพ์:

* UIKeyboardWillShowNotification
* UIKeyboardDidShowNotification
* UIKeyboardWillHideNotification
* UIKeyboardDidHideNotification

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการแจ้งเตือนเหล่านี้โปรดดูคำอธิบายในการอ้างอิงคลาส UIWindow สำหรับข้อมูลเกี่ยวกับวิธีแสดงและซ่อนแป้นพิมพ์โปรดดูข้อความและเว็บ


ฉันตรวจสอบการแจ้งเตือนเหล่านี้แล้ว แต่ไม่รู้วิธีตรวจสอบการแจ้งเตือนเหล่านี้ หากคุณสามารถโพสต์ตัวอย่างได้นั่นจะเป็นประโยชน์มาก
Jitendra Singh

2
ดูที่ NSNotificationCenter คุณจะต้องลงทะเบียนเพื่อรับการแจ้งเตือนที่คุณสนใจอย่าลืมยกเลิกการลงทะเบียนเมื่อแอปพลิเคชันของคุณออก
Thomas Müller

13

การใช้งาน 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
    } 
}

1
ฉันขอแนะนำให้ลบผู้สังเกตการณ์ใน deinit หรือถ้าตัวควบคุมมุมมองในมุมมองจะหายไป
Juan Boero

3
ไม่มีประโยชน์ในการใช้ deinit ถ้านี่เป็นซิงเกิลตันเพราะมันจะไม่มีวัน deinited
Sirens

11

การใช้ลำดับชั้นมุมมองย่อยของหน้าต่างเป็นตัวบ่งชี้สำหรับการแสดงแป้นพิมพ์ถือเป็นการแฮ็ก หาก 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;

ควรสังเกตว่าการแจ้งเตือนการแสดง / ซ่อนแป้นพิมพ์จะไม่เริ่มทำงานเมื่อผู้ใช้ใช้บลูทู ธ หรือแป้นพิมพ์ภายนอก


10

เพิ่มส่วนขยาย

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

Can doguard let keyboardWindowClass = NSClassFromString("UIRemoteKeyboardWindow") else { return false }; return UIApplication.shared.windows.contains(where: { $0.isKind(of: keyboardWindowClass) })
Clay Bridges

5

มาจากคู่มือการเขียนโปรแกรมข้อความ 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;
}

5

ตอนนี้ใน 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;
}

2
ไม่ถูกต้องที่จะถือว่าหน้าต่างหลาย ๆ บานหมายถึงแป้นพิมพ์และแป้นพิมพ์จะเป็นองค์ประกอบที่สองเสมอ
jmah

1
@jmah แน่นอนว่ามันไม่ใช่แนวทางสากล แต่ครอบคลุมกรณีการใช้งานจำนวนมาก การพยายามรับข้อมูลเกี่ยวกับแป้นพิมพ์ใด ๆ ให้ใช้ลำดับชั้นของมุมมองที่เฉพาะเจาะจงเนื่องจาก Apple ไม่มี API ที่เป็นประโยชน์สำหรับกรณีนี้
malex

นี้ไม่ได้ทำงานสิ่งที่ทำงานสำหรับฉันคือการย้ำผ่านมุมมองทั้งหมดและทุก UITextFields หรือ UITextView ตรวจสอบว่าพวกเขาเป็นคนแรกที่ตอบ ... ถ้าใด ๆ ของแล้วกลับแป้นพิมพ์ที่แท้จริงคือมองเห็นได้อย่างอื่นไม่ได้
เอเอ็มดี

4

ข้อสังเกตบางประการ:

รูปแบบที่แนะนำสำหรับอ็อบเจ็กต์ซิงเกิลตันจะเป็นดังนี้ 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;ซึ่งกำหนดไว้ในวิธีการ noticeShowKeyboard: ดังนี้:

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

หากผู้ใช้หมุนหน้าจอในขณะที่มองเห็นแป้นพิมพ์แอปจะแจ้งว่าแป้นพิมพ์ซ่อนอยู่จากนั้นจะแสดงอีกครั้ง เมื่อมีการแสดงมุมมองอื่น ๆ มักจะยังไม่หมุนเวียน ดังนั้นหากคุณสังเกตแป้นพิมพ์ซ่อน / แสดงเหตุการณ์ด้วยตัวเองให้แปลงพิกัดเมื่อคุณต้องการจริงไม่ใช่ในการแจ้งเตือน

หากผู้ใช้แยกหรือปลดล็อกแป้นพิมพ์หรือใช้แป้นพิมพ์ฮาร์ดแวร์การแจ้งเตือนจะแสดงแป้นพิมพ์ที่ซ่อนอยู่เสมอ การปลดล็อกหรือรวมแป้นพิมพ์จะส่งการแจ้งเตือน "แป้นพิมพ์ที่แสดง"

ผู้ฟังต้องได้รับการเริ่มต้นในขณะที่ซ่อนแป้นพิมพ์มิฉะนั้นจะพลาดการแจ้งเตือนครั้งแรกและจะถือว่าแป้นพิมพ์ถูกซ่อนไว้เมื่อไม่ได้ซ่อนแป้นพิมพ์

ดังนั้นจึงเป็นเรื่องสำคัญที่จะต้องรู้ว่าแท้จริงแล้วคุณต้องการอะไร รหัสนี้มีประโยชน์ในการย้ายสิ่งต่างๆออกจากแป้นพิมพ์ (ด้วยแป้นพิมพ์ที่แยกหรือไม่ได้เชื่อมต่อนั่นคือความรับผิดชอบของผู้ใช้) ไม่ได้บอกคุณว่าผู้ใช้สามารถมองเห็นแป้นพิมพ์บนหน้าจอได้หรือไม่ (ในกรณีของแป้นพิมพ์แยก) ไม่ได้บอกคุณว่าผู้ใช้สามารถพิมพ์ได้ (เช่นเมื่อมีแป้นพิมพ์ฮาร์ดแวร์) การมองไปที่หน้าต่างอื่นจะไม่ทำงานหากแอปสร้างหน้าต่างอื่นขึ้นมาเอง


คำเตือนที่ดีเกี่ยวกับแป้นพิมพ์ใน iPad ขอบคุณ!
JOM

3

การใช้งานอย่างรวดเร็ว :

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

เมื่อใช้ iOS 13, swift 5.0 บิตสุดท้ายนี้ดูเหมือนว่าการโหลดคลาสจะไม่จำเป็น?
user3069232

3

นี่คือวิธีแก้ปัญหาของฉันมันรวมทุกอย่างไว้ในวิธีการคงที่เดียวและคุณสามารถเรียกมันได้ทุกที่เพื่อตรวจสอบ:

+(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

และนี่คือวิธีการทำใน 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)
}

และหากคุณต้องการปิดแป้นพิมพ์เมื่อกดปุ่ม "Return":

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

}

1

ลองใช้ฟังก์ชันนี้

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

ในการตรวจสอบแป้นพิมพ์สภาพอากาศปรากฏขึ้นเราสามารถใช้การแจ้งเตือนที่กำหนดไว้ล่วงหน้าของแป้นพิมพ์

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

สวิฟต์ 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
        }
   }
}

ใช้งานได้ดีสำหรับฉัน (Xcode 10.2, Swift4) แค่อยากรู้ว่าทำไมไม่มีใครโหวตเรื่องนี้?
infinity_coding7

ไม่ใช้ไม่ได้ถ้าแป้นพิมพ์ถูกนำเสนอโดยตัวควบคุมมุมมองก่อนหน้านี้
Ricardo

0

คุณสามารถตรวจสอบมุมมองข้อความฟิลด์ข้อความและป้ายกำกับทั้งหมดซ้ำ ๆ ในมุมมองย่อยของมุมมองระดับบนสุดเพื่อดูว่ามีการตอบกลับครั้งแรกหรือไม่โดยมีลักษณะดังนี้

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

จะล้มเหลวหากคุณมีตัวควบคุมมุมมองเด็ก
Ricardo

-1

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

-5

ฉันคิดว่านี่อาจช่วยคุณได้

+(BOOL)isKeyBoardInDisplay  {

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

    return isExists;
}

ขอบคุณ

Naveen Shan


1
บน iOS 6 เท่านั้นยังไม่ปรากฏ! เมื่อแสดงแป้นพิมพ์แล้วหนึ่งครั้งจะหยุดทำงาน
James Laurenstin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.