iOS: How to access the `UIKeyboard`?

后端 未结 6 901
执念已碎
执念已碎 2020-12-06 07:31

I want to get a pointer reference to UIKeyboard *keyboard to the keyboard on screen so that I can add a transparent subview to it, covering it completely, to ac

相关标签:
6条回答
  • 2020-12-06 07:48

    I found that developerdoug's answer wasn't working on iOS 7, but by modifying things slightly I managed to get access to what I needed. Here's the code I used:

    -(UIView*)findKeyboard
    {
        UIView *keyboard = nil;
    
        for (UIWindow* window in [UIApplication sharedApplication].windows)
        {
            for (UIView *possibleKeyboard in window.subviews)
            {
                if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"])
                {
                    keyboard = possibleKeyboard;
                    break;
                }
            }
        }
    
        return keyboard;
    }
    

    From what I could make out, in iOS 7 the keyboard is composed of a UIPeripheralHostView containing two subviews: a UIKBInputBackdropView (which provides the blur effect on whatever's underneath the keyboard) and a UIKeyboardAutomatic (which provides the character keys). Manipulating the UIPeripheralHostView seems to be equivalent to manipulating the entire keyboard.

    Discaimer: I have no idea whether Apple will accept an app that uses this technique, nor whether it will still work in future SDKs.

    0 讨论(0)
  • 2020-12-06 07:51

    Be aware, Apple has made it clear that applications which modify private view hierarchies without explicit approval beforehand will be rejected. Take a look in the Apple Developer Forums for various developers' experience on the issue.

    If you're just trying to disable the keyboard (prevent it from receiving touches), you might try adding a transparent UIView that is the full size of the screen for the current orientation. If you add it as a subview of the main window, it might work. Apple hasn't made any public method of disabling the keyboard that I'm aware of - you might want to use one of your support incidents with Apple, maybe they will let you in on the solution.

    0 讨论(0)
  • 2020-12-06 07:53

    Under iOS 8 it appears you have to jump down the chain more than in the past. The following works for me to get the keyboard, although with custom keyboards available and such I wouldn't rely on this working unless you're running in a controlled environment.

    - (UIView *)findKeyboard {
        for (UIWindow* window in [UIApplication sharedApplication].windows) {
            UIView *inputSetContainer = [self viewWithPrefix:@"<UIInputSetContainerView" inView:window];
            if (inputSetContainer) {
                UIView *inputSetHost = [self viewWithPrefix:@"<UIInputSetHostView" inView:inputSetContainer];
                if (inputSetHost) {
                    UIView *kbinputbackdrop = [self viewWithPrefix:@"<_UIKBCompatInput" inView:inputSetHost];
                    if (kbinputbackdrop) {
                        UIView *theKeyboard = [self viewWithPrefix:@"<UIKeyboard" inView:kbinputbackdrop];
                        return theKeyboard;
                    }
                }
            }
        }
    
        return nil;
    }
    
    
    - (UIView *)viewWithPrefix:(NSString *)prefix inView:(UIView *)view {
        for (UIView *subview in view.subviews) {
            if ([[subview description] hasPrefix:prefix]) {
                return subview;
            }
        }
    
        return nil;
    }
    
    0 讨论(0)
  • 2020-12-06 07:56

    How about using -[UIApplication beginIgnoringInteractionEvents]?

    Also, another trick to get the view containing the keyboard is to initialize a dummy view with CGRectZero and set it as the inputAccessoryView of your UITextField or UITextView. Then, get its superview. Still, such shenanigans is private/undocumented, but I've heard of apps doing that and getting accepted anyhow. I mean, how else would Instagram be able to make their comment keyboard interactive (dismiss on swipe) like the Messages keyboard?

    0 讨论(0)
  • 2020-12-06 07:58

    For an app I am currently developing I am using a really quick and easy method:

    Add this in the header file:

    // Add in interface
    UIWindow * _window;
    
    // Add as property
    @property (strong, nonatomic) IBOutlet UIView * _keyboard;
    

    Then add this code in the bottom of the keyboardWillShow function:

    -(void) keyboardWillShow: (NSNotification *) notification {
    
        .... // other keyboard will show code //
    
        _window = [UIApplication sharedApplication].windows.lastObject;
    
        [NSTimer scheduledTimerWithTimeInterval:0.05
                                         target:self
                                       selector:@selector(allocateKeyboard)
                                       userInfo:nil
                                        repeats:NO];
    }
    

    This code look for when the keyboard is raised and then allocates the current window. I have then added a timer to allocate the keyboard as there were some issues when allocated immediately.

    - (void)allocateKeyboard {
    
        if (!_keyboard) {
            if (_window.subviews.count) {
    
                // The keyboard is always the 0th subview
                _keyboard = _window.subviews[0];
            }        
        }
    }
    

    We now have the keyboard allocated which gives you direct "access" to the keyboard as the question asks.

    Hope this helps

    0 讨论(0)
  • 2020-12-06 08:07

    Try this:

    // my func
    - (void) findKeyboard {
    
        // Locate non-UIWindow.
        UIWindow *keyboardWindow = nil;
        for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
            if (![[testWindow class] isEqual:[UIWindow class]]) {
               keyboardWindow = testWindow;
               break;
           }
        }
    
        // Locate UIKeyboard.  
        UIView *foundKeyboard = nil;
        for (UIView *possibleKeyboard in [keyboardWindow subviews]) {
    
            // iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
            if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) {
                possibleKeyboard = [[possibleKeyboard subviews] objectAtIndex:0];
            }                                                                                
    
            if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) {
               foundKeyboard = possibleKeyboard;
               break;
            }
        }
    }   
    
    0 讨论(0)
提交回复
热议问题