可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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 achieve the effect of disabling the UIKeyboard
without hiding it.
In doing this, can I assume that there's only one UIKeyboard
on the screen at a time? I.e., is it a singleton? Where's the method [UIKeyboard sharedInstance]
. Brownie points if you implement that method via a category. Or, even more brownie points if you convince me why it's a bad idea to assume only one keyboard and give me a better solution.
回答1:
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;
}
}
}
回答2:
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?
回答3:
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.
回答4:
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.
回答5:
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
回答6:
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;
}